diff options
Diffstat (limited to 'gfx/angle/src/libANGLE/renderer/gl')
102 files changed, 25630 insertions, 0 deletions
diff --git a/gfx/angle/src/libANGLE/renderer/gl/BlitGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/BlitGL.cpp new file mode 100755 index 000000000..b181822ff --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/BlitGL.cpp @@ -0,0 +1,486 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BlitGL.cpp: Implements the BlitGL class, a helper for blitting textures + +#include "libANGLE/renderer/gl/BlitGL.h" + +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/renderer/gl/formatutilsgl.h" +#include "libANGLE/renderer/gl/FramebufferGL.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/TextureGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" +#include "libANGLE/renderer/gl/WorkaroundsGL.h" + +namespace +{ + +gl::Error CheckCompileStatus(const rx::FunctionsGL *functions, GLuint shader) +{ + GLint compileStatus = GL_FALSE; + functions->getShaderiv(shader, GL_COMPILE_STATUS, &compileStatus); + ASSERT(compileStatus == GL_TRUE); + if (compileStatus == GL_FALSE) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to compile internal blit shader."); + } + + return gl::NoError(); +} + +gl::Error CheckLinkStatus(const rx::FunctionsGL *functions, GLuint program) +{ + GLint linkStatus = GL_FALSE; + functions->getProgramiv(program, GL_LINK_STATUS, &linkStatus); + ASSERT(linkStatus == GL_TRUE); + if (linkStatus == GL_FALSE) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to link internal blit program."); + } + + return gl::NoError(); +} + +} // anonymous namespace + +namespace rx +{ + +BlitGL::BlitGL(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + StateManagerGL *stateManager) + : mFunctions(functions), + mWorkarounds(workarounds), + mStateManager(stateManager), + mBlitProgram(0), + mSourceTextureLocation(-1), + mScaleLocation(-1), + mOffsetLocation(-1), + mScratchFBO(0), + mVAO(0) +{ + for (size_t i = 0; i < ArraySize(mScratchTextures); i++) + { + mScratchTextures[i] = 0; + } + + ASSERT(mFunctions); + ASSERT(mStateManager); +} + +BlitGL::~BlitGL() +{ + if (mBlitProgram != 0) + { + mStateManager->deleteProgram(mBlitProgram); + mBlitProgram = 0; + } + + for (size_t i = 0; i < ArraySize(mScratchTextures); i++) + { + if (mScratchTextures[i] != 0) + { + mStateManager->deleteTexture(mScratchTextures[i]); + mScratchTextures[i] = 0; + } + } + + if (mScratchFBO != 0) + { + mStateManager->deleteFramebuffer(mScratchFBO); + mScratchFBO = 0; + } + + if (mVAO != 0) + { + mStateManager->deleteVertexArray(mVAO); + mVAO = 0; + } +} + +gl::Error BlitGL::copyImageToLUMAWorkaroundTexture(GLuint texture, + GLenum textureType, + GLenum target, + GLenum lumaFormat, + size_t level, + const gl::Rectangle &sourceArea, + GLenum internalFormat, + const gl::Framebuffer *source) +{ + mStateManager->bindTexture(textureType, texture); + + // Allocate the texture memory + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); + mFunctions->texImage2D(target, static_cast<GLint>(level), internalFormat, sourceArea.width, + sourceArea.height, 0, internalFormatInfo.format, + source->getImplementationColorReadType(), nullptr); + + return copySubImageToLUMAWorkaroundTexture(texture, textureType, target, lumaFormat, level, + gl::Offset(0, 0, 0), sourceArea, source); +} + +gl::Error BlitGL::copySubImageToLUMAWorkaroundTexture(GLuint texture, + GLenum textureType, + GLenum target, + GLenum lumaFormat, + size_t level, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) +{ + ANGLE_TRY(initializeResources()); + + // Blit the framebuffer to the first scratch texture + const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source); + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID()); + + nativegl::CopyTexImageImageFormat copyTexImageFormat = nativegl::GetCopyTexImageImageFormat( + mFunctions, mWorkarounds, source->getImplementationColorReadFormat(), + source->getImplementationColorReadType()); + const gl::InternalFormat &internalFormatInfo = + gl::GetInternalFormatInfo(copyTexImageFormat.internalFormat); + + mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]); + mFunctions->copyTexImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat, sourceArea.x, + sourceArea.y, sourceArea.width, sourceArea.height, 0); + + // Set the swizzle of the scratch texture so that the channels sample into the correct emulated + // LUMA channels. + GLint swizzle[4] = { + (lumaFormat == GL_ALPHA) ? GL_ALPHA : GL_RED, + (lumaFormat == GL_LUMINANCE_ALPHA) ? GL_ALPHA : GL_ZERO, GL_ZERO, GL_ZERO, + }; + mFunctions->texParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle); + + // Make a temporary framebuffer using the second scratch texture to render the swizzled result + // to. + mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[1]); + mFunctions->texImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat, sourceArea.width, + sourceArea.height, 0, internalFormatInfo.format, + source->getImplementationColorReadType(), nullptr); + + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO); + mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + mScratchTextures[1], 0); + + // Render to the destination texture, sampling from the scratch texture + mStateManager->setViewport(gl::Rectangle(0, 0, sourceArea.width, sourceArea.height)); + mStateManager->setScissorTestEnabled(false); + mStateManager->setDepthRange(0.0f, 1.0f); + mStateManager->setBlendEnabled(false); + mStateManager->setColorMask(true, true, true, true); + mStateManager->setSampleAlphaToCoverageEnabled(false); + mStateManager->setSampleCoverageEnabled(false); + mStateManager->setDepthTestEnabled(false); + mStateManager->setStencilTestEnabled(false); + mStateManager->setCullFaceEnabled(false); + mStateManager->setPolygonOffsetFillEnabled(false); + mStateManager->setRasterizerDiscardEnabled(false); + mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]); + + setScratchTextureParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST); + setScratchTextureParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST); + mStateManager->activeTexture(0); + mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]); + + mStateManager->useProgram(mBlitProgram); + mFunctions->uniform1i(mSourceTextureLocation, 0); + mFunctions->uniform2f(mScaleLocation, 1.0, 1.0); + mFunctions->uniform2f(mOffsetLocation, 0.0, 0.0); + + mStateManager->bindVertexArray(mVAO, 0); + + mFunctions->drawArrays(GL_TRIANGLES, 0, 3); + + // Copy the swizzled texture to the destination texture + mStateManager->bindTexture(textureType, texture); + mFunctions->copyTexSubImage2D(target, static_cast<GLint>(level), destOffset.x, destOffset.y, 0, + 0, sourceArea.width, sourceArea.height); + + // Finally orphan the scratch textures so they can be GCed by the driver. + orphanScratchTextures(); + + return gl::NoError(); +} + +gl::Error BlitGL::blitColorBufferWithShader(const gl::Framebuffer *source, + const gl::Framebuffer *dest, + const gl::Rectangle &sourceAreaIn, + const gl::Rectangle &destAreaIn, + GLenum filter) +{ + ANGLE_TRY(initializeResources()); + + // Normalize the destination area to have positive width and height because we will use + // glViewport to set it, which doesn't allow negative width or height. + gl::Rectangle sourceArea = sourceAreaIn; + gl::Rectangle destArea = destAreaIn; + if (destArea.width < 0) + { + destArea.x += destArea.width; + destArea.width = -destArea.width; + sourceArea.x += sourceArea.width; + sourceArea.width = -sourceArea.width; + } + if (destArea.height < 0) + { + destArea.y += destArea.height; + destArea.height = -destArea.height; + sourceArea.y += sourceArea.height; + sourceArea.height = -sourceArea.height; + } + + const gl::FramebufferAttachment *readAttachment = source->getReadColorbuffer(); + ASSERT(readAttachment->getSamples() <= 1); + + // Compute the part of the source that will be sampled. + gl::Rectangle inBoundsSource; + { + gl::Extents sourceSize = readAttachment->getSize(); + gl::Rectangle sourceBounds(0, 0, sourceSize.width, sourceSize.height); + gl::ClipRectangle(sourceArea, sourceBounds, &inBoundsSource); + + // Note that inBoundsSource will have lost the orientation information. + ASSERT(inBoundsSource.width >= 0 && inBoundsSource.height >= 0); + + // Early out when the sampled part is empty as the blit will be a noop, + // and it prevents a division by zero in later computations. + if (inBoundsSource.width == 0 || inBoundsSource.height == 0) + { + return gl::NoError(); + } + } + + // The blit will be emulated by getting the source of the blit in a texture and sampling it + // with CLAMP_TO_EDGE. The quad used to draw can trivially compute texture coordinates going + // from (0, 0) to (1, 1). These texture coordinates will need to be transformed to make two + // regions match: + // - The region of the texture representing the source framebuffer region that will be sampled + // - The region of the drawn quad that corresponds to non-clamped blit, this is the same as the + // region of the source rectangle that is inside the source attachment. + // + // These two regions, T (texture) and D (dest) are defined by their offset in texcoord space + // in (0, 1)^2 and their size in texcoord space in (-1, 1)^2. The size can be negative to + // represent the orientation of the blit. + // + // Then if P is the quad texcoord, Q the texcoord inside T, and R the texture texcoord: + // - Q = (P - D.offset) / D.size + // - Q = (R - T.offset) / T.size + // Hence R = (P - D.offset) / D.size * T.size - T.offset + // = P * (T.size / D.size) + (T.offset - D.offset * T.size / D.size) + + GLuint textureId; + gl::Vector2 TOffset; + gl::Vector2 TSize; + + // TODO(cwallez) once texture dirty bits are landed, reuse attached texture instead of using + // CopyTexImage2D + { + textureId = mScratchTextures[0]; + TOffset = gl::Vector2(0.0, 0.0); + TSize = gl::Vector2(1.0, 1.0); + if (sourceArea.width < 0) + { + TOffset.x = 1.0; + TSize.x = -1.0; + } + if (sourceArea.height < 0) + { + TOffset.y = 1.0; + TSize.y = -1.0; + } + + GLenum format = readAttachment->getFormat().info->internalFormat; + const FramebufferGL *sourceGL = GetImplAs<FramebufferGL>(source); + mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceGL->getFramebufferID()); + mStateManager->bindTexture(GL_TEXTURE_2D, textureId); + + mFunctions->copyTexImage2D(GL_TEXTURE_2D, 0, format, inBoundsSource.x, inBoundsSource.y, + inBoundsSource.width, inBoundsSource.height, 0); + } + + // Compute normalized sampled draw quad region + // It is the same as the region of the source rectangle that is in bounds. + gl::Vector2 DOffset; + gl::Vector2 DSize; + { + ASSERT(sourceArea.width != 0 && sourceArea.height != 0); + gl::Rectangle orientedInBounds = inBoundsSource; + if (sourceArea.width < 0) + { + orientedInBounds.x += orientedInBounds.width; + orientedInBounds.width = -orientedInBounds.width; + } + if (sourceArea.height < 0) + { + orientedInBounds.y += orientedInBounds.height; + orientedInBounds.height = -orientedInBounds.height; + } + + DOffset = + gl::Vector2(static_cast<float>(orientedInBounds.x - sourceArea.x) / sourceArea.width, + static_cast<float>(orientedInBounds.y - sourceArea.y) / sourceArea.height); + DSize = gl::Vector2(static_cast<float>(orientedInBounds.width) / sourceArea.width, + static_cast<float>(orientedInBounds.height) / sourceArea.height); + } + + ASSERT(DSize.x != 0.0 && DSize.y != 0.0); + gl::Vector2 texCoordScale = gl::Vector2(TSize.x / DSize.x, TSize.y / DSize.y); + gl::Vector2 texCoordOffset = gl::Vector2(TOffset.x - DOffset.x * texCoordScale.x, + TOffset.y - DOffset.y * texCoordScale.y); + + // Reset all the state except scissor and viewport + mStateManager->setDepthRange(0.0f, 1.0f); + mStateManager->setBlendEnabled(false); + mStateManager->setColorMask(true, true, true, true); + mStateManager->setSampleAlphaToCoverageEnabled(false); + mStateManager->setSampleCoverageEnabled(false); + mStateManager->setDepthTestEnabled(false); + mStateManager->setStencilTestEnabled(false); + mStateManager->setCullFaceEnabled(false); + mStateManager->setPolygonOffsetFillEnabled(false); + mStateManager->setRasterizerDiscardEnabled(false); + + // Use the viewport to draw exactly to the destination rectangle + mStateManager->setViewport(destArea); + + // Set uniforms + setScratchTextureParameter(GL_TEXTURE_MIN_FILTER, filter); + setScratchTextureParameter(GL_TEXTURE_MAG_FILTER, filter); + setScratchTextureParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + setScratchTextureParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + mStateManager->activeTexture(0); + mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]); + + mStateManager->useProgram(mBlitProgram); + mFunctions->uniform1i(mSourceTextureLocation, 0); + mFunctions->uniform2f(mScaleLocation, texCoordScale.x, texCoordScale.y); + mFunctions->uniform2f(mOffsetLocation, texCoordOffset.x, texCoordOffset.y); + + const FramebufferGL *destGL = GetImplAs<FramebufferGL>(dest); + mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, destGL->getFramebufferID()); + + mStateManager->bindVertexArray(mVAO, 0); + mFunctions->drawArrays(GL_TRIANGLES, 0, 3); + + return gl::NoError(); +} + +gl::Error BlitGL::initializeResources() +{ + if (mBlitProgram == 0) + { + mBlitProgram = mFunctions->createProgram(); + + // Compile the fragment shader + // It uses a single, large triangle, to avoid arithmetic precision issues where fragments + // with the same Y coordinate don't get exactly the same interpolated texcoord Y. + const char *vsSource = + "#version 150\n" + "out vec2 v_texcoord;\n" + "uniform vec2 u_scale;\n" + "uniform vec2 u_offset;\n" + "\n" + "void main()\n" + "{\n" + " const vec2 quad_positions[3] = vec2[3]\n" + " (\n" + " vec2(-0.5f, 0.0f),\n" + " vec2( 1.5f, 0.0f),\n" + " vec2( 0.5f, 2.0f)\n" + " );\n" + "\n" + " gl_Position = vec4((quad_positions[gl_VertexID] * 2.0) - 1.0, 0.0, 1.0);\n" + " v_texcoord = quad_positions[gl_VertexID] * u_scale + u_offset;\n" + "}\n"; + + GLuint vs = mFunctions->createShader(GL_VERTEX_SHADER); + mFunctions->shaderSource(vs, 1, &vsSource, nullptr); + mFunctions->compileShader(vs); + ANGLE_TRY(CheckCompileStatus(mFunctions, vs)); + + mFunctions->attachShader(mBlitProgram, vs); + mFunctions->deleteShader(vs); + + // Compile the vertex shader + // It discards if the texcoord is outside (0, 1)^2 so the blitframebuffer workaround + // doesn't write when the point sampled is outside of the source framebuffer. + const char *fsSource = + "#version 150\n" + "uniform sampler2D u_source_texture;\n" + "in vec2 v_texcoord;\n" + "out vec4 output_color;\n" + "\n" + "void main()\n" + "{\n" + " if (clamp(v_texcoord, vec2(0.0), vec2(1.0)) != v_texcoord)\n" + " {\n" + " discard;\n" + " }\n" + " output_color = texture(u_source_texture, v_texcoord);\n" + "}\n"; + + GLuint fs = mFunctions->createShader(GL_FRAGMENT_SHADER); + mFunctions->shaderSource(fs, 1, &fsSource, nullptr); + mFunctions->compileShader(fs); + ANGLE_TRY(CheckCompileStatus(mFunctions, fs)); + + mFunctions->attachShader(mBlitProgram, fs); + mFunctions->deleteShader(fs); + + mFunctions->linkProgram(mBlitProgram); + ANGLE_TRY(CheckLinkStatus(mFunctions, mBlitProgram)); + + mSourceTextureLocation = mFunctions->getUniformLocation(mBlitProgram, "u_source_texture"); + mScaleLocation = mFunctions->getUniformLocation(mBlitProgram, "u_scale"); + mOffsetLocation = mFunctions->getUniformLocation(mBlitProgram, "u_offset"); + mStateManager->useProgram(mBlitProgram); + } + + for (size_t i = 0; i < ArraySize(mScratchTextures); i++) + { + if (mScratchTextures[i] == 0) + { + mFunctions->genTextures(1, &mScratchTextures[i]); + } + } + + if (mScratchFBO == 0) + { + mFunctions->genFramebuffers(1, &mScratchFBO); + } + + if (mVAO == 0) + { + mFunctions->genVertexArrays(1, &mVAO); + } + + return gl::NoError(); +} + +void BlitGL::orphanScratchTextures() +{ + for (auto texture : mScratchTextures) + { + mStateManager->bindTexture(GL_TEXTURE_2D, texture); + mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, + nullptr); + } +} + +void BlitGL::setScratchTextureParameter(GLenum param, GLenum value) +{ + for (auto texture : mScratchTextures) + { + mStateManager->bindTexture(GL_TEXTURE_2D, texture); + mFunctions->texParameteri(GL_TEXTURE_2D, param, value); + mFunctions->texParameteri(GL_TEXTURE_2D, param, value); + } +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/BlitGL.h b/gfx/angle/src/libANGLE/renderer/gl/BlitGL.h new file mode 100755 index 000000000..b306ede29 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/BlitGL.h @@ -0,0 +1,83 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BlitGL.h: Defines the BlitGL class, a helper for blitting textures + +#ifndef LIBANGLE_RENDERER_GL_BLITGL_H_ +#define LIBANGLE_RENDERER_GL_BLITGL_H_ + +#include "angle_gl.h" +#include "common/angleutils.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Error.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ + +class FramebufferGL; +class FunctionsGL; +class StateManagerGL; +struct WorkaroundsGL; + +class BlitGL : public angle::NonCopyable +{ + public: + BlitGL(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + StateManagerGL *stateManager); + ~BlitGL(); + + gl::Error copyImageToLUMAWorkaroundTexture(GLuint texture, + GLenum textureType, + GLenum target, + GLenum lumaFormat, + size_t level, + const gl::Rectangle &sourceArea, + GLenum internalFormat, + const gl::Framebuffer *source); + gl::Error copySubImageToLUMAWorkaroundTexture(GLuint texture, + GLenum textureType, + GLenum target, + GLenum lumaFormat, + size_t level, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source); + + gl::Error blitColorBufferWithShader(const gl::Framebuffer *source, + const gl::Framebuffer *dest, + const gl::Rectangle &sourceArea, + const gl::Rectangle &destArea, + GLenum filter); + + gl::Error initializeResources(); + + private: + void orphanScratchTextures(); + void setScratchTextureParameter(GLenum param, GLenum value); + + const FunctionsGL *mFunctions; + const WorkaroundsGL &mWorkarounds; + StateManagerGL *mStateManager; + + GLuint mBlitProgram; + GLint mSourceTextureLocation; + GLint mScaleLocation; + GLint mOffsetLocation; + + GLuint mScratchTextures[2]; + GLuint mScratchFBO; + + GLuint mVAO; +}; +} + +#endif // LIBANGLE_RENDERER_GL_BLITGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/BufferGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/BufferGL.cpp new file mode 100755 index 000000000..a5eda6b30 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/BufferGL.cpp @@ -0,0 +1,204 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferGL.cpp: Implements the class methods for BufferGL. + +#include "libANGLE/renderer/gl/BufferGL.h" + +#include "common/debug.h" +#include "common/utilities.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" +#include "libANGLE/renderer/gl/renderergl_utils.h" + +namespace rx +{ + +// Use the GL_COPY_READ_BUFFER binding when two buffers need to be bound simultaneously. +// GL_ELEMENT_ARRAY_BUFFER is supported on more versions but can modify the state of the currently +// bound VAO. Two simultaneous buffer bindings are only needed for glCopyBufferSubData which also +// adds the GL_COPY_READ_BUFFER binding. +static const GLenum SourceBufferOperationTarget = GL_COPY_READ_BUFFER; + +// Use the GL_ELEMENT_ARRAY_BUFFER binding for most operations since it's available on all +// supported GL versions and doesn't affect any current state when it changes. +static const GLenum DestBufferOperationTarget = GL_ARRAY_BUFFER; + +BufferGL::BufferGL(const gl::BufferState &state, + const FunctionsGL *functions, + StateManagerGL *stateManager) + : BufferImpl(state), + mIsMapped(false), + mMapOffset(0), + mMapSize(0), + mShadowBufferData(!CanMapBufferForRead(functions)), + mShadowCopy(), + mBufferSize(0), + mFunctions(functions), + mStateManager(stateManager), + mBufferID(0) +{ + ASSERT(mFunctions); + ASSERT(mStateManager); + + mFunctions->genBuffers(1, &mBufferID); +} + +BufferGL::~BufferGL() +{ + mStateManager->deleteBuffer(mBufferID); + mBufferID = 0; +} + +gl::Error BufferGL::setData(GLenum /*target*/, const void *data, size_t size, GLenum usage) +{ + mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID); + mFunctions->bufferData(DestBufferOperationTarget, size, data, usage); + + if (mShadowBufferData) + { + if (!mShadowCopy.resize(size)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize buffer data shadow copy."); + } + + if (size > 0 && data != nullptr) + { + memcpy(mShadowCopy.data(), data, size); + } + } + + mBufferSize = size; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error BufferGL::setSubData(GLenum /*target*/, const void *data, size_t size, size_t offset) +{ + mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID); + mFunctions->bufferSubData(DestBufferOperationTarget, offset, size, data); + + if (mShadowBufferData && size > 0) + { + memcpy(mShadowCopy.data() + offset, data, size); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error BufferGL::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +{ + BufferGL *sourceGL = GetAs<BufferGL>(source); + + mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID); + mStateManager->bindBuffer(SourceBufferOperationTarget, sourceGL->getBufferID()); + + mFunctions->copyBufferSubData(SourceBufferOperationTarget, DestBufferOperationTarget, sourceOffset, destOffset, size); + + if (mShadowBufferData && size > 0) + { + ASSERT(sourceGL->mShadowBufferData); + memcpy(mShadowCopy.data() + destOffset, sourceGL->mShadowCopy.data() + sourceOffset, size); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error BufferGL::map(GLenum access, GLvoid **mapPtr) +{ + if (mShadowBufferData) + { + *mapPtr = mShadowCopy.data(); + } + else + { + mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID); + *mapPtr = mFunctions->mapBuffer(DestBufferOperationTarget, access); + } + + mIsMapped = true; + mMapOffset = 0; + mMapSize = mBufferSize; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error BufferGL::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) +{ + if (mShadowBufferData) + { + *mapPtr = mShadowCopy.data() + offset; + } + else + { + mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID); + *mapPtr = mFunctions->mapBufferRange(DestBufferOperationTarget, offset, length, access); + } + + mIsMapped = true; + mMapOffset = offset; + mMapSize = length; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error BufferGL::unmap(GLboolean *result) +{ + ASSERT(result); + ASSERT(mIsMapped); + + if (mShadowBufferData) + { + mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID); + mFunctions->bufferSubData(DestBufferOperationTarget, mMapOffset, mMapSize, + mShadowCopy.data() + mMapOffset); + *result = GL_TRUE; + } + else + { + mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID); + *result = mFunctions->unmapBuffer(DestBufferOperationTarget); + } + + mIsMapped = false; + return gl::Error(GL_NO_ERROR); +} + +gl::Error BufferGL::getIndexRange(GLenum type, + size_t offset, + size_t count, + bool primitiveRestartEnabled, + gl::IndexRange *outRange) +{ + ASSERT(!mIsMapped); + + if (mShadowBufferData) + { + *outRange = gl::ComputeIndexRange(type, mShadowCopy.data() + offset, count, + primitiveRestartEnabled); + } + else + { + mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID); + + const gl::Type &typeInfo = gl::GetTypeInfo(type); + const uint8_t *bufferData = MapBufferRangeWithFallback( + mFunctions, DestBufferOperationTarget, offset, count * typeInfo.bytes, GL_MAP_READ_BIT); + *outRange = gl::ComputeIndexRange(type, bufferData, count, primitiveRestartEnabled); + mFunctions->unmapBuffer(DestBufferOperationTarget); + } + + return gl::Error(GL_NO_ERROR); +} + +GLuint BufferGL::getBufferID() const +{ + return mBufferID; +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/BufferGL.h b/gfx/angle/src/libANGLE/renderer/gl/BufferGL.h new file mode 100755 index 000000000..d886873fe --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/BufferGL.h @@ -0,0 +1,62 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferGL.h: Defines the class interface for BufferGL. + +#ifndef LIBANGLE_RENDERER_GL_BUFFERGL_H_ +#define LIBANGLE_RENDERER_GL_BUFFERGL_H_ + +#include "common/MemoryBuffer.h" +#include "libANGLE/renderer/BufferImpl.h" + +namespace rx +{ + +class FunctionsGL; +class StateManagerGL; + +class BufferGL : public BufferImpl +{ + public: + BufferGL(const gl::BufferState &state, + const FunctionsGL *functions, + StateManagerGL *stateManager); + ~BufferGL() override; + + gl::Error setData(GLenum target, const void *data, size_t size, GLenum usage) override; + gl::Error setSubData(GLenum target, const void *data, size_t size, size_t offset) override; + gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) override; + gl::Error map(GLenum access, GLvoid **mapPtr) override; + gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) override; + gl::Error unmap(GLboolean *result) override; + + gl::Error getIndexRange(GLenum type, + size_t offset, + size_t count, + bool primitiveRestartEnabled, + gl::IndexRange *outRange) override; + + GLuint getBufferID() const; + + private: + bool mIsMapped; + size_t mMapOffset; + size_t mMapSize; + + bool mShadowBufferData; + MemoryBuffer mShadowCopy; + + size_t mBufferSize; + + const FunctionsGL *mFunctions; + StateManagerGL *mStateManager; + + GLuint mBufferID; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_BUFFERGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/CompilerGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/CompilerGL.cpp new file mode 100755 index 000000000..71be15611 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/CompilerGL.cpp @@ -0,0 +1,91 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// CompilerGL: +// Implementation of the GL compiler methods. +// + +#include "libANGLE/renderer/gl/CompilerGL.h" + +#include "libANGLE/renderer/gl/FunctionsGL.h" + +namespace rx +{ + +namespace +{ + +ShShaderOutput GetShaderOutputType(const FunctionsGL *functions) +{ + ASSERT(functions); + + if (functions->standard == STANDARD_GL_DESKTOP) + { + // GLSL outputs + if (functions->isAtLeastGL(gl::Version(4, 5))) + { + return SH_GLSL_450_CORE_OUTPUT; + } + else if (functions->isAtLeastGL(gl::Version(4, 4))) + { + return SH_GLSL_440_CORE_OUTPUT; + } + else if (functions->isAtLeastGL(gl::Version(4, 3))) + { + return SH_GLSL_430_CORE_OUTPUT; + } + else if (functions->isAtLeastGL(gl::Version(4, 2))) + { + return SH_GLSL_420_CORE_OUTPUT; + } + else if (functions->isAtLeastGL(gl::Version(4, 1))) + { + return SH_GLSL_410_CORE_OUTPUT; + } + else if (functions->isAtLeastGL(gl::Version(4, 0))) + { + return SH_GLSL_400_CORE_OUTPUT; + } + else if (functions->isAtLeastGL(gl::Version(3, 3))) + { + return SH_GLSL_330_CORE_OUTPUT; + } + else if (functions->isAtLeastGL(gl::Version(3, 2))) + { + return SH_GLSL_150_CORE_OUTPUT; + } + else if (functions->isAtLeastGL(gl::Version(3, 1))) + { + return SH_GLSL_140_OUTPUT; + } + else if (functions->isAtLeastGL(gl::Version(3, 0))) + { + return SH_GLSL_130_OUTPUT; + } + else + { + return SH_GLSL_COMPATIBILITY_OUTPUT; + } + } + else if (functions->standard == STANDARD_GL_ES) + { + // ESSL outputs + return SH_ESSL_OUTPUT; + } + else + { + UNREACHABLE(); + return ShShaderOutput(0); + } +} + +} // anonymous namespace + +CompilerGL::CompilerGL(const FunctionsGL *functions) + : mTranslatorOutputType(GetShaderOutputType(functions)) +{ +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/CompilerGL.h b/gfx/angle/src/libANGLE/renderer/gl/CompilerGL.h new file mode 100755 index 000000000..eadbf67ed --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/CompilerGL.h @@ -0,0 +1,33 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// CompilerGL.h: Defines the class interface for CompilerGL. + +#ifndef LIBANGLE_RENDERER_GL_COMPILERGL_H_ +#define LIBANGLE_RENDERER_GL_COMPILERGL_H_ + +#include "libANGLE/renderer/CompilerImpl.h" + +namespace rx +{ +class FunctionsGL; + +class CompilerGL : public CompilerImpl +{ + public: + CompilerGL(const FunctionsGL *functions); + ~CompilerGL() override {} + + gl::Error release() override { return gl::Error(GL_NO_ERROR); } + ShShaderOutput getTranslatorOutputType() const override { return mTranslatorOutputType; } + + private: + ShShaderOutput mTranslatorOutputType; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_COMPILERGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/ContextGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/ContextGL.cpp new file mode 100755 index 000000000..8e378a4be --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/ContextGL.cpp @@ -0,0 +1,370 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ContextGL: +// OpenGL-specific functionality associated with a GL Context. +// + +#include "libANGLE/renderer/gl/ContextGL.h" + +#include "libANGLE/renderer/gl/BufferGL.h" +#include "libANGLE/renderer/gl/CompilerGL.h" +#include "libANGLE/renderer/gl/FenceNVGL.h" +#include "libANGLE/renderer/gl/FenceSyncGL.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/FramebufferGL.h" +#include "libANGLE/renderer/gl/PathGL.h" +#include "libANGLE/renderer/gl/ProgramGL.h" +#include "libANGLE/renderer/gl/QueryGL.h" +#include "libANGLE/renderer/gl/RenderbufferGL.h" +#include "libANGLE/renderer/gl/RendererGL.h" +#include "libANGLE/renderer/gl/SamplerGL.h" +#include "libANGLE/renderer/gl/ShaderGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" +#include "libANGLE/renderer/gl/TextureGL.h" +#include "libANGLE/renderer/gl/TransformFeedbackGL.h" +#include "libANGLE/renderer/gl/VertexArrayGL.h" + +namespace rx +{ + +ContextGL::ContextGL(const gl::ContextState &state, RendererGL *renderer) + : ContextImpl(state), mRenderer(renderer) +{ +} + +ContextGL::~ContextGL() +{ +} + +gl::Error ContextGL::initialize() +{ + return gl::NoError(); +} + +CompilerImpl *ContextGL::createCompiler() +{ + return new CompilerGL(getFunctions()); +} + +ShaderImpl *ContextGL::createShader(const gl::ShaderState &data) +{ + return new ShaderGL(data, getFunctions(), getWorkaroundsGL()); +} + +ProgramImpl *ContextGL::createProgram(const gl::ProgramState &data) +{ + return new ProgramGL(data, getFunctions(), getWorkaroundsGL(), getStateManager(), + getExtensions().pathRendering); +} + +FramebufferImpl *ContextGL::createFramebuffer(const gl::FramebufferState &data) +{ + return new FramebufferGL(data, getFunctions(), getStateManager(), getWorkaroundsGL(), + mRenderer->getBlitter(), false); +} + +TextureImpl *ContextGL::createTexture(const gl::TextureState &state) +{ + return new TextureGL(state, getFunctions(), getWorkaroundsGL(), getStateManager(), + mRenderer->getBlitter()); +} + +RenderbufferImpl *ContextGL::createRenderbuffer() +{ + return new RenderbufferGL(getFunctions(), getWorkaroundsGL(), getStateManager(), + getNativeTextureCaps()); +} + +BufferImpl *ContextGL::createBuffer(const gl::BufferState &state) +{ + return new BufferGL(state, getFunctions(), getStateManager()); +} + +VertexArrayImpl *ContextGL::createVertexArray(const gl::VertexArrayState &data) +{ + return new VertexArrayGL(data, getFunctions(), getStateManager()); +} + +QueryImpl *ContextGL::createQuery(GLenum type) +{ + return new QueryGL(type, getFunctions(), getStateManager()); +} + +FenceNVImpl *ContextGL::createFenceNV() +{ + return new FenceNVGL(getFunctions()); +} + +FenceSyncImpl *ContextGL::createFenceSync() +{ + return new FenceSyncGL(getFunctions()); +} + +TransformFeedbackImpl *ContextGL::createTransformFeedback(const gl::TransformFeedbackState &state) +{ + return new TransformFeedbackGL(state, getFunctions(), getStateManager()); +} + +SamplerImpl *ContextGL::createSampler() +{ + return new SamplerGL(getFunctions(), getStateManager()); +} + +std::vector<PathImpl *> ContextGL::createPaths(GLsizei range) +{ + const FunctionsGL *funcs = getFunctions(); + + std::vector<PathImpl *> ret; + ret.reserve(range); + + const GLuint first = funcs->genPathsNV(range); + if (first == 0) + return ret; + + for (GLsizei i = 0; i < range; ++i) + { + const auto id = first + i; + ret.push_back(new PathGL(funcs, id)); + } + + return ret; +} + +gl::Error ContextGL::flush() +{ + return mRenderer->flush(); +} + +gl::Error ContextGL::finish() +{ + return mRenderer->finish(); +} + +gl::Error ContextGL::drawArrays(GLenum mode, GLint first, GLsizei count) +{ + return mRenderer->drawArrays(mState, mode, first, count); +} + +gl::Error ContextGL::drawArraysInstanced(GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount) +{ + return mRenderer->drawArraysInstanced(mState, mode, first, count, instanceCount); +} + +gl::Error ContextGL::drawElements(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) +{ + return mRenderer->drawElements(mState, mode, count, type, indices, indexRange); +} + +gl::Error ContextGL::drawElementsInstanced(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange) +{ + return mRenderer->drawElementsInstanced(mState, mode, count, type, indices, instances, + indexRange); +} + +gl::Error ContextGL::drawRangeElements(GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) +{ + return mRenderer->drawRangeElements(mState, mode, start, end, count, type, indices, indexRange); +} + +void ContextGL::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask) +{ + mRenderer->stencilFillPath(mState, path, fillMode, mask); +} + +void ContextGL::stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask) +{ + mRenderer->stencilStrokePath(mState, path, reference, mask); +} + +void ContextGL::coverFillPath(const gl::Path *path, GLenum coverMode) +{ + mRenderer->coverFillPath(mState, path, coverMode); +} + +void ContextGL::coverStrokePath(const gl::Path *path, GLenum coverMode) +{ + mRenderer->coverStrokePath(mState, path, coverMode); +} + +void ContextGL::stencilThenCoverFillPath(const gl::Path *path, + GLenum fillMode, + GLuint mask, + GLenum coverMode) +{ + mRenderer->stencilThenCoverFillPath(mState, path, fillMode, mask, coverMode); +} + +void ContextGL::stencilThenCoverStrokePath(const gl::Path *path, + GLint reference, + GLuint mask, + GLenum coverMode) +{ + mRenderer->stencilThenCoverStrokePath(mState, path, reference, mask, coverMode); +} + +void ContextGL::coverFillPathInstanced(const std::vector<gl::Path *> &paths, + GLenum coverMode, + GLenum transformType, + const GLfloat *transformValues) +{ + mRenderer->coverFillPathInstanced(mState, paths, coverMode, transformType, transformValues); +} + +void ContextGL::coverStrokePathInstanced(const std::vector<gl::Path *> &paths, + GLenum coverMode, + GLenum transformType, + const GLfloat *transformValues) +{ + mRenderer->coverStrokePathInstanced(mState, paths, coverMode, transformType, transformValues); +} + +void ContextGL::stencilFillPathInstanced(const std::vector<gl::Path *> &paths, + GLenum fillMode, + GLuint mask, + GLenum transformType, + const GLfloat *transformValues) +{ + mRenderer->stencilFillPathInstanced(mState, paths, fillMode, mask, transformType, + transformValues); +} + +void ContextGL::stencilStrokePathInstanced(const std::vector<gl::Path *> &paths, + GLint reference, + GLuint mask, + GLenum transformType, + const GLfloat *transformValues) +{ + mRenderer->stencilStrokePathInstanced(mState, paths, reference, mask, transformType, + transformValues); +} + +void ContextGL::stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths, + GLenum coverMode, + GLenum fillMode, + GLuint mask, + GLenum transformType, + const GLfloat *transformValues) +{ + mRenderer->stencilThenCoverFillPathInstanced(mState, paths, coverMode, fillMode, mask, + transformType, transformValues); +} + +void ContextGL::stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths, + GLenum coverMode, + GLint reference, + GLuint mask, + GLenum transformType, + const GLfloat *transformValues) +{ + mRenderer->stencilThenCoverStrokePathInstanced(mState, paths, coverMode, reference, mask, + transformType, transformValues); +} + +GLenum ContextGL::getResetStatus() +{ + return mRenderer->getResetStatus(); +} + +std::string ContextGL::getVendorString() const +{ + return mRenderer->getVendorString(); +} + +std::string ContextGL::getRendererDescription() const +{ + return mRenderer->getRendererDescription(); +} + +void ContextGL::insertEventMarker(GLsizei length, const char *marker) +{ + mRenderer->insertEventMarker(length, marker); +} + +void ContextGL::pushGroupMarker(GLsizei length, const char *marker) +{ + mRenderer->pushGroupMarker(length, marker); +} + +void ContextGL::popGroupMarker() +{ + mRenderer->popGroupMarker(); +} + +void ContextGL::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) +{ + mRenderer->getStateManager()->syncState(state, dirtyBits); +} + +GLint ContextGL::getGPUDisjoint() +{ + return mRenderer->getGPUDisjoint(); +} + +GLint64 ContextGL::getTimestamp() +{ + return mRenderer->getTimestamp(); +} + +void ContextGL::onMakeCurrent(const gl::ContextState &data) +{ + // Queries need to be paused/resumed on context switches + mRenderer->getStateManager()->onMakeCurrent(data); +} + +const gl::Caps &ContextGL::getNativeCaps() const +{ + return mRenderer->getNativeCaps(); +} + +const gl::TextureCapsMap &ContextGL::getNativeTextureCaps() const +{ + return mRenderer->getNativeTextureCaps(); +} + +const gl::Extensions &ContextGL::getNativeExtensions() const +{ + return mRenderer->getNativeExtensions(); +} + +const gl::Limitations &ContextGL::getNativeLimitations() const +{ + return mRenderer->getNativeLimitations(); +} + +const FunctionsGL *ContextGL::getFunctions() const +{ + return mRenderer->getFunctions(); +} + +StateManagerGL *ContextGL::getStateManager() +{ + return mRenderer->getStateManager(); +} + +const WorkaroundsGL &ContextGL::getWorkaroundsGL() +{ + return mRenderer->getWorkarounds(); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/ContextGL.h b/gfx/angle/src/libANGLE/renderer/gl/ContextGL.h new file mode 100755 index 000000000..b3d5e0ee8 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/ContextGL.h @@ -0,0 +1,183 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ContextGL: +// OpenGL-specific functionality associated with a GL Context. +// + +#ifndef LIBANGLE_RENDERER_GL_CONTEXTGL_H_ +#define LIBANGLE_RENDERER_GL_CONTEXTGL_H_ + +#include "libANGLE/renderer/ContextImpl.h" + +namespace sh +{ +struct BlockMemberInfo; +} + +namespace rx +{ +class FunctionsGL; +class RendererGL; +class StateManagerGL; +struct WorkaroundsGL; + +class ContextGL : public ContextImpl +{ + public: + ContextGL(const gl::ContextState &state, RendererGL *renderer); + ~ContextGL() override; + + gl::Error initialize() override; + + // Shader creation + CompilerImpl *createCompiler() override; + ShaderImpl *createShader(const gl::ShaderState &data) override; + ProgramImpl *createProgram(const gl::ProgramState &data) override; + + // Framebuffer creation + FramebufferImpl *createFramebuffer(const gl::FramebufferState &data) override; + + // Texture creation + TextureImpl *createTexture(const gl::TextureState &state) override; + + // Renderbuffer creation + RenderbufferImpl *createRenderbuffer() override; + + // Buffer creation + BufferImpl *createBuffer(const gl::BufferState &state) override; + + // Vertex Array creation + VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override; + + // Query and Fence creation + QueryImpl *createQuery(GLenum type) override; + FenceNVImpl *createFenceNV() override; + FenceSyncImpl *createFenceSync() override; + + // Transform Feedback creation + TransformFeedbackImpl *createTransformFeedback( + const gl::TransformFeedbackState &state) override; + + // Sampler object creation + SamplerImpl *createSampler() override; + + // Path object creation + std::vector<PathImpl *> createPaths(GLsizei range) override; + + // Flush and finish. + gl::Error flush() override; + gl::Error finish() override; + + // Drawing methods. + gl::Error drawArrays(GLenum mode, GLint first, GLsizei count) override; + gl::Error drawArraysInstanced(GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount) override; + + gl::Error drawElements(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) override; + gl::Error drawElementsInstanced(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange) override; + gl::Error drawRangeElements(GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) override; + + // CHROMIUM_path_rendering implementation + void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask) override; + void stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask) override; + void coverFillPath(const gl::Path *path, GLenum coverMode) override; + void coverStrokePath(const gl::Path *path, GLenum coverMode) override; + void stencilThenCoverFillPath(const gl::Path *path, + GLenum fillMode, + GLuint mask, + GLenum coverMode) override; + void stencilThenCoverStrokePath(const gl::Path *path, + GLint reference, + GLuint mask, + GLenum coverMode) override; + void coverFillPathInstanced(const std::vector<gl::Path *> &paths, + GLenum coverMode, + GLenum transformType, + const GLfloat *transformValues) override; + void coverStrokePathInstanced(const std::vector<gl::Path *> &paths, + GLenum coverMode, + GLenum transformType, + const GLfloat *transformValues) override; + void stencilFillPathInstanced(const std::vector<gl::Path *> &paths, + GLenum fillMode, + GLuint mask, + GLenum transformType, + const GLfloat *transformValues) override; + void stencilStrokePathInstanced(const std::vector<gl::Path *> &paths, + GLint reference, + GLuint mask, + GLenum transformType, + const GLfloat *transformValues) override; + void stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths, + GLenum coverMode, + GLenum fillMode, + GLuint mask, + GLenum transformType, + const GLfloat *transformValues) override; + void stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths, + GLenum coverMode, + GLint reference, + GLuint mask, + GLenum transformType, + const GLfloat *transformValues) override; + + // Device loss + GLenum getResetStatus() override; + + // Vendor and description strings. + std::string getVendorString() const override; + std::string getRendererDescription() const override; + + // Debug markers. + void insertEventMarker(GLsizei length, const char *marker) override; + void pushGroupMarker(GLsizei length, const char *marker) override; + void popGroupMarker() override; + + // State sync with dirty bits. + void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) override; + + // Disjoint timer queries + GLint getGPUDisjoint() override; + GLint64 getTimestamp() override; + + // Context switching + void onMakeCurrent(const gl::ContextState &data) override; + + // Caps queries + const gl::Caps &getNativeCaps() const override; + const gl::TextureCapsMap &getNativeTextureCaps() const override; + const gl::Extensions &getNativeExtensions() const override; + const gl::Limitations &getNativeLimitations() const override; + + // Handle helpers + const FunctionsGL *getFunctions() const; + StateManagerGL *getStateManager(); + const WorkaroundsGL &getWorkaroundsGL(); + + private: + RendererGL *mRenderer; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_GL_CONTEXTGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/DisplayGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/DisplayGL.cpp new file mode 100755 index 000000000..30c5c7b4e --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/DisplayGL.cpp @@ -0,0 +1,103 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayGL.h: GL implementation of egl::Display + +#include "libANGLE/renderer/gl/DisplayGL.h" + +#include "libANGLE/AttributeMap.h" +#include "libANGLE/Context.h" +#include "libANGLE/Display.h" +#include "libANGLE/Surface.h" +#include "libANGLE/renderer/gl/ContextGL.h" +#include "libANGLE/renderer/gl/RendererGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" +#include "libANGLE/renderer/gl/SurfaceGL.h" + +#include <EGL/eglext.h> + +namespace rx +{ + +DisplayGL::DisplayGL() : mRenderer(nullptr), mCurrentDrawSurface(nullptr) +{ +} + +DisplayGL::~DisplayGL() +{ +} + +egl::Error DisplayGL::initialize(egl::Display *display) +{ + mRenderer = new RendererGL(getFunctionsGL(), display->getAttributeMap()); + + const gl::Version &maxVersion = mRenderer->getMaxSupportedESVersion(); + if (maxVersion < gl::Version(2, 0)) + { + return egl::Error(EGL_NOT_INITIALIZED, "OpenGL ES 2.0 is not supportable."); + } + + return egl::Error(EGL_SUCCESS); +} + +void DisplayGL::terminate() +{ + SafeDelete(mRenderer); +} + +ImageImpl *DisplayGL::createImage(EGLenum target, + egl::ImageSibling *buffer, + const egl::AttributeMap &attribs) +{ + UNIMPLEMENTED(); + return nullptr; +} + +ContextImpl *DisplayGL::createContext(const gl::ContextState &state) +{ + ASSERT(mRenderer != nullptr); + return new ContextGL(state, mRenderer); +} + +StreamProducerImpl *DisplayGL::createStreamProducerD3DTextureNV12( + egl::Stream::ConsumerType consumerType, + const egl::AttributeMap &attribs) +{ + UNIMPLEMENTED(); + return nullptr; +} + +egl::Error DisplayGL::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) +{ + // Notify the previous surface (if it still exists) that it is no longer current + if (mCurrentDrawSurface && mSurfaceSet.find(mCurrentDrawSurface) != mSurfaceSet.end()) + { + ANGLE_TRY(GetImplAs<SurfaceGL>(mCurrentDrawSurface)->unMakeCurrent()); + } + mCurrentDrawSurface = nullptr; + + if (!drawSurface) + { + return egl::Error(EGL_SUCCESS); + } + + // Pause transform feedback before making a new surface current, to workaround anglebug.com/1426 + ContextGL *glContext = GetImplAs<ContextGL>(context); + glContext->getStateManager()->pauseTransformFeedback(context->getContextState()); + + SurfaceGL *glDrawSurface = GetImplAs<SurfaceGL>(drawSurface); + ANGLE_TRY(glDrawSurface->makeCurrent()); + mCurrentDrawSurface = drawSurface; + + return egl::Error(EGL_SUCCESS); +} + +gl::Version DisplayGL::getMaxSupportedESVersion() const +{ + ASSERT(mRenderer != nullptr); + return mRenderer->getMaxSupportedESVersion(); +} +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/DisplayGL.h b/gfx/angle/src/libANGLE/renderer/gl/DisplayGL.h new file mode 100755 index 000000000..a63da6bbc --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/DisplayGL.h @@ -0,0 +1,62 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayGL.h: Defines the class interface for DisplayGL. + +#ifndef LIBANGLE_RENDERER_GL_DISPLAYGL_H_ +#define LIBANGLE_RENDERER_GL_DISPLAYGL_H_ + +#include "libANGLE/renderer/DisplayImpl.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" + +namespace egl +{ +class Surface; +} + +namespace rx +{ + +class RendererGL; + +class DisplayGL : public DisplayImpl +{ + public: + DisplayGL(); + ~DisplayGL() override; + + egl::Error initialize(egl::Display *display) override; + void terminate() override; + + ImageImpl *createImage(EGLenum target, + egl::ImageSibling *buffer, + const egl::AttributeMap &attribs) override; + + ContextImpl *createContext(const gl::ContextState &state) override; + + StreamProducerImpl *createStreamProducerD3DTextureNV12( + egl::Stream::ConsumerType consumerType, + const egl::AttributeMap &attribs) override; + + egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override; + + virtual egl::Error getDriverVersion(std::string *version) const = 0; + gl::Version getMaxSupportedESVersion() const override; + + protected: + RendererGL *getRenderer() const { return mRenderer; }; + + private: + virtual const FunctionsGL *getFunctionsGL() const = 0; + + RendererGL *mRenderer; + + egl::Surface *mCurrentDrawSurface; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_DISPLAYGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/FeatureSupportGL.md b/gfx/angle/src/libANGLE/renderer/gl/FeatureSupportGL.md new file mode 100755 index 000000000..edc2353ab --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/FeatureSupportGL.md @@ -0,0 +1,107 @@ +# ANGLE RendererGL feature support +Documentation of OpenGL ES and EGL features, caps and formats and required extensions. + +## OpenGL ES Feature Support +|Feature|OpenGL version|OpenGL extension|OpenGL ES version|OpenGL ES extension|Notes| +|---|---|---|---|---|---| +|Framebuffer/renderbuffer objects|3.0|[GL_EXT_framebuffer_object](https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt)|2.0|--|Can potentially be emulated with Pbuffers but realistically this extension is always required.| +|Blit framebuffer|3.0|[GL_EXT_framebuffer_blit](https://www.opengl.org/registry/specs/EXT/framebuffer_blit.txt)|3.0|[GL_ANGLE_framebuffer_blit](https://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_framebuffer_blit.txt) or [GL_NV_framebuffer_blit](https://www.khronos.org/registry/gles/extensions/NV/NV_framebuffer_blit.txt)|| +|Multisampling|3.0|[GL_EXT_framebuffer_multisample](https://www.opengl.org/registry/specs/EXT/framebuffer_multisample.txt)|3.0|[GL_EXT_multisampled_render_to_texture](https://www.khronos.org/registry/gles/extensions/EXT/EXT_multisampled_render_to_texture.txt) or [GL_ANGLE_framebuffer_multisample](https://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_framebuffer_multisample.txt)|| +|Depth textures|3.0|[GL_ARB_depth_texture](https://www.opengl.org/registry/specs/ARB/depth_texture.txt)|3.0|[GL_OES_depth_texture](https://www.khronos.org/registry/gles/extensions/OES/OES_depth_texture.txt) or [GL_ANGLE_depth_texture](https://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_depth_texture.txt) +|Draw buffers (MRT)|2.0?|[GL_ARB_draw_buffers](https://www.opengl.org/registry/specs/ARB/draw_buffers.txt) or [GL_EXT_draw_buffers2](https://www.opengl.org/registry/specs/EXT/draw_buffers2.txt)|3.0|[GL_EXT_draw_buffers](https://www.khronos.org/registry/gles/extensions/EXT/EXT_draw_buffers.txt)|| +|3D textures|1.2|[GL_EXT_texture3D](https://www.opengl.org/registry/specs/EXT/texture3D.txt)|3.0|[GL_OES_texture_3D](https://www.khronos.org/registry/gles/extensions/OES/OES_texture_3D.txt)|| +|Array textures|3.0|[GL_EXT_texture_array](https://www.opengl.org/registry/specs/EXT/texture_array.txt)|3.0|--|| +|Texture storage|4.2|[GL_EXT_texture_storage](https://www.khronos.org/registry/gles/extensions/EXT/EXT_texture_storage.txt)|3.0|[GL_EXT_texture_storage](https://www.khronos.org/registry/gles/extensions/EXT/EXT_texture_storage.txt)|Can be emulated with TexImage calls.| +|Uniform buffer object|3.1|[GL_ARB_uniform_buffer_object](https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt)|3.0|--|| +|Sync objects|3.2|[GL_ARB_sync](https://www.opengl.org/registry/specs/ARB/sync.txt)|3.0|--|| +|Fence objects|--|[GL_NV_fence](https://www.opengl.org/registry/specs/NV/fence.txt)|--|[GL_NV_fence](https://www.opengl.org/registry/specs/NV/fence.txt)|| +|MapBuffer|1.5|--|--|[GL_OES_mapbuffer](https://www.khronos.org/registry/gles/extensions/OES/OES_mapbuffer.txt)|| +|MapBufferRange|3.0|[GL_ARB_map_buffer_range](https://www.opengl.org/registry/specs/ARB/map_buffer_range.txt)|3.0|[GL_EXT_map_buffer_range](https://www.khronos.org/registry/gles/extensions/EXT/EXT_map_buffer_range.txt)|| +|Transform feedback|3.0|[GL_EXT_transform_feedback](GL_EXT_transform_feedback) or [GL_EXT_transform_feedback2](http://developer.download.nvidia.com/opengl/specs/GL_EXT_transform_feedback2.txt) or [GL_ARB_transform_feedback3](https://www.opengl.org/registry/specs/ARB/transform_feedback3.txt)|3.0|--|| +|Sampler object|3.3|[GL_ARB_sampler_objects](https://www.opengl.org/registry/specs/ARB/sampler_objects.txt)|3.0|--|| +|Occlusion query|1.5|[GL_ARB_occlusion_query](https://www.opengl.org/registry/specs/ARB/occlusion_query.txt)|2.0|--|| +|Timer query|3.3|[GL_ARB_timer_query](https://www.opengl.org/registry/specs/ARB/timer_query.txt)|--|[GL_EXT_disjoint_timer_query](https://www.khronos.org/registry/gles/extensions/EXT/EXT_disjoint_timer_query.txt)|| +|Vertex array object|3.0|[GL_ARB_vertex_array_object](https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt)|3.0|[GL_OES_vertex_array_object](https://www.khronos.org/registry/gles/extensions/OES/OES_vertex_array_object.txt)|Can be emulated but costsmany extra API calls. Virtualized contexts also require some kind of emulation of the default attribute state.| +|Anisotropic filtering|--|[GL_EXT_texture_filter_anisotropic](https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt)|--|[GL_EXT_texture_filter_anisotropic](https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt)|Ubiquitous extension.| + +## OpenGL ES Caps +|Cap(s)|OpenGL version|OpenGL extension|OpenGL ES version|OpenGL ES extension|Notes| +|---|---|---|---|---|---| +|GL_MAX_ELEMENT_INDEX|4.3|[GL_ARB_ES3_compatibility](https://www.opengl.org/registry/specs/ARB/ES3_compatibility.txt)|3.0|--|Seems pretty safe to use an arbitrary limit, all implementations tested return 0xFFFFFFFF.| +|GL_MAX_3D_TEXTURE_SIZE|1.2|[GL_EXT_texture3D](https://www.opengl.org/registry/specs/EXT/texture3D.txt)|3.0|[GL_OES_texture_3D](https://www.khronos.org/registry/gles/extensions/OES/OES_texture_3D.txt)|| +|GL_MAX_TEXTURE_SIZE|1.0|--|2.0|--|| +|GL_MAX_CUBE_MAP_TEXTURE_SIZE|1.3|--|2.0|| +|GL_MAX_ARRAY_TEXTURE_LAYERS|3.0|[GL_EXT_texture_array](https://www.opengl.org/registry/specs/EXT/texture_array.txt)|3.0|--|| +|GL_MAX_TEXTURE_LOD_BIAS|1.5|[GL_EXT_texture_lod_bias](https://www.opengl.org/registry/specs/EXT/texture_lod_bias.txt)|3.0|--|| +|GL_MAX_RENDERBUFFER_SIZE GL_MAX_COLOR_ATTACHMENTS|3.0|[GL_EXT_framebuffer_object](https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt) |2.0|--|| +|GL_MAX_DRAW_BUFFERS|2.0?|[GL_ARB_draw_buffers](https://www.opengl.org/registry/specs/ARB/draw_buffers.txt) or [GL_EXT_draw_buffers2](https://www.opengl.org/registry/specs/EXT/draw_buffers2.txt)|3.0|[GL_EXT_draw_buffers](https://www.khronos.org/registry/gles/extensions/EXT/EXT_draw_buffers.txt)|| +|GL_MAX_VIEWPORT_DIMS|1.0|--|2.0|--|| +|GL_ALIASED_POINT_SIZE_RANGE|1.0?|--|2.0|--|| +|GL_ALIASED_LINE_WIDTH_RANGE|1.2|--|2.0|--|| +|GL_ALIASED_LINE_WIDTH_RANGE|1.2|--|2.0|--|| +|GL_MAX_ELEMENTS_INDICES|1.2|--|3.0|--|| +|GL_MAX_ELEMENTS_VERTICES|1.2|--|3.0|--|| +|Shader format precision (glGetShaderPrecisionFormat)|4.1|[GL_ARB_ES2_compatibility](https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt)|2.0|--|Can use reasonable default values (IEEE float and twos complement integer).| +|GL_MAX_VERTEX_ATTRIBS|2.0|--|2.0|--|| +|GL_MAX_VERTEX_UNIFORM_COMPONENTS|2.0|--|2.0|--|| +|GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS|2.0|--|2.0|--|| +|GL_MAX_VERTEX_UNIFORM_VECTORS GL_MAX_FRAGMENT_UNIFORM_VECTORS|4.1|[GL_ARB_ES2_compatibility](https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt)|2.0|--|Defined as GL_MAX_VERTEX_UNIFORM_COMPONENTS / 4 and GL_MAX_FRAGMENT_UNIFORM_COMPONENTS / 4. Can simply use those values when the cap is not available.| +|GL_MAX_VERTEX_UNIFORM_BLOCKS GL_MAX_FRAGMENT_UNIFORM_BLOCKS GL_MAX_UNIFORM_BUFFER_BINDINGS GL_MAX_UNIFORM_BLOCK_SIZE GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT GL_MAX_COMBINED_UNIFORM_BLOCKS GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS |3.1|[GL_ARB_uniform_buffer_object](https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt)|3.0|--|| +|GL_MAX_VERTEX_OUTPUT_COMPONENTS|3.2|--|3.0|--|Doesn't seem to be a desktop extension for this cap, it may be possible to use the minimum ES3 value (64) if lower than GL 3.2.| +|GL_MAX_FRAGMENT_UNIFORM_COMPONENTS|2.0|--|2.0|--|| +|GL_MAX_TEXTURE_IMAGE_UNITS|2.0|--|2.0|--|| +|GL_MAX_FRAGMENT_INPUT_COMPONENTS|3.2|--|3.0|--|Doesn't seem to be a desktop extension for this cap either, it may be possible to use the minimum ES3 value (60) if lower than GL 3.2.| +|GL_MIN_PROGRAM_TEXEL_OFFSET GL_MAX_PROGRAM_TEXEL_OFFSET|3.0|--|3.0|--|Could potentially be emulated in the shader by adding the offsets in normalized texture coordinates before sampling.| +|GL_MAX_VARYING_COMPONENTS|3.0|[GL_ARB_ES3_compatibility](https://www.opengl.org/registry/specs/ARB/ES3_compatibility.txt)|3.0|--|Was depricated in the OpenGL core spec but re-added in GL_ARB_ES3_compatibility| +|GL_MAX_VARYING_VECTORS|4.1|[GL_ARB_ES2_compatibility](https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt)|2.0|--|Defined as GL_MAX_VARYING_COMPONENTS / 4.| +|GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS|3.0|[GL_EXT_transform_feedback](GL_EXT_transform_feedback) or [GL_EXT_transform_feedback2](http://developer.download.nvidia.com/opengl/specs/GL_EXT_transform_feedback2.txt) or [GL_ARB_transform_feedback3](https://www.opengl.org/registry/specs/ARB/transform_feedback3.txt)|3.0|-- +|GL_MAX_SAMPLES|3.0|[GL_EXT_framebuffer_multisample](https://www.opengl.org/registry/specs/EXT/framebuffer_multisample.txt)|3.0|[GL_EXT_multisampled_render_to_texture](https://www.khronos.org/registry/gles/extensions/EXT/EXT_multisampled_render_to_texture.txt) or [GL_ANGLE_framebuffer_multisample](https://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_framebuffer_multisample.txt)|| +|GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT|--|[GL_EXT_texture_filter_anisotropic](https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt)|--|[GL_EXT_texture_filter_anisotropic](https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt)|Ubiquitous extension.| +|IMPLEMENTATION_COLOR_READ_FORMAT IMPLEMENTATION_COLOR_READ_TYPE|--|[GL_ARB_ES2_compatibility](https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt)|2.0|--|Desktop GL doesn't as many limitations as ES for ReadPixels, can either always return GL_RGBA/GL_UNSIGNED_BYTE or return the format and type of the read buffer.| + +##OpenGL ES Formats (TODO) +|Format|OpenGL version|OpenGL extension|OpenGL ES version|OpenGL ES extension|Notes| +|---|---|---|---|---|---| +|GL_RGBA8<br>GL_RGB8 |1.0|--|3.0|[GL_OES_rgb8_rgba8](https://www.khronos.org/registry/gles/extensions/OES/OES_rgb8_rgba8.txt)|| + +## ESSL Features (TODO) +|Feature|GLSL version|Notes| +|---|---|---| +|Unsigned integers|1.30|| +|Pack layout std140|1.40|| + +## ESSL3 Builtins +Builtins that are added going from ESSL1 to ESSL3. + +|Function|GLSL version|Extension|Notes| +|---|---|---|---| +|sinh<br>cosh<br>tanh<br>asinh<br>acosh|1.30||| +|atanh|1.10||| +|abs (genIType)|1.30|[GL_EXT_gpu_shader4](https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt)|| +|sign (genIType)|1.50|[GL_EXT_gpu_shader4](https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt)|Can be emulated easily.| +|trunc|1.30||| +|round<br>roundEven|1.30||| +|min (genIType, genUType)<br>max (genIType, genUType)<br>clamp (genIType, genUType)|1.30|| +|mix (genBType)|4.50|[GL_EXT_shader_integer_mix](https://www.opengl.org/registry/specs/EXT/shader_integer_mix.txt)|Should be possible to emulate with a ternery operation.| +|modf|1.30||| +|isnan|1.30||| +|isinf|1.10||| +|floatBitsToInt<br>floatBitsToUint<br>intBitsToFloat<br>uintBitsToFloat|3.30|[GL_ARB_shader_bit_encoding](https://www.opengl.org/registry/specs/ARB/shader_bit_encoding.txt) or [ARB_gpu_shader5](https://www.opengl.org/registry/specs/ARB/gpu_shader5.txt)|| +|packSnorm2x16<br>packHalf2x16<br>unpackSnorm2x16<br>unpackHalf2x16|4.20|[GL_ARB_shading_language_packing](https://www.opengl.org/registry/specs/ARB/shading_language_packing.txt)|Can be emulated using bit casting functions.| +|packUnorm2x16<br>unpackUnorm2x16|4.10|[GL_ARB_shading_language_packing](https://www.opengl.org/registry/specs/ARB/shading_language_packing.txt)|Can be emulated using bit casting functions.| +|matrixCompMult (NxM matrices)|1.10||| +|outerProduct|1.20||| +|transpose|1.20||| +|determinant|1.50||Can be emulated.| +|inverse|1.40||Can be emulated.| +|lessThan (uvec)<br>lessThanEqual (uvec)<br>greaterThan (uvec)<br>greaterThanEqual (uvec)<br>equal (uvec)<br>notEqual (uvec)|1.30||| +|texture<br>textureProj<br>textureLod<br>textureOffset<br>textureProjOffset<br>textureLodOffset<br>textureProjLod<br>textureProjLodOffset<br>texelFetch<br>texelFetchOffset<br>textureGrad<br>textureGradOffset<br>textureProjGrad<br>textureProjGradOffset<br>textureSize|1.30||Equivalent to texture2D, textureCube, etc| +|dFdx<br>dFdy<br>fwidth|1.10|| + +## EGL Feature Support (TODO) +|Feature|EGL version|EGL extension|WGL core|WGL extension|GLX version|GLX extensions|Notes| +|---|---|---|---|---|---|---|---| +|Pbuffers|||No|[WGL_ARB_pbuffer](https://www.opengl.org/registry/specs/ARB/wgl_pbuffer.txt)|||| +|BindTexImage|||No|[WGL_ARB_render_texture](https://www.opengl.org/registry/specs/ARB/wgl_render_texture.txt)|||Possibly to emulate with OpenGL textures but not strictly required, it is possible only export EGL configs without EGL_BIND_TO_TEXTURE_RGB and EGL_BIND_TO_TEXTURE_RGBA. Bindable pbuffers may be required by Chrome though.| +|Pixmaps|||||||| +|Swap control|||No|[WGL_EXT_swap_control](https://www.opengl.org/registry/specs/EXT/wgl_swap_control.txt)|No|[GLX_EXT_swap_control](https://www.opengl.org/registry/specs/EXT/swap_control.txt)|| diff --git a/gfx/angle/src/libANGLE/renderer/gl/FenceNVGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/FenceNVGL.cpp new file mode 100755 index 000000000..b463054c3 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/FenceNVGL.cpp @@ -0,0 +1,51 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FenceNVGL.cpp: Implements the class methods for FenceNVGL. + +#include "libANGLE/renderer/gl/FenceNVGL.h" + +#include "common/debug.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" + + +namespace rx +{ + +FenceNVGL::FenceNVGL(const FunctionsGL *functions) + : FenceNVImpl(), + mFunctions(functions) +{ + mFunctions->genFencesNV(1, &mFence); +} + +FenceNVGL::~FenceNVGL() +{ + mFunctions->deleteFencesNV(1, &mFence); + mFence = 0; +} + +gl::Error FenceNVGL::set(GLenum condition) +{ + ASSERT(condition == GL_ALL_COMPLETED_NV); + mFunctions->setFenceNV(mFence, condition); + return gl::Error(GL_NO_ERROR); +} + +gl::Error FenceNVGL::test(GLboolean *outFinished) +{ + ASSERT(outFinished); + *outFinished = mFunctions->testFenceNV(mFence); + return gl::Error(GL_NO_ERROR); +} + +gl::Error FenceNVGL::finish() +{ + mFunctions->finishFenceNV(mFence); + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/FenceNVGL.h b/gfx/angle/src/libANGLE/renderer/gl/FenceNVGL.h new file mode 100755 index 000000000..ffeca8515 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/FenceNVGL.h @@ -0,0 +1,36 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FenceNVGL.h: Defines the class interface for FenceNVGL. + +#ifndef LIBANGLE_RENDERER_GL_FENCENVGL_H_ +#define LIBANGLE_RENDERER_GL_FENCENVGL_H_ + +#include "libANGLE/renderer/FenceNVImpl.h" + +namespace rx +{ +class FunctionsGL; + +class FenceNVGL : public FenceNVImpl +{ + public: + explicit FenceNVGL(const FunctionsGL *functions); + ~FenceNVGL() override; + + gl::Error set(GLenum condition) override; + gl::Error test(GLboolean *outFinished) override; + gl::Error finish() override; + + private: + GLuint mFence; + + const FunctionsGL *mFunctions; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_FENCENVGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/FenceSyncGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/FenceSyncGL.cpp new file mode 100755 index 000000000..a3589b95e --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/FenceSyncGL.cpp @@ -0,0 +1,67 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FenceSyncGL.cpp: Implements the class methods for FenceSyncGL. + +#include "libANGLE/renderer/gl/FenceSyncGL.h" + +#include "common/debug.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" + +namespace rx +{ + +FenceSyncGL::FenceSyncGL(const FunctionsGL *functions) + : FenceSyncImpl(), + mFunctions(functions), + mSyncObject(0) +{ + ASSERT(mFunctions); +} + +FenceSyncGL::~FenceSyncGL() +{ + if (mSyncObject != 0) + { + mFunctions->deleteSync(mSyncObject); + } +} + +gl::Error FenceSyncGL::set(GLenum condition, GLbitfield flags) +{ + ASSERT(condition == GL_SYNC_GPU_COMMANDS_COMPLETE && flags == 0); + mSyncObject = mFunctions->fenceSync(condition, flags); + if (mSyncObject == 0) + { + // if glFenceSync fails, it returns 0. + return gl::Error(GL_OUT_OF_MEMORY, "glFenceSync failed to create a GLsync object."); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error FenceSyncGL::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) +{ + ASSERT(mSyncObject != 0); + *outResult = mFunctions->clientWaitSync(mSyncObject, flags, timeout); + return gl::Error(GL_NO_ERROR); +} + +gl::Error FenceSyncGL::serverWait(GLbitfield flags, GLuint64 timeout) +{ + ASSERT(mSyncObject != 0); + mFunctions->waitSync(mSyncObject, flags, timeout); + return gl::Error(GL_NO_ERROR); +} + +gl::Error FenceSyncGL::getStatus(GLint *outResult) +{ + ASSERT(mSyncObject != 0); + mFunctions->getSynciv(mSyncObject, GL_SYNC_STATUS, 1, nullptr, outResult); + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/FenceSyncGL.h b/gfx/angle/src/libANGLE/renderer/gl/FenceSyncGL.h new file mode 100755 index 000000000..8dfd6632d --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/FenceSyncGL.h @@ -0,0 +1,36 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FenceSyncGL.h: Defines the class interface for FenceSyncGL. + +#ifndef LIBANGLE_RENDERER_GL_FENCESYNCGL_H_ +#define LIBANGLE_RENDERER_GL_FENCESYNCGL_H_ + +#include "libANGLE/renderer/FenceSyncImpl.h" + +namespace rx +{ +class FunctionsGL; + +class FenceSyncGL : public FenceSyncImpl +{ + public: + explicit FenceSyncGL(const FunctionsGL *functions); + ~FenceSyncGL() override; + + gl::Error set(GLenum condition, GLbitfield flags) override; + gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) override; + gl::Error serverWait(GLbitfield flags, GLuint64 timeout) override; + gl::Error getStatus(GLint *outResult) override; + + private: + const FunctionsGL *mFunctions; + GLsync mSyncObject; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_FENCESYNCGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp new file mode 100755 index 000000000..0a058f8ba --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp @@ -0,0 +1,553 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FramebufferGL.cpp: Implements the class methods for FramebufferGL. + +#include "libANGLE/renderer/gl/FramebufferGL.h" + +#include "common/BitSetIterator.h" +#include "common/debug.h" +#include "libANGLE/ContextState.h" +#include "libANGLE/State.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/ContextImpl.h" +#include "libANGLE/renderer/gl/BlitGL.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/RenderbufferGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" +#include "libANGLE/renderer/gl/TextureGL.h" +#include "libANGLE/renderer/gl/WorkaroundsGL.h" +#include "libANGLE/renderer/gl/formatutilsgl.h" +#include "libANGLE/renderer/gl/renderergl_utils.h" +#include "platform/Platform.h" + +using namespace gl; +using angle::CheckedNumeric; + +namespace rx +{ + +FramebufferGL::FramebufferGL(const FramebufferState &state, + const FunctionsGL *functions, + StateManagerGL *stateManager, + const WorkaroundsGL &workarounds, + BlitGL *blitter, + bool isDefault) + : FramebufferImpl(state), + mFunctions(functions), + mStateManager(stateManager), + mWorkarounds(workarounds), + mBlitter(blitter), + mFramebufferID(0), + mIsDefault(isDefault) +{ + if (!mIsDefault) + { + mFunctions->genFramebuffers(1, &mFramebufferID); + } +} + +FramebufferGL::FramebufferGL(GLuint id, + const FramebufferState &state, + const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + BlitGL *blitter, + StateManagerGL *stateManager) + : FramebufferImpl(state), + mFunctions(functions), + mStateManager(stateManager), + mWorkarounds(workarounds), + mBlitter(blitter), + mFramebufferID(id), + mIsDefault(true) +{ +} + +FramebufferGL::~FramebufferGL() +{ + mStateManager->deleteFramebuffer(mFramebufferID); + mFramebufferID = 0; +} + +static void BindFramebufferAttachment(const FunctionsGL *functions, + GLenum attachmentPoint, + const FramebufferAttachment *attachment) +{ + if (attachment) + { + if (attachment->type() == GL_TEXTURE) + { + const Texture *texture = attachment->getTexture(); + const TextureGL *textureGL = GetImplAs<TextureGL>(texture); + + if (texture->getTarget() == GL_TEXTURE_2D) + { + functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, + textureGL->getTextureID(), attachment->mipLevel()); + } + else if (texture->getTarget() == GL_TEXTURE_CUBE_MAP) + { + functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, attachment->cubeMapFace(), + textureGL->getTextureID(), attachment->mipLevel()); + } + else if (texture->getTarget() == GL_TEXTURE_2D_ARRAY || texture->getTarget() == GL_TEXTURE_3D) + { + functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint, textureGL->getTextureID(), + attachment->mipLevel(), attachment->layer()); + } + else + { + UNREACHABLE(); + } + } + else if (attachment->type() == GL_RENDERBUFFER) + { + const Renderbuffer *renderbuffer = attachment->getRenderbuffer(); + const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer); + + functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER, + renderbufferGL->getRenderbufferID()); + } + else + { + UNREACHABLE(); + } + } + else + { + // Unbind this attachment + functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0); + } +} + +Error FramebufferGL::discard(size_t count, const GLenum *attachments) +{ + UNIMPLEMENTED(); + return Error(GL_INVALID_OPERATION); +} + +Error FramebufferGL::invalidate(size_t count, const GLenum *attachments) +{ + // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available. + if (mFunctions->invalidateFramebuffer) + { + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); + mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count), attachments); + } + + return Error(GL_NO_ERROR); +} + +Error FramebufferGL::invalidateSub(size_t count, + const GLenum *attachments, + const gl::Rectangle &area) +{ + // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available. + if (mFunctions->invalidateSubFramebuffer) + { + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); + mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count), + attachments, area.x, area.y, area.width, area.height); + } + + return Error(GL_NO_ERROR); +} + +Error FramebufferGL::clear(ContextImpl *context, GLbitfield mask) +{ + syncClearState(mask); + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); + mFunctions->clear(mask); + + return Error(GL_NO_ERROR); +} + +Error FramebufferGL::clearBufferfv(ContextImpl *context, + GLenum buffer, + GLint drawbuffer, + const GLfloat *values) +{ + syncClearBufferState(buffer, drawbuffer); + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); + mFunctions->clearBufferfv(buffer, drawbuffer, values); + + return Error(GL_NO_ERROR); +} + +Error FramebufferGL::clearBufferuiv(ContextImpl *context, + GLenum buffer, + GLint drawbuffer, + const GLuint *values) +{ + syncClearBufferState(buffer, drawbuffer); + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); + mFunctions->clearBufferuiv(buffer, drawbuffer, values); + + return Error(GL_NO_ERROR); +} + +Error FramebufferGL::clearBufferiv(ContextImpl *context, + GLenum buffer, + GLint drawbuffer, + const GLint *values) +{ + syncClearBufferState(buffer, drawbuffer); + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); + mFunctions->clearBufferiv(buffer, drawbuffer, values); + + return Error(GL_NO_ERROR); +} + +Error FramebufferGL::clearBufferfi(ContextImpl *context, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil) +{ + syncClearBufferState(buffer, drawbuffer); + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); + mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil); + + return Error(GL_NO_ERROR); +} + +GLenum FramebufferGL::getImplementationColorReadFormat() const +{ + const auto *readAttachment = mState.getReadAttachment(); + const Format &format = readAttachment->getFormat(); + return format.info->getReadPixelsFormat(); +} + +GLenum FramebufferGL::getImplementationColorReadType() const +{ + const auto *readAttachment = mState.getReadAttachment(); + const Format &format = readAttachment->getFormat(); + return format.info->getReadPixelsType(); +} + +Error FramebufferGL::readPixels(ContextImpl *context, + const gl::Rectangle &area, + GLenum format, + GLenum type, + GLvoid *pixels) const +{ + // TODO: don't sync the pixel pack state here once the dirty bits contain the pixel pack buffer + // binding + const PixelPackState &packState = context->getGLState().getPackState(); + mStateManager->setPixelPackState(packState); + + nativegl::ReadPixelsFormat readPixelsFormat = + nativegl::GetReadPixelsFormat(mFunctions, mWorkarounds, format, type); + GLenum readFormat = readPixelsFormat.format; + GLenum readType = readPixelsFormat.type; + + mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID); + + if (mWorkarounds.packOverlappingRowsSeparatelyPackBuffer && packState.pixelBuffer.get() && + packState.rowLength != 0 && packState.rowLength < area.width) + { + return readPixelsRowByRowWorkaround(area, readFormat, readType, packState, pixels); + } + + if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion) + { + gl::Extents size(area.width, area.height, 1); + + bool apply; + ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, packState, readFormat, readType, + false, pixels), + apply); + + if (apply) + { + return readPixelsPaddingWorkaround(area, readFormat, readType, packState, pixels); + } + } + + mFunctions->readPixels(area.x, area.y, area.width, area.height, readFormat, readType, pixels); + + return gl::NoError(); +} + +Error FramebufferGL::blit(ContextImpl *context, + const gl::Rectangle &sourceArea, + const gl::Rectangle &destArea, + GLbitfield mask, + GLenum filter) +{ + const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer(); + const Framebuffer *destFramebuffer = context->getGLState().getDrawFramebuffer(); + + const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer(); + GLsizei readAttachmentSamples = colorReadAttachment->getSamples(); + + bool needManualColorBlit = false; + + // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we + // could avoid doing a manual blit. + + // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads: + // When values are taken from the read buffer, no linearization is performed, even + // if the format of the buffer is SRGB. + // Starting from OpenGL 4.4 (section 18.3.1) it reads: + // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the + // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment + // corresponding to the read buffer is SRGB, the red, green, and blue components are + // converted from the non-linear sRGB color space according [...]. + { + bool sourceSRGB = colorReadAttachment != nullptr && + colorReadAttachment->getColorEncoding() == GL_SRGB; + needManualColorBlit = + needManualColorBlit || (sourceSRGB && mFunctions->isAtMostGL(gl::Version(4, 3))); + } + + // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads: + // Blit operations bypass the fragment pipeline. The only fragment operations which + // affect a blit are the pixel ownership test and scissor test. + // Starting from OpenGL 4.2 (section 4.3.2) it reads: + // When values are written to the draw buffers, blit operations bypass the fragment + // pipeline. The only fragment operations which affect a blit are the pixel ownership + // test, the scissor test and sRGB conversion. + if (!needManualColorBlit) + { + bool destSRGB = false; + for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i) + { + const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i); + if (attachment && attachment->getColorEncoding() == GL_SRGB) + { + destSRGB = true; + break; + } + } + + needManualColorBlit = + needManualColorBlit || (destSRGB && mFunctions->isAtMostGL(gl::Version(4, 1))); + } + + // Enable FRAMEBUFFER_SRGB if needed + mStateManager->setFramebufferSRGBEnabledForFramebuffer(true, this); + + GLenum blitMask = mask; + if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1) + { + ANGLE_TRY(mBlitter->blitColorBufferWithShader(sourceFramebuffer, destFramebuffer, + sourceArea, destArea, filter)); + blitMask &= ~GL_COLOR_BUFFER_BIT; + } + + if (blitMask == 0) + { + return gl::NoError(); + } + + const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer); + mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID()); + mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID); + + mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(), + destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask, + filter); + + return gl::NoError(); +} + +bool FramebufferGL::checkStatus() const +{ + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); + GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) + { + ANGLEPlatformCurrent()->logWarning("GL framebuffer returned incomplete."); + } + return (status == GL_FRAMEBUFFER_COMPLETE); +} + +void FramebufferGL::syncState(const Framebuffer::DirtyBits &dirtyBits) +{ + // Don't need to sync state for the default FBO. + if (mIsDefault) + { + return; + } + + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); + + for (auto dirtyBit : angle::IterateBitSet(dirtyBits)) + { + switch (dirtyBit) + { + case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT: + BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT, + mState.getDepthAttachment()); + break; + case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT: + BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT, + mState.getStencilAttachment()); + break; + case Framebuffer::DIRTY_BIT_DRAW_BUFFERS: + { + const auto &drawBuffers = mState.getDrawBufferStates(); + mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()), + drawBuffers.data()); + break; + } + case Framebuffer::DIRTY_BIT_READ_BUFFER: + mFunctions->readBuffer(mState.getReadBufferState()); + break; + default: + { + ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 && + dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX); + size_t index = + static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0); + BindFramebufferAttachment(mFunctions, + static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index), + mState.getColorAttachment(index)); + break; + } + } + } +} + +GLuint FramebufferGL::getFramebufferID() const +{ + return mFramebufferID; +} + +bool FramebufferGL::isDefault() const +{ + return mIsDefault; +} + +void FramebufferGL::syncClearState(GLbitfield mask) +{ + if (mFunctions->standard == STANDARD_GL_DESKTOP) + { + if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && + (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault) + { + bool hasSRGBAttachment = false; + for (const auto &attachment : mState.getColorAttachments()) + { + if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB) + { + hasSRGBAttachment = true; + break; + } + } + + mStateManager->setFramebufferSRGBEnabled(hasSRGBAttachment); + } + else + { + mStateManager->setFramebufferSRGBEnabled(!mIsDefault); + } + } +} + +void FramebufferGL::syncClearBufferState(GLenum buffer, GLint drawBuffer) +{ + if (mFunctions->standard == STANDARD_GL_DESKTOP) + { + if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR && + !mIsDefault) + { + // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer + // is an SRGB format. + const auto &drawbufferState = mState.getDrawBufferStates(); + const auto &colorAttachments = mState.getColorAttachments(); + + const FramebufferAttachment *attachment = nullptr; + if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 && + drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size()) + { + size_t attachmentIdx = + static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0); + attachment = &colorAttachments[attachmentIdx]; + } + + if (attachment != nullptr) + { + mStateManager->setFramebufferSRGBEnabled(attachment->getColorEncoding() == GL_SRGB); + } + } + else + { + mStateManager->setFramebufferSRGBEnabled(!mIsDefault); + } + } +} +gl::Error FramebufferGL::readPixelsRowByRowWorkaround(const gl::Rectangle &area, + GLenum format, + GLenum type, + const gl::PixelPackState &pack, + GLvoid *pixels) const +{ + intptr_t offset = reinterpret_cast<intptr_t>(pixels); + + const gl::InternalFormat &glFormat = + gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type)); + GLuint rowBytes = 0; + ANGLE_TRY_RESULT(glFormat.computeRowPitch(area.width, pack.alignment, pack.rowLength), + rowBytes); + GLuint skipBytes = 0; + ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes); + + gl::PixelPackState directPack; + directPack.pixelBuffer = pack.pixelBuffer; + directPack.alignment = 1; + mStateManager->setPixelPackState(directPack); + directPack.pixelBuffer.set(nullptr); + + offset += skipBytes; + for (GLint row = 0; row < area.height; ++row) + { + mFunctions->readPixels(area.x, row + area.y, area.width, 1, format, type, + reinterpret_cast<GLvoid *>(offset)); + offset += row * rowBytes; + } + + return gl::NoError(); +} + +gl::Error FramebufferGL::readPixelsPaddingWorkaround(const gl::Rectangle &area, + GLenum format, + GLenum type, + const gl::PixelPackState &pack, + GLvoid *pixels) const +{ + const gl::InternalFormat &glFormat = + gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type)); + GLuint rowBytes = 0; + ANGLE_TRY_RESULT(glFormat.computeRowPitch(area.width, pack.alignment, pack.rowLength), + rowBytes); + GLuint skipBytes = 0; + ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes); + + // Get all by the last row + if (area.height > 1) + { + mFunctions->readPixels(area.x, area.y, area.width, area.height - 1, format, type, pixels); + } + + // Get the last row manually + gl::PixelPackState directPack; + directPack.pixelBuffer = pack.pixelBuffer; + directPack.alignment = 1; + mStateManager->setPixelPackState(directPack); + directPack.pixelBuffer.set(nullptr); + + intptr_t lastRowOffset = + reinterpret_cast<intptr_t>(pixels) + skipBytes + (area.height - 1) * rowBytes; + mFunctions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type, + reinterpret_cast<GLvoid *>(lastRowOffset)); + + return gl::NoError(); +} +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.h b/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.h new file mode 100755 index 000000000..a8bcb894c --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.h @@ -0,0 +1,113 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FramebufferGL.h: Defines the class interface for FramebufferGL. + +#ifndef LIBANGLE_RENDERER_GL_FRAMEBUFFERGL_H_ +#define LIBANGLE_RENDERER_GL_FRAMEBUFFERGL_H_ + +#include "libANGLE/renderer/FramebufferImpl.h" + +namespace rx +{ + +class BlitGL; +class FunctionsGL; +class StateManagerGL; +struct WorkaroundsGL; + +class FramebufferGL : public FramebufferImpl +{ + public: + FramebufferGL(const gl::FramebufferState &data, + const FunctionsGL *functions, + StateManagerGL *stateManager, + const WorkaroundsGL &workarounds, + BlitGL *blitter, + bool isDefault); + // Constructor called when we need to create a FramebufferGL from an + // existing framebuffer name, for example for the default framebuffer + // on the Mac EGL CGL backend. + FramebufferGL(GLuint id, + const gl::FramebufferState &data, + const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + BlitGL *blitter, + StateManagerGL *stateManager); + ~FramebufferGL() override; + + gl::Error discard(size_t count, const GLenum *attachments) override; + gl::Error invalidate(size_t count, const GLenum *attachments) override; + gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override; + + gl::Error clear(ContextImpl *context, GLbitfield mask) override; + gl::Error clearBufferfv(ContextImpl *context, + GLenum buffer, + GLint drawbuffer, + const GLfloat *values) override; + gl::Error clearBufferuiv(ContextImpl *context, + GLenum buffer, + GLint drawbuffer, + const GLuint *values) override; + gl::Error clearBufferiv(ContextImpl *context, + GLenum buffer, + GLint drawbuffer, + const GLint *values) override; + gl::Error clearBufferfi(ContextImpl *context, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil) override; + + GLenum getImplementationColorReadFormat() const override; + GLenum getImplementationColorReadType() const override; + gl::Error readPixels(ContextImpl *context, + const gl::Rectangle &area, + GLenum format, + GLenum type, + GLvoid *pixels) const override; + + gl::Error blit(ContextImpl *context, + const gl::Rectangle &sourceArea, + const gl::Rectangle &destArea, + GLbitfield mask, + GLenum filter) override; + + bool checkStatus() const override; + + void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override; + + GLuint getFramebufferID() const; + bool isDefault() const; + + private: + void syncClearState(GLbitfield mask); + void syncClearBufferState(GLenum buffer, GLint drawBuffer); + + gl::Error readPixelsRowByRowWorkaround(const gl::Rectangle &area, + GLenum format, + GLenum type, + const gl::PixelPackState &pack, + GLvoid *pixels) const; + + gl::Error readPixelsPaddingWorkaround(const gl::Rectangle &area, + GLenum format, + GLenum type, + const gl::PixelPackState &pack, + GLvoid *pixels) const; + + const FunctionsGL *mFunctions; + StateManagerGL *mStateManager; + const WorkaroundsGL &mWorkarounds; + BlitGL *mBlitter; + + GLuint mFramebufferID; + bool mIsDefault; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_FRAMEBUFFERGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp new file mode 100755 index 000000000..fcbf211bc --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp @@ -0,0 +1,2316 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FunctionsGL.cpp: Implements the FuntionsGL class to contain loaded GL functions + +#include "libANGLE/renderer/gl/FunctionsGL.h" + +#include <algorithm> + +#include "common/string_utils.h" +#include "libANGLE/renderer/gl/renderergl_utils.h" + +namespace rx +{ + +static void GetGLVersion(PFNGLGETSTRINGPROC getStringFunction, gl::Version *outVersion, StandardGL *outStandard) +{ + const std::string version = reinterpret_cast<const char*>(getStringFunction(GL_VERSION)); + if (version.find("OpenGL ES") == std::string::npos) + { + // OpenGL spec states the GL_VERSION string will be in the following format: + // <version number><space><vendor-specific information> + // The version number is either of the form major number.minor number or major + // number.minor number.release number, where the numbers all have one or more + // digits + *outStandard = STANDARD_GL_DESKTOP; + *outVersion = gl::Version(version[0] - '0', version[2] - '0'); + } + else + { + // ES spec states that the GL_VERSION string will be in the following format: + // "OpenGL ES N.M vendor-specific information" + *outStandard = STANDARD_GL_ES; + *outVersion = gl::Version(version[10] - '0', version[12] - '0'); + } +} + +static std::vector<std::string> GetIndexedExtensions(PFNGLGETINTEGERVPROC getIntegerFunction, PFNGLGETSTRINGIPROC getStringIFunction) +{ + std::vector<std::string> result; + + GLint numExtensions; + getIntegerFunction(GL_NUM_EXTENSIONS, &numExtensions); + + result.reserve(numExtensions); + + for (GLint i = 0; i < numExtensions; i++) + { + result.push_back(reinterpret_cast<const char*>(getStringIFunction(GL_EXTENSIONS, i))); + } + + return result; +} + +template <typename T> +static void AssignGLEntryPoint(void *function, T *outFunction) +{ + *outFunction = reinterpret_cast<T>(function); +} + +template <typename T> +static void AssignGLExtensionEntryPoint(const std::vector<std::string> &extensions, const char *requiredExtensionString, + void *function, T *outFunction) +{ + std::vector<std::string> requiredExtensions; + angle::SplitStringAlongWhitespace(requiredExtensionString, &requiredExtensions); + for (const std::string& requiredExtension : requiredExtensions) + { + if (std::find(extensions.begin(), extensions.end(), requiredExtension) == extensions.end()) + { + return; + } + } + + *outFunction = reinterpret_cast<T>(function); +} + +FunctionsGL::FunctionsGL() + : version(), + standard(), + extensions(), + + blendFunc(nullptr), + clear(nullptr), + clearColor(nullptr), + clearDepth(nullptr), + clearStencil(nullptr), + colorMask(nullptr), + cullFace(nullptr), + depthFunc(nullptr), + depthMask(nullptr), + depthRange(nullptr), + disable(nullptr), + drawBuffer(nullptr), + enable(nullptr), + finish(nullptr), + flush(nullptr), + frontFace(nullptr), + getBooleanv(nullptr), + getDoublev(nullptr), + getError(nullptr), + getFloatv(nullptr), + getIntegerv(nullptr), + getString(nullptr), + getTexImage(nullptr), + getTexLevelParameterfv(nullptr), + getTexLevelParameteriv(nullptr), + getTexParameterfv(nullptr), + getTexParameteriv(nullptr), + hint(nullptr), + isEnabled(nullptr), + lineWidth(nullptr), + logicOp(nullptr), + pixelStoref(nullptr), + pixelStorei(nullptr), + pointSize(nullptr), + polygonMode(nullptr), + readBuffer(nullptr), + readPixels(nullptr), + scissor(nullptr), + stencilFunc(nullptr), + stencilMask(nullptr), + stencilOp(nullptr), + texImage1D(nullptr), + texImage2D(nullptr), + texParameterf(nullptr), + texParameterfv(nullptr), + texParameteri(nullptr), + texParameteriv(nullptr), + viewport(nullptr), + + bindTexture(nullptr), + copyTexImage1D(nullptr), + copyTexImage2D(nullptr), + copyTexSubImage1D(nullptr), + copyTexSubImage2D(nullptr), + deleteTextures(nullptr), + drawArrays(nullptr), + drawElements(nullptr), + genTextures(nullptr), + isTexture(nullptr), + polygonOffset(nullptr), + texSubImage1D(nullptr), + texSubImage2D(nullptr), + + blendColor(nullptr), + blendEquation(nullptr), + copyTexSubImage3D(nullptr), + drawRangeElements(nullptr), + texImage3D(nullptr), + texSubImage3D(nullptr), + + deleteFencesNV(nullptr), + genFencesNV(nullptr), + isFenceNV(nullptr), + testFenceNV(nullptr), + getFenceivNV(nullptr), + finishFenceNV(nullptr), + setFenceNV(nullptr), + + activeTexture(nullptr), + compressedTexImage1D(nullptr), + compressedTexImage2D(nullptr), + compressedTexImage3D(nullptr), + compressedTexSubImage1D(nullptr), + compressedTexSubImage2D(nullptr), + compressedTexSubImage3D(nullptr), + getCompressedTexImage(nullptr), + sampleCoverage(nullptr), + + blendFuncSeparate(nullptr), + multiDrawArrays(nullptr), + multiDrawElements(nullptr), + pointParameterf(nullptr), + pointParameterfv(nullptr), + pointParameteri(nullptr), + pointParameteriv(nullptr), + + beginQuery(nullptr), + bindBuffer(nullptr), + bufferData(nullptr), + bufferSubData(nullptr), + deleteBuffers(nullptr), + deleteQueries(nullptr), + endQuery(nullptr), + genBuffers(nullptr), + genQueries(nullptr), + getBufferParameteriv(nullptr), + getBufferPointerv(nullptr), + getBufferSubData(nullptr), + getQueryObjectiv(nullptr), + getQueryObjectuiv(nullptr), + getQueryiv(nullptr), + isBuffer(nullptr), + isQuery(nullptr), + mapBuffer(nullptr), + unmapBuffer(nullptr), + + attachShader(nullptr), + bindAttribLocation(nullptr), + blendEquationSeparate(nullptr), + compileShader(nullptr), + createProgram(nullptr), + createShader(nullptr), + deleteProgram(nullptr), + deleteShader(nullptr), + detachShader(nullptr), + disableVertexAttribArray(nullptr), + drawBuffers(nullptr), + enableVertexAttribArray(nullptr), + getActiveAttrib(nullptr), + getActiveUniform(nullptr), + getAttachedShaders(nullptr), + getAttribLocation(nullptr), + getProgramInfoLog(nullptr), + getProgramiv(nullptr), + getShaderInfoLog(nullptr), + getShaderSource(nullptr), + getShaderiv(nullptr), + getUniformLocation(nullptr), + getUniformfv(nullptr), + getUniformiv(nullptr), + getVertexAttribPointerv(nullptr), + getVertexAttribdv(nullptr), + getVertexAttribfv(nullptr), + getVertexAttribiv(nullptr), + isProgram(nullptr), + isShader(nullptr), + linkProgram(nullptr), + shaderSource(nullptr), + stencilFuncSeparate(nullptr), + stencilMaskSeparate(nullptr), + stencilOpSeparate(nullptr), + uniform1f(nullptr), + uniform1fv(nullptr), + uniform1i(nullptr), + uniform1iv(nullptr), + uniform2f(nullptr), + uniform2fv(nullptr), + uniform2i(nullptr), + uniform2iv(nullptr), + uniform3f(nullptr), + uniform3fv(nullptr), + uniform3i(nullptr), + uniform3iv(nullptr), + uniform4f(nullptr), + uniform4fv(nullptr), + uniform4i(nullptr), + uniform4iv(nullptr), + uniformMatrix2fv(nullptr), + uniformMatrix3fv(nullptr), + uniformMatrix4fv(nullptr), + useProgram(nullptr), + validateProgram(nullptr), + vertexAttrib1d(nullptr), + vertexAttrib1dv(nullptr), + vertexAttrib1f(nullptr), + vertexAttrib1fv(nullptr), + vertexAttrib1s(nullptr), + vertexAttrib1sv(nullptr), + vertexAttrib2d(nullptr), + vertexAttrib2dv(nullptr), + vertexAttrib2f(nullptr), + vertexAttrib2fv(nullptr), + vertexAttrib2s(nullptr), + vertexAttrib2sv(nullptr), + vertexAttrib3d(nullptr), + vertexAttrib3dv(nullptr), + vertexAttrib3f(nullptr), + vertexAttrib3fv(nullptr), + vertexAttrib3s(nullptr), + vertexAttrib3sv(nullptr), + vertexAttrib4Nbv(nullptr), + vertexAttrib4Niv(nullptr), + vertexAttrib4Nsv(nullptr), + vertexAttrib4Nub(nullptr), + vertexAttrib4Nubv(nullptr), + vertexAttrib4Nuiv(nullptr), + vertexAttrib4Nusv(nullptr), + vertexAttrib4bv(nullptr), + vertexAttrib4d(nullptr), + vertexAttrib4dv(nullptr), + vertexAttrib4f(nullptr), + vertexAttrib4fv(nullptr), + vertexAttrib4iv(nullptr), + vertexAttrib4s(nullptr), + vertexAttrib4sv(nullptr), + vertexAttrib4ubv(nullptr), + vertexAttrib4uiv(nullptr), + vertexAttrib4usv(nullptr), + vertexAttribPointer(nullptr), + + uniformMatrix2x3fv(nullptr), + uniformMatrix2x4fv(nullptr), + uniformMatrix3x2fv(nullptr), + uniformMatrix3x4fv(nullptr), + uniformMatrix4x2fv(nullptr), + uniformMatrix4x3fv(nullptr), + + beginConditionalRender(nullptr), + beginTransformFeedback(nullptr), + bindBufferBase(nullptr), + bindBufferRange(nullptr), + bindFragDataLocation(nullptr), + bindFramebuffer(nullptr), + bindRenderbuffer(nullptr), + bindVertexArray(nullptr), + blitFramebuffer(nullptr), + checkFramebufferStatus(nullptr), + clampColor(nullptr), + clearBufferfi(nullptr), + clearBufferfv(nullptr), + clearBufferiv(nullptr), + clearBufferuiv(nullptr), + colorMaski(nullptr), + deleteFramebuffers(nullptr), + deleteRenderbuffers(nullptr), + deleteVertexArrays(nullptr), + disablei(nullptr), + enablei(nullptr), + endConditionalRender(nullptr), + endTransformFeedback(nullptr), + flushMappedBufferRange(nullptr), + framebufferRenderbuffer(nullptr), + framebufferTexture1D(nullptr), + framebufferTexture2D(nullptr), + framebufferTexture3D(nullptr), + framebufferTextureLayer(nullptr), + genFramebuffers(nullptr), + genRenderbuffers(nullptr), + genVertexArrays(nullptr), + generateMipmap(nullptr), + getBooleani_v(nullptr), + getFragDataLocation(nullptr), + getFramebufferAttachmentParameteriv(nullptr), + getIntegeri_v(nullptr), + getRenderbufferParameteriv(nullptr), + getStringi(nullptr), + getTexParameterIiv(nullptr), + getTexParameterIuiv(nullptr), + getTransformFeedbackVarying(nullptr), + getUniformuiv(nullptr), + getVertexAttribIiv(nullptr), + getVertexAttribIuiv(nullptr), + isEnabledi(nullptr), + isFramebuffer(nullptr), + isRenderbuffer(nullptr), + isVertexArray(nullptr), + mapBufferRange(nullptr), + renderbufferStorage(nullptr), + renderbufferStorageMultisample(nullptr), + texParameterIiv(nullptr), + texParameterIuiv(nullptr), + transformFeedbackVaryings(nullptr), + uniform1ui(nullptr), + uniform1uiv(nullptr), + uniform2ui(nullptr), + uniform2uiv(nullptr), + uniform3ui(nullptr), + uniform3uiv(nullptr), + uniform4ui(nullptr), + uniform4uiv(nullptr), + vertexAttribI1i(nullptr), + vertexAttribI1iv(nullptr), + vertexAttribI1ui(nullptr), + vertexAttribI1uiv(nullptr), + vertexAttribI2i(nullptr), + vertexAttribI2iv(nullptr), + vertexAttribI2ui(nullptr), + vertexAttribI2uiv(nullptr), + vertexAttribI3i(nullptr), + vertexAttribI3iv(nullptr), + vertexAttribI3ui(nullptr), + vertexAttribI3uiv(nullptr), + vertexAttribI4bv(nullptr), + vertexAttribI4i(nullptr), + vertexAttribI4iv(nullptr), + vertexAttribI4sv(nullptr), + vertexAttribI4ubv(nullptr), + vertexAttribI4ui(nullptr), + vertexAttribI4uiv(nullptr), + vertexAttribI4usv(nullptr), + vertexAttribIPointer(nullptr), + + copyBufferSubData(nullptr), + drawArraysInstanced(nullptr), + drawElementsInstanced(nullptr), + getActiveUniformBlockName(nullptr), + getActiveUniformBlockiv(nullptr), + getActiveUniformName(nullptr), + getActiveUniformsiv(nullptr), + getUniformBlockIndex(nullptr), + getUniformIndices(nullptr), + primitiveRestartIndex(nullptr), + texBuffer(nullptr), + uniformBlockBinding(nullptr), + + clientWaitSync(nullptr), + deleteSync(nullptr), + drawElementsBaseVertex(nullptr), + drawElementsInstancedBaseVertex(nullptr), + drawRangeElementsBaseVertex(nullptr), + fenceSync(nullptr), + framebufferTexture(nullptr), + getBufferParameteri64v(nullptr), + getInteger64i_v(nullptr), + getInteger64v(nullptr), + getMultisamplefv(nullptr), + getSynciv(nullptr), + isSync(nullptr), + multiDrawElementsBaseVertex(nullptr), + provokingVertex(nullptr), + sampleMaski(nullptr), + texImage2DMultisample(nullptr), + texImage3DMultisample(nullptr), + waitSync(nullptr), + + matrixLoadEXT(nullptr), + genPathsNV(nullptr), + delPathsNV(nullptr), + pathCommandsNV(nullptr), + setPathParameterfNV(nullptr), + setPathParameteriNV(nullptr), + getPathParameterfNV(nullptr), + getPathParameteriNV(nullptr), + pathStencilFuncNV(nullptr), + stencilFillPathNV(nullptr), + stencilStrokePathNV(nullptr), + coverFillPathNV(nullptr), + coverStrokePathNV(nullptr), + stencilThenCoverFillPathNV(nullptr), + stencilThenCoverStrokePathNV(nullptr), + coverFillPathInstancedNV(nullptr), + coverStrokePathInstancedNV(nullptr), + stencilFillPathInstancedNV(nullptr), + stencilStrokePathInstancedNV(nullptr), + stencilThenCoverFillPathInstancedNV(nullptr), + stencilThenCoverStrokePathInstancedNV(nullptr), + programPathFragmentInputGenNV(nullptr), + + bindFragDataLocationIndexed(nullptr), + bindSampler(nullptr), + deleteSamplers(nullptr), + genSamplers(nullptr), + getFragDataIndex(nullptr), + getQueryObjecti64v(nullptr), + getQueryObjectui64v(nullptr), + getSamplerParameterIiv(nullptr), + getSamplerParameterIuiv(nullptr), + getSamplerParameterfv(nullptr), + getSamplerParameteriv(nullptr), + isSampler(nullptr), + queryCounter(nullptr), + samplerParameterIiv(nullptr), + samplerParameterIuiv(nullptr), + samplerParameterf(nullptr), + samplerParameterfv(nullptr), + samplerParameteri(nullptr), + samplerParameteriv(nullptr), + vertexAttribDivisor(nullptr), + vertexAttribP1ui(nullptr), + vertexAttribP1uiv(nullptr), + vertexAttribP2ui(nullptr), + vertexAttribP2uiv(nullptr), + vertexAttribP3ui(nullptr), + vertexAttribP3uiv(nullptr), + vertexAttribP4ui(nullptr), + vertexAttribP4uiv(nullptr), + + beginQueryIndexed(nullptr), + bindTransformFeedback(nullptr), + blendEquationSeparatei(nullptr), + blendEquationi(nullptr), + blendFuncSeparatei(nullptr), + blendFunci(nullptr), + deleteTransformFeedbacks(nullptr), + drawArraysIndirect(nullptr), + drawElementsIndirect(nullptr), + drawTransformFeedback(nullptr), + drawTransformFeedbackStream(nullptr), + endQueryIndexed(nullptr), + genTransformFeedbacks(nullptr), + getActiveSubroutineName(nullptr), + getActiveSubroutineUniformName(nullptr), + getActiveSubroutineUniformiv(nullptr), + getProgramStageiv(nullptr), + getQueryIndexediv(nullptr), + getSubroutineIndex(nullptr), + getSubroutineUniformLocation(nullptr), + getUniformSubroutineuiv(nullptr), + getUniformdv(nullptr), + isTransformFeedback(nullptr), + minSampleShading(nullptr), + patchParameterfv(nullptr), + patchParameteri(nullptr), + pauseTransformFeedback(nullptr), + resumeTransformFeedback(nullptr), + uniform1d(nullptr), + uniform1dv(nullptr), + uniform2d(nullptr), + uniform2dv(nullptr), + uniform3d(nullptr), + uniform3dv(nullptr), + uniform4d(nullptr), + uniform4dv(nullptr), + uniformMatrix2dv(nullptr), + uniformMatrix2x3dv(nullptr), + uniformMatrix2x4dv(nullptr), + uniformMatrix3dv(nullptr), + uniformMatrix3x2dv(nullptr), + uniformMatrix3x4dv(nullptr), + uniformMatrix4dv(nullptr), + uniformMatrix4x2dv(nullptr), + uniformMatrix4x3dv(nullptr), + uniformSubroutinesuiv(nullptr), + + activeShaderProgram(nullptr), + bindProgramPipeline(nullptr), + clearDepthf(nullptr), + createShaderProgramv(nullptr), + deleteProgramPipelines(nullptr), + depthRangeArrayv(nullptr), + depthRangeIndexed(nullptr), + depthRangef(nullptr), + genProgramPipelines(nullptr), + getDoublei_v(nullptr), + getFloati_v(nullptr), + getProgramBinary(nullptr), + getProgramPipelineInfoLog(nullptr), + getProgramPipelineiv(nullptr), + getShaderPrecisionFormat(nullptr), + getVertexAttribLdv(nullptr), + isProgramPipeline(nullptr), + programBinary(nullptr), + programParameteri(nullptr), + programUniform1d(nullptr), + programUniform1dv(nullptr), + programUniform1f(nullptr), + programUniform1fv(nullptr), + programUniform1i(nullptr), + programUniform1iv(nullptr), + programUniform1ui(nullptr), + programUniform1uiv(nullptr), + programUniform2d(nullptr), + programUniform2dv(nullptr), + programUniform2f(nullptr), + programUniform2fv(nullptr), + programUniform2i(nullptr), + programUniform2iv(nullptr), + programUniform2ui(nullptr), + programUniform2uiv(nullptr), + programUniform3d(nullptr), + programUniform3dv(nullptr), + programUniform3f(nullptr), + programUniform3fv(nullptr), + programUniform3i(nullptr), + programUniform3iv(nullptr), + programUniform3ui(nullptr), + programUniform3uiv(nullptr), + programUniform4d(nullptr), + programUniform4dv(nullptr), + programUniform4f(nullptr), + programUniform4fv(nullptr), + programUniform4i(nullptr), + programUniform4iv(nullptr), + programUniform4ui(nullptr), + programUniform4uiv(nullptr), + programUniformMatrix2dv(nullptr), + programUniformMatrix2fv(nullptr), + programUniformMatrix2x3dv(nullptr), + programUniformMatrix2x3fv(nullptr), + programUniformMatrix2x4dv(nullptr), + programUniformMatrix2x4fv(nullptr), + programUniformMatrix3dv(nullptr), + programUniformMatrix3fv(nullptr), + programUniformMatrix3x2dv(nullptr), + programUniformMatrix3x2fv(nullptr), + programUniformMatrix3x4dv(nullptr), + programUniformMatrix3x4fv(nullptr), + programUniformMatrix4dv(nullptr), + programUniformMatrix4fv(nullptr), + programUniformMatrix4x2dv(nullptr), + programUniformMatrix4x2fv(nullptr), + programUniformMatrix4x3dv(nullptr), + programUniformMatrix4x3fv(nullptr), + releaseShaderCompiler(nullptr), + scissorArrayv(nullptr), + scissorIndexed(nullptr), + scissorIndexedv(nullptr), + shaderBinary(nullptr), + useProgramStages(nullptr), + validateProgramPipeline(nullptr), + vertexAttribL1d(nullptr), + vertexAttribL1dv(nullptr), + vertexAttribL2d(nullptr), + vertexAttribL2dv(nullptr), + vertexAttribL3d(nullptr), + vertexAttribL3dv(nullptr), + vertexAttribL4d(nullptr), + vertexAttribL4dv(nullptr), + vertexAttribLPointer(nullptr), + viewportArrayv(nullptr), + viewportIndexedf(nullptr), + viewportIndexedfv(nullptr), + + bindImageTexture(nullptr), + drawArraysInstancedBaseInstance(nullptr), + drawElementsInstancedBaseInstance(nullptr), + drawElementsInstancedBaseVertexBaseInstance(nullptr), + drawTransformFeedbackInstanced(nullptr), + drawTransformFeedbackStreamInstanced(nullptr), + getActiveAtomicCounterBufferiv(nullptr), + getInternalformativ(nullptr), + memoryBarrier(nullptr), + texStorage1D(nullptr), + texStorage2D(nullptr), + texStorage3D(nullptr), + + bindVertexBuffer(nullptr), + clearBufferData(nullptr), + clearBufferSubData(nullptr), + copyImageSubData(nullptr), + debugMessageCallback(nullptr), + debugMessageControl(nullptr), + debugMessageInsert(nullptr), + dispatchCompute(nullptr), + dispatchComputeIndirect(nullptr), + framebufferParameteri(nullptr), + getDebugMessageLog(nullptr), + getFramebufferParameteriv(nullptr), + getInternalformati64v(nullptr), + getPointerv(nullptr), + getObjectLabel(nullptr), + getObjectPtrLabel(nullptr), + getProgramInterfaceiv(nullptr), + getProgramResourceIndex(nullptr), + getProgramResourceLocation(nullptr), + getProgramResourceLocationIndex(nullptr), + getProgramResourceName(nullptr), + getProgramResourceiv(nullptr), + invalidateBufferData(nullptr), + invalidateBufferSubData(nullptr), + invalidateFramebuffer(nullptr), + invalidateSubFramebuffer(nullptr), + invalidateTexImage(nullptr), + invalidateTexSubImage(nullptr), + multiDrawArraysIndirect(nullptr), + multiDrawElementsIndirect(nullptr), + objectLabel(nullptr), + objectPtrLabel(nullptr), + popDebugGroup(nullptr), + pushDebugGroup(nullptr), + shaderStorageBlockBinding(nullptr), + texBufferRange(nullptr), + texStorage2DMultisample(nullptr), + texStorage3DMultisample(nullptr), + textureView(nullptr), + vertexAttribBinding(nullptr), + vertexAttribFormat(nullptr), + vertexAttribIFormat(nullptr), + vertexAttribLFormat(nullptr), + vertexBindingDivisor(nullptr), + coverageModulationNV(nullptr), + + bindBuffersBase(nullptr), + bindBuffersRange(nullptr), + bindImageTextures(nullptr), + bindSamplers(nullptr), + bindTextures(nullptr), + bindVertexBuffers(nullptr), + bufferStorage(nullptr), + clearTexImage(nullptr), + clearTexSubImage(nullptr), + + bindTextureUnit(nullptr), + blitNamedFramebuffer(nullptr), + checkNamedFramebufferStatus(nullptr), + clearNamedBufferData(nullptr), + clearNamedBufferSubData(nullptr), + clearNamedFramebufferfi(nullptr), + clearNamedFramebufferfv(nullptr), + clearNamedFramebufferiv(nullptr), + clearNamedFramebufferuiv(nullptr), + clipControl(nullptr), + compressedTextureSubImage1D(nullptr), + compressedTextureSubImage2D(nullptr), + compressedTextureSubImage3D(nullptr), + copyNamedBufferSubData(nullptr), + copyTextureSubImage1D(nullptr), + copyTextureSubImage2D(nullptr), + copyTextureSubImage3D(nullptr), + createBuffers(nullptr), + createFramebuffers(nullptr), + createProgramPipelines(nullptr), + createQueries(nullptr), + createRenderbuffers(nullptr), + createSamplers(nullptr), + createTextures(nullptr), + createTransformFeedbacks(nullptr), + createVertexArrays(nullptr), + disableVertexArrayAttrib(nullptr), + enableVertexArrayAttrib(nullptr), + flushMappedNamedBufferRange(nullptr), + generateTextureMipmap(nullptr), + getCompressedTextureImage(nullptr), + getCompressedTextureSubImage(nullptr), + getGraphicsResetStatus(nullptr), + getNamedBufferParameteri64v(nullptr), + getNamedBufferParameteriv(nullptr), + getNamedBufferPointerv(nullptr), + getNamedBufferSubData(nullptr), + getNamedFramebufferAttachmentParameteriv(nullptr), + getNamedFramebufferParameteriv(nullptr), + getNamedRenderbufferParameteriv(nullptr), + getQueryBufferObjecti64v(nullptr), + getQueryBufferObjectiv(nullptr), + getQueryBufferObjectui64v(nullptr), + getQueryBufferObjectuiv(nullptr), + getTextureImage(nullptr), + getTextureLevelParameterfv(nullptr), + getTextureLevelParameteriv(nullptr), + getTextureParameterIiv(nullptr), + getTextureParameterIuiv(nullptr), + getTextureParameterfv(nullptr), + getTextureParameteriv(nullptr), + getTextureSubImage(nullptr), + getTransformFeedbacki64_v(nullptr), + getTransformFeedbacki_v(nullptr), + getTransformFeedbackiv(nullptr), + getVertexArrayIndexed64iv(nullptr), + getVertexArrayIndexediv(nullptr), + getVertexArrayiv(nullptr), + getnCompressedTexImage(nullptr), + getnTexImage(nullptr), + getnUniformdv(nullptr), + getnUniformfv(nullptr), + getnUniformiv(nullptr), + getnUniformuiv(nullptr), + invalidateNamedFramebufferData(nullptr), + invalidateNamedFramebufferSubData(nullptr), + mapNamedBuffer(nullptr), + mapNamedBufferRange(nullptr), + memoryBarrierByRegion(nullptr), + namedBufferData(nullptr), + namedBufferStorage(nullptr), + namedBufferSubData(nullptr), + namedFramebufferDrawBuffer(nullptr), + namedFramebufferDrawBuffers(nullptr), + namedFramebufferParameteri(nullptr), + namedFramebufferReadBuffer(nullptr), + namedFramebufferRenderbuffer(nullptr), + namedFramebufferTexture(nullptr), + namedFramebufferTextureLayer(nullptr), + namedRenderbufferStorage(nullptr), + namedRenderbufferStorageMultisample(nullptr), + readnPixels(nullptr), + textureBarrier(nullptr), + textureBuffer(nullptr), + textureBufferRange(nullptr), + textureParameterIiv(nullptr), + textureParameterIuiv(nullptr), + textureParameterf(nullptr), + textureParameterfv(nullptr), + textureParameteri(nullptr), + textureParameteriv(nullptr), + textureStorage1D(nullptr), + textureStorage2D(nullptr), + textureStorage2DMultisample(nullptr), + textureStorage3D(nullptr), + textureStorage3DMultisample(nullptr), + textureSubImage1D(nullptr), + textureSubImage2D(nullptr), + textureSubImage3D(nullptr), + transformFeedbackBufferBase(nullptr), + transformFeedbackBufferRange(nullptr), + unmapNamedBuffer(nullptr), + vertexArrayAttribBinding(nullptr), + vertexArrayAttribFormat(nullptr), + vertexArrayAttribIFormat(nullptr), + vertexArrayAttribLFormat(nullptr), + vertexArrayBindingDivisor(nullptr), + vertexArrayElementBuffer(nullptr), + vertexArrayVertexBuffer(nullptr), + vertexArrayVertexBuffers(nullptr), + blendBarrier(nullptr), + primitiveBoundingBox(nullptr), + eglImageTargetRenderbufferStorageOES(nullptr), + eglImageTargetTexture2DOES(nullptr) +{ +} + +FunctionsGL::~FunctionsGL() +{ +} + +void FunctionsGL::initialize() +{ + // Grab the version number + AssignGLEntryPoint(loadProcAddress("glGetString"), &getString); + AssignGLEntryPoint(loadProcAddress("glGetIntegerv"), &getIntegerv); + GetGLVersion(getString, &version, &standard); + + // Grab the GL extensions + if (isAtLeastGL(gl::Version(3, 0)) || isAtLeastGLES(gl::Version(3, 0))) + { + AssignGLEntryPoint(loadProcAddress("glGetStringi"), &getStringi); + extensions = GetIndexedExtensions(getIntegerv, getStringi); + } + else + { + const char *exts = reinterpret_cast<const char*>(getString(GL_EXTENSIONS)); + angle::SplitStringAlongWhitespace(std::string(exts), &extensions); + } + + // Load the entry points + switch (standard) + { + case STANDARD_GL_DESKTOP: + initializeProcsDesktopGL(); + break; + + case STANDARD_GL_ES: + initializeProcsGLES(); + break; + + default: + UNREACHABLE(); + break; + } +} + +void FunctionsGL::initializeProcsDesktopGL() +{ + // Check the context profile + profile = 0; + if (isAtLeastGL(gl::Version(3, 2))) + { + getIntegerv(GL_CONTEXT_PROFILE_MASK, &profile); + } + + // clang-format off + + // Load extensions + // Even though extensions are written against specific versions of GL, many drivers expose the extensions + // in even older versions. Always try loading the extensions regardless of GL version. + + // GL_ARB_program_interface_query (loading only functions relevant to GL_NV_path_rendering here) + AssignGLExtensionEntryPoint(extensions, "GL_ARB_program_interface_query", loadProcAddress("glGetProgramInterfaceiv"), &getProgramInterfaceiv); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_program_interface_query", loadProcAddress("glGetProgramResourceName"), &getProgramResourceName); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_program_interface_query", loadProcAddress("glGetProgramResourceiv"), &getProgramResourceiv); + + // GL_NV_path_rendering + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glMatrixLoadfEXT"), &matrixLoadEXT); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGenPathsNV"), &genPathsNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glDeletePathsNV"), &delPathsNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathCommandsNV"), &pathCommandsNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glIsPathNV"), &isPathNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathParameterfNV"), &setPathParameterfNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathParameteriNV"), &setPathParameteriNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGetPathParameterfvNV"), &getPathParameterfNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGetPathParameterivNV"), &getPathParameteriNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathStencilFuncNV"), &pathStencilFuncNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilFillPathNV"), &stencilFillPathNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilStrokePathNV"), &stencilStrokePathNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverFillPathNV"), &coverFillPathNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverStrokePathNV"), &coverStrokePathNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverFillPathNV"), &stencilThenCoverFillPathNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverStrokePathNV"), &stencilThenCoverStrokePathNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverFillPathInstancedNV"), &coverFillPathInstancedNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverStrokePathInstancedNV"), &coverStrokePathInstancedNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilFillPathInstancedNV"), &stencilFillPathInstancedNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilStrokePathInstancedNV"), &stencilStrokePathInstancedNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverFillPathInstancedNV"), &stencilThenCoverFillPathInstancedNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverStrokePathInstancedNV"), &stencilThenCoverStrokePathInstancedNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glProgramPathFragmentInputGenNV"), &programPathFragmentInputGenNV); + + // GL_NV_framebuffer_mixed_samples + AssignGLExtensionEntryPoint(extensions, "GL_NV_framebuffer_mixed_samples", loadProcAddress("glCoverageModulationNV"), &coverageModulationNV); + + // GL_NV_fence + AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glDeleteFencesNV"), &deleteFencesNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glGenFencesNV"), &genFencesNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glIsFenceNV"), &isFenceNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glTestFenceNV"), &testFenceNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glGetFenceivNV"), &getFenceivNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glFinishFenceNV"), &finishFenceNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glSetFenceNV"), &setFenceNV); + + // GL_EXT_texture_storage + AssignGLExtensionEntryPoint(extensions, "GL_EXT_texture_storage", loadProcAddress("glTexStorage1DEXT"), &texStorage1D); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_texture_storage", loadProcAddress("glTexStorage2DEXT"), &texStorage2D); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_texture_storage GL_EXT_texture3D", loadProcAddress("glTexStorage3DEXT"), &texStorage3D); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_texture_storage GL_EXT_direct_state_access", loadProcAddress("glTextureStorage1DEXT"), &textureStorage1D); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_texture_storage GL_EXT_direct_state_access", loadProcAddress("glTextureStorage2DEXT"), &textureStorage2D); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_texture_storage GL_EXT_direct_state_access GL_EXT_texture3D", loadProcAddress("glTextureStorage3DEXT"), &textureStorage3D); + + // GL_ARB_vertex_array_object + AssignGLExtensionEntryPoint(extensions, "GL_ARB_vertex_array_object", loadProcAddress("glBindVertexArray"), &bindVertexArray); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_vertex_array_object", loadProcAddress("glDeleteVertexArrays"), &deleteVertexArrays); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_vertex_array_object", loadProcAddress("glGenVertexArrays"), &genVertexArrays); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_vertex_array_object", loadProcAddress("glIsVertexArray"), &isVertexArray); + + // GL_ARB_sync + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sync", loadProcAddress("glClientWaitSync"), &clientWaitSync); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sync", loadProcAddress("glDeleteSync"), &deleteSync); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sync", loadProcAddress("glFenceSync"), &fenceSync); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sync", loadProcAddress("glGetInteger64i_v"), &getInteger64i_v); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sync", loadProcAddress("glGetInteger64v"), &getInteger64v); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sync", loadProcAddress("glGetSynciv"), &getSynciv); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sync", loadProcAddress("glIsSync"), &isSync); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sync", loadProcAddress("glWaitSync"), &waitSync); + + // GL_EXT_framebuffer_object + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glIsRenderbufferEXT"), &isRenderbuffer); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glBindRenderbufferEXT"), &bindRenderbuffer); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glDeleteRenderbuffersEXT"), &deleteRenderbuffers); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glGenRenderbuffersEXT"), &genRenderbuffers); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glRenderbufferStorageEXT"), &renderbufferStorage); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glGetRenderbufferParameterivEXT"), &getRenderbufferParameteriv); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glIsFramebufferEXT"), &isFramebuffer); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glBindFramebufferEXT"), &bindFramebuffer); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glDeleteFramebuffersEXT"), &deleteFramebuffers); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glGenFramebuffersEXT"), &genFramebuffers); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glCheckFramebufferStatusEXT"), &checkFramebufferStatus); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glFramebufferTexture1DEXT"), &framebufferTexture1D); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glFramebufferTexture2DEXT"), &framebufferTexture2D); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glFramebufferTexture3DEXT"), &framebufferTexture3D); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glFramebufferRenderbufferEXT"), &framebufferRenderbuffer); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glGetFramebufferAttachmentParameterivEXT"), &getFramebufferAttachmentParameteriv); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glGenerateMipmapEXT"), &generateMipmap); + + // GL_EXT_framebuffer_blit + AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_blit", loadProcAddress("glBlitFramebufferEXT"), &blitFramebuffer); + + // GL_KHR_debug + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glDebugMessageControl"), &debugMessageControl); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glDebugMessageInsert"), &debugMessageInsert); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glDebugMessageCallback"), &debugMessageCallback); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glGetDebugMessageLog"), &getDebugMessageLog); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glGetPointerv"), &getPointerv); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glPushDebugGroup"), &pushDebugGroup); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glPopDebugGroup"), &popDebugGroup); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glObjectLabel"), &objectLabel); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glGetObjectLabel"), &getObjectLabel); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glObjectPtrLabel"), &objectPtrLabel); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glGetObjectPtrLabel"), &getObjectPtrLabel); + + // GL_ARB_internalformat_query + AssignGLExtensionEntryPoint(extensions, "GL_ARB_internalformat_query", loadProcAddress("glGetInternalformativ"), &getInternalformativ); + + // GL_ARB_ES2_compatibility + AssignGLExtensionEntryPoint(extensions, "GL_ARB_ES2_compatibility", loadProcAddress("glReleaseShaderCompiler"), &releaseShaderCompiler); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_ES2_compatibility", loadProcAddress("glShaderBinary"), &shaderBinary); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_ES2_compatibility", loadProcAddress("glGetShaderPrecisionFormat"), &getShaderPrecisionFormat); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_ES2_compatibility", loadProcAddress("glDepthRangef"), &depthRangef); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_ES2_compatibility", loadProcAddress("glClearDepthf"), &clearDepthf); + + // GL_ARB_instanced_arrays + AssignGLExtensionEntryPoint(extensions, "GL_ARB_instanced_arrays", loadProcAddress("glVertexAttribDivisorARB"), &vertexAttribDivisor); + + // GL_EXT_draw_instanced + AssignGLExtensionEntryPoint(extensions, "GL_EXT_draw_instanced", loadProcAddress("glDrawArraysInstancedEXT"), &drawArraysInstanced); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_draw_instanced", loadProcAddress("glDrawElementsInstancedEXT"), &drawElementsInstanced); + + // GL_ARB_draw_instanced + AssignGLExtensionEntryPoint(extensions, "GL_ARB_draw_instanced", loadProcAddress("glDrawArraysInstancedARB"), &drawArraysInstanced); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_draw_instanced", loadProcAddress("glDrawElementsInstancedARB"), &drawElementsInstanced); + + // GL_ARB_sampler_objects + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glGenSamplers"), &genSamplers); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glDeleteSamplers"), &deleteSamplers); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glIsSampler"), &isSampler); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glBindSampler"), &bindSampler); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glSamplerParameteri"), &samplerParameteri); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glSamplerParameterf"), &samplerParameterf); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glSamplerParameteriv"), &samplerParameteriv); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glSamplerParameterfv"), &samplerParameterfv); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glSamplerParameterIiv"), &samplerParameterIiv); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glSamplerParameterIuiv"), &samplerParameterIuiv); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glGetSamplerParameteriv"), &getSamplerParameteriv); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glGetSamplerParameterfv"), &getSamplerParameterfv); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glGetSamplerParameterIiv"), &getSamplerParameterIiv); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glGetSamplerParameterIuiv"), &getSamplerParameterIuiv); + + // GL_ARB_occlusion_query + AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGenQueriesARB"), &genQueries); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glDeleteQueriesARB"), &deleteQueries); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glIsQueryARB"), &isQuery); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glBeginQueryARB"), &beginQuery); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glEndQueryARB"), &endQuery); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGetQueryivARB"), &getQueryiv); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGetQueryObjectivARB"), &getQueryObjectiv); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGetQueryObjectuivARB"), &getQueryObjectuiv); + + // EXT_transform_feedback + AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glBindBufferRangeEXT"), &bindBufferRange); + AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glBindBufferBaseEXT"), &bindBufferBase); + AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glBeginTransformFeedbackEXT"), &beginTransformFeedback); + AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glEndTransformFeedbackEXT"), &endTransformFeedback); + AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glTransformFeedbackVaryingsEXT"), &transformFeedbackVaryings); + AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glGetTransformFeedbackVaryingEXT"), &getTransformFeedbackVarying); + + // GL_ARB_transform_feedback2 + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glBindTransformFeedback"), &bindTransformFeedback); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glDeleteTransformFeedbacks"), &deleteTransformFeedbacks); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glGenTransformFeedbacks"), &genTransformFeedbacks); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glIsTransformFeedback"), &isTransformFeedback); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glPauseTransformFeedback"), &pauseTransformFeedback); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glResumeTransformFeedback"), &resumeTransformFeedback); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glDrawTransformFeedback"), &drawTransformFeedback); + + // GL_ARB_transform_feedback3 + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glDrawTransformFeedbackStream"), &drawTransformFeedbackStream); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glBeginQueryIndexed"), &beginQueryIndexed); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glEndQueryIndexed"), &endQueryIndexed); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glGetQueryIndexediv"), &getQueryIndexediv); + + // GL_ARB_get_program_binary + AssignGLExtensionEntryPoint(extensions, "GL_ARB_get_program_binary", loadProcAddress("glGetProgramBinary"), &getProgramBinary); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_get_program_binary", loadProcAddress("glProgramBinary"), &programBinary); + AssignGLExtensionEntryPoint(extensions, "GL_ARB_get_program_binary", loadProcAddress("glProgramParameteri"), &programParameteri); + + // GL_ARB_robustness + AssignGLExtensionEntryPoint(extensions, "GL_ARB_robustness", loadProcAddress("glGetGraphicsResetStatusARB"), &getGraphicsResetStatus); + + // GL_KHR_robustness + AssignGLExtensionEntryPoint(extensions, "GL_KHR_robustness", loadProcAddress("glGetGraphicsResetStatus"), &getGraphicsResetStatus); + + // 1.0 + if (isAtLeastGL(gl::Version(1, 0))) + { + AssignGLEntryPoint(loadProcAddress("glBlendFunc"), &blendFunc); + AssignGLEntryPoint(loadProcAddress("glClear"), &clear); + AssignGLEntryPoint(loadProcAddress("glClearColor"), &clearColor); + AssignGLEntryPoint(loadProcAddress("glClearDepth"), &clearDepth); + AssignGLEntryPoint(loadProcAddress("glClearStencil"), &clearStencil); + AssignGLEntryPoint(loadProcAddress("glColorMask"), &colorMask); + AssignGLEntryPoint(loadProcAddress("glCullFace"), &cullFace); + AssignGLEntryPoint(loadProcAddress("glDepthFunc"), &depthFunc); + AssignGLEntryPoint(loadProcAddress("glDepthMask"), &depthMask); + AssignGLEntryPoint(loadProcAddress("glDepthRange"), &depthRange); + AssignGLEntryPoint(loadProcAddress("glDisable"), &disable); + AssignGLEntryPoint(loadProcAddress("glDrawBuffer"), &drawBuffer); + AssignGLEntryPoint(loadProcAddress("glEnable"), &enable); + AssignGLEntryPoint(loadProcAddress("glFinish"), &finish); + AssignGLEntryPoint(loadProcAddress("glFlush"), &flush); + AssignGLEntryPoint(loadProcAddress("glFrontFace"), &frontFace); + AssignGLEntryPoint(loadProcAddress("glGetBooleanv"), &getBooleanv); + AssignGLEntryPoint(loadProcAddress("glGetDoublev"), &getDoublev); + AssignGLEntryPoint(loadProcAddress("glGetError"), &getError); + AssignGLEntryPoint(loadProcAddress("glGetFloatv"), &getFloatv); + AssignGLEntryPoint(loadProcAddress("glGetIntegerv"), &getIntegerv); + AssignGLEntryPoint(loadProcAddress("glGetString"), &getString); + AssignGLEntryPoint(loadProcAddress("glGetTexImage"), &getTexImage); + AssignGLEntryPoint(loadProcAddress("glGetTexLevelParameterfv"), &getTexLevelParameterfv); + AssignGLEntryPoint(loadProcAddress("glGetTexLevelParameteriv"), &getTexLevelParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetTexParameterfv"), &getTexParameterfv); + AssignGLEntryPoint(loadProcAddress("glGetTexParameteriv"), &getTexParameteriv); + AssignGLEntryPoint(loadProcAddress("glHint"), &hint); + AssignGLEntryPoint(loadProcAddress("glIsEnabled"), &isEnabled); + AssignGLEntryPoint(loadProcAddress("glLineWidth"), &lineWidth); + AssignGLEntryPoint(loadProcAddress("glLogicOp"), &logicOp); + AssignGLEntryPoint(loadProcAddress("glPixelStoref"), &pixelStoref); + AssignGLEntryPoint(loadProcAddress("glPixelStorei"), &pixelStorei); + AssignGLEntryPoint(loadProcAddress("glPointSize"), &pointSize); + AssignGLEntryPoint(loadProcAddress("glPolygonMode"), &polygonMode); + AssignGLEntryPoint(loadProcAddress("glReadBuffer"), &readBuffer); + AssignGLEntryPoint(loadProcAddress("glReadPixels"), &readPixels); + AssignGLEntryPoint(loadProcAddress("glScissor"), &scissor); + AssignGLEntryPoint(loadProcAddress("glStencilFunc"), &stencilFunc); + AssignGLEntryPoint(loadProcAddress("glStencilMask"), &stencilMask); + AssignGLEntryPoint(loadProcAddress("glStencilOp"), &stencilOp); + AssignGLEntryPoint(loadProcAddress("glTexImage1D"), &texImage1D); + AssignGLEntryPoint(loadProcAddress("glTexImage2D"), &texImage2D); + AssignGLEntryPoint(loadProcAddress("glTexParameterf"), &texParameterf); + AssignGLEntryPoint(loadProcAddress("glTexParameterfv"), &texParameterfv); + AssignGLEntryPoint(loadProcAddress("glTexParameteri"), &texParameteri); + AssignGLEntryPoint(loadProcAddress("glTexParameteriv"), &texParameteriv); + AssignGLEntryPoint(loadProcAddress("glViewport"), &viewport); + } + + // 1.1 + if (isAtLeastGL(gl::Version(1, 1))) + { + AssignGLEntryPoint(loadProcAddress("glBindTexture"), &bindTexture); + AssignGLEntryPoint(loadProcAddress("glCopyTexImage1D"), ©TexImage1D); + AssignGLEntryPoint(loadProcAddress("glCopyTexImage2D"), ©TexImage2D); + AssignGLEntryPoint(loadProcAddress("glCopyTexSubImage1D"), ©TexSubImage1D); + AssignGLEntryPoint(loadProcAddress("glCopyTexSubImage2D"), ©TexSubImage2D); + AssignGLEntryPoint(loadProcAddress("glDeleteTextures"), &deleteTextures); + AssignGLEntryPoint(loadProcAddress("glDrawArrays"), &drawArrays); + AssignGLEntryPoint(loadProcAddress("glDrawElements"), &drawElements); + AssignGLEntryPoint(loadProcAddress("glGenTextures"), &genTextures); + AssignGLEntryPoint(loadProcAddress("glIsTexture"), &isTexture); + AssignGLEntryPoint(loadProcAddress("glPolygonOffset"), &polygonOffset); + AssignGLEntryPoint(loadProcAddress("glTexSubImage1D"), &texSubImage1D); + AssignGLEntryPoint(loadProcAddress("glTexSubImage2D"), &texSubImage2D); + } + + // 1.2 + if (isAtLeastGL(gl::Version(1, 2))) + { + AssignGLEntryPoint(loadProcAddress("glBlendColor"), &blendColor); + AssignGLEntryPoint(loadProcAddress("glBlendEquation"), &blendEquation); + AssignGLEntryPoint(loadProcAddress("glCopyTexSubImage3D"), ©TexSubImage3D); + AssignGLEntryPoint(loadProcAddress("glDrawRangeElements"), &drawRangeElements); + AssignGLEntryPoint(loadProcAddress("glTexImage3D"), &texImage3D); + AssignGLEntryPoint(loadProcAddress("glTexSubImage3D"), &texSubImage3D); + } + + // 1.3 + if (isAtLeastGL(gl::Version(1, 3))) + { + AssignGLEntryPoint(loadProcAddress("glActiveTexture"), &activeTexture); + AssignGLEntryPoint(loadProcAddress("glCompressedTexImage1D"), &compressedTexImage1D); + AssignGLEntryPoint(loadProcAddress("glCompressedTexImage2D"), &compressedTexImage2D); + AssignGLEntryPoint(loadProcAddress("glCompressedTexImage3D"), &compressedTexImage3D); + AssignGLEntryPoint(loadProcAddress("glCompressedTexSubImage1D"), &compressedTexSubImage1D); + AssignGLEntryPoint(loadProcAddress("glCompressedTexSubImage2D"), &compressedTexSubImage2D); + AssignGLEntryPoint(loadProcAddress("glCompressedTexSubImage3D"), &compressedTexSubImage3D); + AssignGLEntryPoint(loadProcAddress("glGetCompressedTexImage"), &getCompressedTexImage); + AssignGLEntryPoint(loadProcAddress("glSampleCoverage"), &sampleCoverage); + } + + // 1.4 + if (isAtLeastGL(gl::Version(1, 4))) + { + AssignGLEntryPoint(loadProcAddress("glBlendFuncSeparate"), &blendFuncSeparate); + AssignGLEntryPoint(loadProcAddress("glMultiDrawArrays"), &multiDrawArrays); + AssignGLEntryPoint(loadProcAddress("glMultiDrawElements"), &multiDrawElements); + AssignGLEntryPoint(loadProcAddress("glPointParameterf"), &pointParameterf); + AssignGLEntryPoint(loadProcAddress("glPointParameterfv"), &pointParameterfv); + AssignGLEntryPoint(loadProcAddress("glPointParameteri"), &pointParameteri); + AssignGLEntryPoint(loadProcAddress("glPointParameteriv"), &pointParameteriv); + } + + // 1.5 + if (isAtLeastGL(gl::Version(1, 5))) + { + AssignGLEntryPoint(loadProcAddress("glBeginQuery"), &beginQuery); + AssignGLEntryPoint(loadProcAddress("glBindBuffer"), &bindBuffer); + AssignGLEntryPoint(loadProcAddress("glBufferData"), &bufferData); + AssignGLEntryPoint(loadProcAddress("glBufferSubData"), &bufferSubData); + AssignGLEntryPoint(loadProcAddress("glDeleteBuffers"), &deleteBuffers); + AssignGLEntryPoint(loadProcAddress("glDeleteQueries"), &deleteQueries); + AssignGLEntryPoint(loadProcAddress("glEndQuery"), &endQuery); + AssignGLEntryPoint(loadProcAddress("glGenBuffers"), &genBuffers); + AssignGLEntryPoint(loadProcAddress("glGenQueries"), &genQueries); + AssignGLEntryPoint(loadProcAddress("glGetBufferParameteriv"), &getBufferParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetBufferPointerv"), &getBufferPointerv); + AssignGLEntryPoint(loadProcAddress("glGetBufferSubData"), &getBufferSubData); + AssignGLEntryPoint(loadProcAddress("glGetQueryObjectiv"), &getQueryObjectiv); + AssignGLEntryPoint(loadProcAddress("glGetQueryObjectuiv"), &getQueryObjectuiv); + AssignGLEntryPoint(loadProcAddress("glGetQueryiv"), &getQueryiv); + AssignGLEntryPoint(loadProcAddress("glIsBuffer"), &isBuffer); + AssignGLEntryPoint(loadProcAddress("glIsQuery"), &isQuery); + AssignGLEntryPoint(loadProcAddress("glMapBuffer"), &mapBuffer); + AssignGLEntryPoint(loadProcAddress("glUnmapBuffer"), &unmapBuffer); + } + + // 2.0 + if (isAtLeastGL(gl::Version(2, 0))) + { + AssignGLEntryPoint(loadProcAddress("glAttachShader"), &attachShader); + AssignGLEntryPoint(loadProcAddress("glBindAttribLocation"), &bindAttribLocation); + AssignGLEntryPoint(loadProcAddress("glBlendEquationSeparate"), &blendEquationSeparate); + AssignGLEntryPoint(loadProcAddress("glCompileShader"), &compileShader); + AssignGLEntryPoint(loadProcAddress("glCreateProgram"), &createProgram); + AssignGLEntryPoint(loadProcAddress("glCreateShader"), &createShader); + AssignGLEntryPoint(loadProcAddress("glDeleteProgram"), &deleteProgram); + AssignGLEntryPoint(loadProcAddress("glDeleteShader"), &deleteShader); + AssignGLEntryPoint(loadProcAddress("glDetachShader"), &detachShader); + AssignGLEntryPoint(loadProcAddress("glDisableVertexAttribArray"), &disableVertexAttribArray); + AssignGLEntryPoint(loadProcAddress("glDrawBuffers"), &drawBuffers); + AssignGLEntryPoint(loadProcAddress("glEnableVertexAttribArray"), &enableVertexAttribArray); + AssignGLEntryPoint(loadProcAddress("glGetActiveAttrib"), &getActiveAttrib); + AssignGLEntryPoint(loadProcAddress("glGetActiveUniform"), &getActiveUniform); + AssignGLEntryPoint(loadProcAddress("glGetAttachedShaders"), &getAttachedShaders); + AssignGLEntryPoint(loadProcAddress("glGetAttribLocation"), &getAttribLocation); + AssignGLEntryPoint(loadProcAddress("glGetProgramInfoLog"), &getProgramInfoLog); + AssignGLEntryPoint(loadProcAddress("glGetProgramiv"), &getProgramiv); + AssignGLEntryPoint(loadProcAddress("glGetShaderInfoLog"), &getShaderInfoLog); + AssignGLEntryPoint(loadProcAddress("glGetShaderSource"), &getShaderSource); + AssignGLEntryPoint(loadProcAddress("glGetShaderiv"), &getShaderiv); + AssignGLEntryPoint(loadProcAddress("glGetUniformLocation"), &getUniformLocation); + AssignGLEntryPoint(loadProcAddress("glGetUniformfv"), &getUniformfv); + AssignGLEntryPoint(loadProcAddress("glGetUniformiv"), &getUniformiv); + AssignGLEntryPoint(loadProcAddress("glGetVertexAttribPointerv"), &getVertexAttribPointerv); + AssignGLEntryPoint(loadProcAddress("glGetVertexAttribdv"), &getVertexAttribdv); + AssignGLEntryPoint(loadProcAddress("glGetVertexAttribfv"), &getVertexAttribfv); + AssignGLEntryPoint(loadProcAddress("glGetVertexAttribiv"), &getVertexAttribiv); + AssignGLEntryPoint(loadProcAddress("glIsProgram"), &isProgram); + AssignGLEntryPoint(loadProcAddress("glIsShader"), &isShader); + AssignGLEntryPoint(loadProcAddress("glLinkProgram"), &linkProgram); + AssignGLEntryPoint(loadProcAddress("glShaderSource"), &shaderSource); + AssignGLEntryPoint(loadProcAddress("glStencilFuncSeparate"), &stencilFuncSeparate); + AssignGLEntryPoint(loadProcAddress("glStencilMaskSeparate"), &stencilMaskSeparate); + AssignGLEntryPoint(loadProcAddress("glStencilOpSeparate"), &stencilOpSeparate); + AssignGLEntryPoint(loadProcAddress("glUniform1f"), &uniform1f); + AssignGLEntryPoint(loadProcAddress("glUniform1fv"), &uniform1fv); + AssignGLEntryPoint(loadProcAddress("glUniform1i"), &uniform1i); + AssignGLEntryPoint(loadProcAddress("glUniform1iv"), &uniform1iv); + AssignGLEntryPoint(loadProcAddress("glUniform2f"), &uniform2f); + AssignGLEntryPoint(loadProcAddress("glUniform2fv"), &uniform2fv); + AssignGLEntryPoint(loadProcAddress("glUniform2i"), &uniform2i); + AssignGLEntryPoint(loadProcAddress("glUniform2iv"), &uniform2iv); + AssignGLEntryPoint(loadProcAddress("glUniform3f"), &uniform3f); + AssignGLEntryPoint(loadProcAddress("glUniform3fv"), &uniform3fv); + AssignGLEntryPoint(loadProcAddress("glUniform3i"), &uniform3i); + AssignGLEntryPoint(loadProcAddress("glUniform3iv"), &uniform3iv); + AssignGLEntryPoint(loadProcAddress("glUniform4f"), &uniform4f); + AssignGLEntryPoint(loadProcAddress("glUniform4fv"), &uniform4fv); + AssignGLEntryPoint(loadProcAddress("glUniform4i"), &uniform4i); + AssignGLEntryPoint(loadProcAddress("glUniform4iv"), &uniform4iv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix2fv"), &uniformMatrix2fv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix3fv"), &uniformMatrix3fv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix4fv"), &uniformMatrix4fv); + AssignGLEntryPoint(loadProcAddress("glUseProgram"), &useProgram); + AssignGLEntryPoint(loadProcAddress("glValidateProgram"), &validateProgram); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib1d"), &vertexAttrib1d); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib1dv"), &vertexAttrib1dv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib1f"), &vertexAttrib1f); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib1fv"), &vertexAttrib1fv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib1s"), &vertexAttrib1s); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib1sv"), &vertexAttrib1sv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib2d"), &vertexAttrib2d); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib2dv"), &vertexAttrib2dv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib2f"), &vertexAttrib2f); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib2fv"), &vertexAttrib2fv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib2s"), &vertexAttrib2s); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib2sv"), &vertexAttrib2sv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib3d"), &vertexAttrib3d); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib3dv"), &vertexAttrib3dv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib3f"), &vertexAttrib3f); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib3fv"), &vertexAttrib3fv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib3s"), &vertexAttrib3s); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib3sv"), &vertexAttrib3sv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4Nbv"), &vertexAttrib4Nbv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4Niv"), &vertexAttrib4Niv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4Nsv"), &vertexAttrib4Nsv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4Nub"), &vertexAttrib4Nub); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4Nubv"), &vertexAttrib4Nubv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4Nuiv"), &vertexAttrib4Nuiv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4Nusv"), &vertexAttrib4Nusv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4bv"), &vertexAttrib4bv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4d"), &vertexAttrib4d); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4dv"), &vertexAttrib4dv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4f"), &vertexAttrib4f); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4fv"), &vertexAttrib4fv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4iv"), &vertexAttrib4iv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4s"), &vertexAttrib4s); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4sv"), &vertexAttrib4sv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4ubv"), &vertexAttrib4ubv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4uiv"), &vertexAttrib4uiv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4usv"), &vertexAttrib4usv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribPointer"), &vertexAttribPointer); + } + + // 2.1 + if (isAtLeastGL(gl::Version(2, 1))) + { + AssignGLEntryPoint(loadProcAddress("glUniformMatrix2x3fv"), &uniformMatrix2x3fv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix2x4fv"), &uniformMatrix2x4fv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix3x2fv"), &uniformMatrix3x2fv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix3x4fv"), &uniformMatrix3x4fv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix4x2fv"), &uniformMatrix4x2fv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix4x3fv"), &uniformMatrix4x3fv); + } + + // 3.0 + if (isAtLeastGL(gl::Version(3, 0))) + { + AssignGLEntryPoint(loadProcAddress("glBeginConditionalRender"), &beginConditionalRender); + AssignGLEntryPoint(loadProcAddress("glBeginTransformFeedback"), &beginTransformFeedback); + AssignGLEntryPoint(loadProcAddress("glBindBufferBase"), &bindBufferBase); + AssignGLEntryPoint(loadProcAddress("glBindBufferRange"), &bindBufferRange); + AssignGLEntryPoint(loadProcAddress("glBindFragDataLocation"), &bindFragDataLocation); + AssignGLEntryPoint(loadProcAddress("glBindFramebuffer"), &bindFramebuffer); + AssignGLEntryPoint(loadProcAddress("glBindRenderbuffer"), &bindRenderbuffer); + AssignGLEntryPoint(loadProcAddress("glBindVertexArray"), &bindVertexArray); + AssignGLEntryPoint(loadProcAddress("glBlitFramebuffer"), &blitFramebuffer); + AssignGLEntryPoint(loadProcAddress("glCheckFramebufferStatus"), &checkFramebufferStatus); + AssignGLEntryPoint(loadProcAddress("glClampColor"), &clampColor); + AssignGLEntryPoint(loadProcAddress("glClearBufferfi"), &clearBufferfi); + AssignGLEntryPoint(loadProcAddress("glClearBufferfv"), &clearBufferfv); + AssignGLEntryPoint(loadProcAddress("glClearBufferiv"), &clearBufferiv); + AssignGLEntryPoint(loadProcAddress("glClearBufferuiv"), &clearBufferuiv); + AssignGLEntryPoint(loadProcAddress("glColorMaski"), &colorMaski); + AssignGLEntryPoint(loadProcAddress("glDeleteFramebuffers"), &deleteFramebuffers); + AssignGLEntryPoint(loadProcAddress("glDeleteRenderbuffers"), &deleteRenderbuffers); + AssignGLEntryPoint(loadProcAddress("glDeleteVertexArrays"), &deleteVertexArrays); + AssignGLEntryPoint(loadProcAddress("glDisablei"), &disablei); + AssignGLEntryPoint(loadProcAddress("glEnablei"), &enablei); + AssignGLEntryPoint(loadProcAddress("glEndConditionalRender"), &endConditionalRender); + AssignGLEntryPoint(loadProcAddress("glEndTransformFeedback"), &endTransformFeedback); + AssignGLEntryPoint(loadProcAddress("glFlushMappedBufferRange"), &flushMappedBufferRange); + AssignGLEntryPoint(loadProcAddress("glFramebufferRenderbuffer"), &framebufferRenderbuffer); + AssignGLEntryPoint(loadProcAddress("glFramebufferTexture1D"), &framebufferTexture1D); + AssignGLEntryPoint(loadProcAddress("glFramebufferTexture2D"), &framebufferTexture2D); + AssignGLEntryPoint(loadProcAddress("glFramebufferTexture3D"), &framebufferTexture3D); + AssignGLEntryPoint(loadProcAddress("glFramebufferTextureLayer"), &framebufferTextureLayer); + AssignGLEntryPoint(loadProcAddress("glGenFramebuffers"), &genFramebuffers); + AssignGLEntryPoint(loadProcAddress("glGenRenderbuffers"), &genRenderbuffers); + AssignGLEntryPoint(loadProcAddress("glGenVertexArrays"), &genVertexArrays); + AssignGLEntryPoint(loadProcAddress("glGenerateMipmap"), &generateMipmap); + AssignGLEntryPoint(loadProcAddress("glGetBooleani_v"), &getBooleani_v); + AssignGLEntryPoint(loadProcAddress("glGetFragDataLocation"), &getFragDataLocation); + AssignGLEntryPoint(loadProcAddress("glGetFramebufferAttachmentParameteriv"), &getFramebufferAttachmentParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetIntegeri_v"), &getIntegeri_v); + AssignGLEntryPoint(loadProcAddress("glGetRenderbufferParameteriv"), &getRenderbufferParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetStringi"), &getStringi); + AssignGLEntryPoint(loadProcAddress("glGetTexParameterIiv"), &getTexParameterIiv); + AssignGLEntryPoint(loadProcAddress("glGetTexParameterIuiv"), &getTexParameterIuiv); + AssignGLEntryPoint(loadProcAddress("glGetTransformFeedbackVarying"), &getTransformFeedbackVarying); + AssignGLEntryPoint(loadProcAddress("glGetUniformuiv"), &getUniformuiv); + AssignGLEntryPoint(loadProcAddress("glGetVertexAttribIiv"), &getVertexAttribIiv); + AssignGLEntryPoint(loadProcAddress("glGetVertexAttribIuiv"), &getVertexAttribIuiv); + AssignGLEntryPoint(loadProcAddress("glIsEnabledi"), &isEnabledi); + AssignGLEntryPoint(loadProcAddress("glIsFramebuffer"), &isFramebuffer); + AssignGLEntryPoint(loadProcAddress("glIsRenderbuffer"), &isRenderbuffer); + AssignGLEntryPoint(loadProcAddress("glIsVertexArray"), &isVertexArray); + AssignGLEntryPoint(loadProcAddress("glMapBufferRange"), &mapBufferRange); + AssignGLEntryPoint(loadProcAddress("glRenderbufferStorage"), &renderbufferStorage); + AssignGLEntryPoint(loadProcAddress("glRenderbufferStorageMultisample"), &renderbufferStorageMultisample); + AssignGLEntryPoint(loadProcAddress("glTexParameterIiv"), &texParameterIiv); + AssignGLEntryPoint(loadProcAddress("glTexParameterIuiv"), &texParameterIuiv); + AssignGLEntryPoint(loadProcAddress("glTransformFeedbackVaryings"), &transformFeedbackVaryings); + AssignGLEntryPoint(loadProcAddress("glUniform1ui"), &uniform1ui); + AssignGLEntryPoint(loadProcAddress("glUniform1uiv"), &uniform1uiv); + AssignGLEntryPoint(loadProcAddress("glUniform2ui"), &uniform2ui); + AssignGLEntryPoint(loadProcAddress("glUniform2uiv"), &uniform2uiv); + AssignGLEntryPoint(loadProcAddress("glUniform3ui"), &uniform3ui); + AssignGLEntryPoint(loadProcAddress("glUniform3uiv"), &uniform3uiv); + AssignGLEntryPoint(loadProcAddress("glUniform4ui"), &uniform4ui); + AssignGLEntryPoint(loadProcAddress("glUniform4uiv"), &uniform4uiv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI1i"), &vertexAttribI1i); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI1iv"), &vertexAttribI1iv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI1ui"), &vertexAttribI1ui); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI1uiv"), &vertexAttribI1uiv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI2i"), &vertexAttribI2i); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI2iv"), &vertexAttribI2iv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI2ui"), &vertexAttribI2ui); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI2uiv"), &vertexAttribI2uiv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI3i"), &vertexAttribI3i); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI3iv"), &vertexAttribI3iv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI3ui"), &vertexAttribI3ui); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI3uiv"), &vertexAttribI3uiv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI4bv"), &vertexAttribI4bv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI4i"), &vertexAttribI4i); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI4iv"), &vertexAttribI4iv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI4sv"), &vertexAttribI4sv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI4ubv"), &vertexAttribI4ubv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI4ui"), &vertexAttribI4ui); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI4uiv"), &vertexAttribI4uiv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI4usv"), &vertexAttribI4usv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribIPointer"), &vertexAttribIPointer); + } + + // 3.1 + if (isAtLeastGL(gl::Version(3, 1))) + { + AssignGLEntryPoint(loadProcAddress("glCopyBufferSubData"), ©BufferSubData); + AssignGLEntryPoint(loadProcAddress("glDrawArraysInstanced"), &drawArraysInstanced); + AssignGLEntryPoint(loadProcAddress("glDrawElementsInstanced"), &drawElementsInstanced); + AssignGLEntryPoint(loadProcAddress("glGetActiveUniformBlockName"), &getActiveUniformBlockName); + AssignGLEntryPoint(loadProcAddress("glGetActiveUniformBlockiv"), &getActiveUniformBlockiv); + AssignGLEntryPoint(loadProcAddress("glGetActiveUniformName"), &getActiveUniformName); + AssignGLEntryPoint(loadProcAddress("glGetActiveUniformsiv"), &getActiveUniformsiv); + AssignGLEntryPoint(loadProcAddress("glGetUniformBlockIndex"), &getUniformBlockIndex); + AssignGLEntryPoint(loadProcAddress("glGetUniformIndices"), &getUniformIndices); + AssignGLEntryPoint(loadProcAddress("glPrimitiveRestartIndex"), &primitiveRestartIndex); + AssignGLEntryPoint(loadProcAddress("glTexBuffer"), &texBuffer); + AssignGLEntryPoint(loadProcAddress("glUniformBlockBinding"), &uniformBlockBinding); + } + + // 3.2 + if (isAtLeastGL(gl::Version(3, 2))) + { + AssignGLEntryPoint(loadProcAddress("glClientWaitSync"), &clientWaitSync); + AssignGLEntryPoint(loadProcAddress("glDeleteSync"), &deleteSync); + AssignGLEntryPoint(loadProcAddress("glDrawElementsBaseVertex"), &drawElementsBaseVertex); + AssignGLEntryPoint(loadProcAddress("glDrawElementsInstancedBaseVertex"), &drawElementsInstancedBaseVertex); + AssignGLEntryPoint(loadProcAddress("glDrawRangeElementsBaseVertex"), &drawRangeElementsBaseVertex); + AssignGLEntryPoint(loadProcAddress("glFenceSync"), &fenceSync); + AssignGLEntryPoint(loadProcAddress("glFramebufferTexture"), &framebufferTexture); + AssignGLEntryPoint(loadProcAddress("glGetBufferParameteri64v"), &getBufferParameteri64v); + AssignGLEntryPoint(loadProcAddress("glGetInteger64i_v"), &getInteger64i_v); + AssignGLEntryPoint(loadProcAddress("glGetInteger64v"), &getInteger64v); + AssignGLEntryPoint(loadProcAddress("glGetMultisamplefv"), &getMultisamplefv); + AssignGLEntryPoint(loadProcAddress("glGetSynciv"), &getSynciv); + AssignGLEntryPoint(loadProcAddress("glIsSync"), &isSync); + AssignGLEntryPoint(loadProcAddress("glMultiDrawElementsBaseVertex"), &multiDrawElementsBaseVertex); + AssignGLEntryPoint(loadProcAddress("glProvokingVertex"), &provokingVertex); + AssignGLEntryPoint(loadProcAddress("glSampleMaski"), &sampleMaski); + AssignGLEntryPoint(loadProcAddress("glTexImage2DMultisample"), &texImage2DMultisample); + AssignGLEntryPoint(loadProcAddress("glTexImage3DMultisample"), &texImage3DMultisample); + AssignGLEntryPoint(loadProcAddress("glWaitSync"), &waitSync); + } + + // 3.3 + if (isAtLeastGL(gl::Version(3, 3))) + { + AssignGLEntryPoint(loadProcAddress("glBindFragDataLocationIndexed"), &bindFragDataLocationIndexed); + AssignGLEntryPoint(loadProcAddress("glBindSampler"), &bindSampler); + AssignGLEntryPoint(loadProcAddress("glDeleteSamplers"), &deleteSamplers); + AssignGLEntryPoint(loadProcAddress("glGenSamplers"), &genSamplers); + AssignGLEntryPoint(loadProcAddress("glGetFragDataIndex"), &getFragDataIndex); + AssignGLEntryPoint(loadProcAddress("glGetQueryObjecti64v"), &getQueryObjecti64v); + AssignGLEntryPoint(loadProcAddress("glGetQueryObjectui64v"), &getQueryObjectui64v); + AssignGLEntryPoint(loadProcAddress("glGetSamplerParameterIiv"), &getSamplerParameterIiv); + AssignGLEntryPoint(loadProcAddress("glGetSamplerParameterIuiv"), &getSamplerParameterIuiv); + AssignGLEntryPoint(loadProcAddress("glGetSamplerParameterfv"), &getSamplerParameterfv); + AssignGLEntryPoint(loadProcAddress("glGetSamplerParameteriv"), &getSamplerParameteriv); + AssignGLEntryPoint(loadProcAddress("glIsSampler"), &isSampler); + AssignGLEntryPoint(loadProcAddress("glQueryCounter"), &queryCounter); + AssignGLEntryPoint(loadProcAddress("glSamplerParameterIiv"), &samplerParameterIiv); + AssignGLEntryPoint(loadProcAddress("glSamplerParameterIuiv"), &samplerParameterIuiv); + AssignGLEntryPoint(loadProcAddress("glSamplerParameterf"), &samplerParameterf); + AssignGLEntryPoint(loadProcAddress("glSamplerParameterfv"), &samplerParameterfv); + AssignGLEntryPoint(loadProcAddress("glSamplerParameteri"), &samplerParameteri); + AssignGLEntryPoint(loadProcAddress("glSamplerParameteriv"), &samplerParameteriv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribDivisor"), &vertexAttribDivisor); + AssignGLEntryPoint(loadProcAddress("glVertexAttribP1ui"), &vertexAttribP1ui); + AssignGLEntryPoint(loadProcAddress("glVertexAttribP1uiv"), &vertexAttribP1uiv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribP2ui"), &vertexAttribP2ui); + AssignGLEntryPoint(loadProcAddress("glVertexAttribP2uiv"), &vertexAttribP2uiv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribP3ui"), &vertexAttribP3ui); + AssignGLEntryPoint(loadProcAddress("glVertexAttribP3uiv"), &vertexAttribP3uiv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribP4ui"), &vertexAttribP4ui); + AssignGLEntryPoint(loadProcAddress("glVertexAttribP4uiv"), &vertexAttribP4uiv); + } + + // 4.0 + if (isAtLeastGL(gl::Version(4, 0))) + { + AssignGLEntryPoint(loadProcAddress("glBeginQueryIndexed"), &beginQueryIndexed); + AssignGLEntryPoint(loadProcAddress("glBindTransformFeedback"), &bindTransformFeedback); + AssignGLEntryPoint(loadProcAddress("glBlendEquationSeparatei"), &blendEquationSeparatei); + AssignGLEntryPoint(loadProcAddress("glBlendEquationi"), &blendEquationi); + AssignGLEntryPoint(loadProcAddress("glBlendFuncSeparatei"), &blendFuncSeparatei); + AssignGLEntryPoint(loadProcAddress("glBlendFunci"), &blendFunci); + AssignGLEntryPoint(loadProcAddress("glDeleteTransformFeedbacks"), &deleteTransformFeedbacks); + AssignGLEntryPoint(loadProcAddress("glDrawArraysIndirect"), &drawArraysIndirect); + AssignGLEntryPoint(loadProcAddress("glDrawElementsIndirect"), &drawElementsIndirect); + AssignGLEntryPoint(loadProcAddress("glDrawTransformFeedback"), &drawTransformFeedback); + AssignGLEntryPoint(loadProcAddress("glDrawTransformFeedbackStream"), &drawTransformFeedbackStream); + AssignGLEntryPoint(loadProcAddress("glEndQueryIndexed"), &endQueryIndexed); + AssignGLEntryPoint(loadProcAddress("glGenTransformFeedbacks"), &genTransformFeedbacks); + AssignGLEntryPoint(loadProcAddress("glGetActiveSubroutineName"), &getActiveSubroutineName); + AssignGLEntryPoint(loadProcAddress("glGetActiveSubroutineUniformName"), &getActiveSubroutineUniformName); + AssignGLEntryPoint(loadProcAddress("glGetActiveSubroutineUniformiv"), &getActiveSubroutineUniformiv); + AssignGLEntryPoint(loadProcAddress("glGetProgramStageiv"), &getProgramStageiv); + AssignGLEntryPoint(loadProcAddress("glGetQueryIndexediv"), &getQueryIndexediv); + AssignGLEntryPoint(loadProcAddress("glGetSubroutineIndex"), &getSubroutineIndex); + AssignGLEntryPoint(loadProcAddress("glGetSubroutineUniformLocation"), &getSubroutineUniformLocation); + AssignGLEntryPoint(loadProcAddress("glGetUniformSubroutineuiv"), &getUniformSubroutineuiv); + AssignGLEntryPoint(loadProcAddress("glGetUniformdv"), &getUniformdv); + AssignGLEntryPoint(loadProcAddress("glIsTransformFeedback"), &isTransformFeedback); + AssignGLEntryPoint(loadProcAddress("glMinSampleShading"), &minSampleShading); + AssignGLEntryPoint(loadProcAddress("glPatchParameterfv"), &patchParameterfv); + AssignGLEntryPoint(loadProcAddress("glPatchParameteri"), &patchParameteri); + AssignGLEntryPoint(loadProcAddress("glPauseTransformFeedback"), &pauseTransformFeedback); + AssignGLEntryPoint(loadProcAddress("glResumeTransformFeedback"), &resumeTransformFeedback); + AssignGLEntryPoint(loadProcAddress("glUniform1d"), &uniform1d); + AssignGLEntryPoint(loadProcAddress("glUniform1dv"), &uniform1dv); + AssignGLEntryPoint(loadProcAddress("glUniform2d"), &uniform2d); + AssignGLEntryPoint(loadProcAddress("glUniform2dv"), &uniform2dv); + AssignGLEntryPoint(loadProcAddress("glUniform3d"), &uniform3d); + AssignGLEntryPoint(loadProcAddress("glUniform3dv"), &uniform3dv); + AssignGLEntryPoint(loadProcAddress("glUniform4d"), &uniform4d); + AssignGLEntryPoint(loadProcAddress("glUniform4dv"), &uniform4dv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix2dv"), &uniformMatrix2dv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix2x3dv"), &uniformMatrix2x3dv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix2x4dv"), &uniformMatrix2x4dv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix3dv"), &uniformMatrix3dv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix3x2dv"), &uniformMatrix3x2dv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix3x4dv"), &uniformMatrix3x4dv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix4dv"), &uniformMatrix4dv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix4x2dv"), &uniformMatrix4x2dv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix4x3dv"), &uniformMatrix4x3dv); + AssignGLEntryPoint(loadProcAddress("glUniformSubroutinesuiv"), &uniformSubroutinesuiv); + } + + // 4.1 + if (isAtLeastGL(gl::Version(4, 1))) + { + AssignGLEntryPoint(loadProcAddress("glActiveShaderProgram"), &activeShaderProgram); + AssignGLEntryPoint(loadProcAddress("glBindProgramPipeline"), &bindProgramPipeline); + AssignGLEntryPoint(loadProcAddress("glClearDepthf"), &clearDepthf); + AssignGLEntryPoint(loadProcAddress("glCreateShaderProgramv"), &createShaderProgramv); + AssignGLEntryPoint(loadProcAddress("glDeleteProgramPipelines"), &deleteProgramPipelines); + AssignGLEntryPoint(loadProcAddress("glDepthRangeArrayv"), &depthRangeArrayv); + AssignGLEntryPoint(loadProcAddress("glDepthRangeIndexed"), &depthRangeIndexed); + AssignGLEntryPoint(loadProcAddress("glDepthRangef"), &depthRangef); + AssignGLEntryPoint(loadProcAddress("glGenProgramPipelines"), &genProgramPipelines); + AssignGLEntryPoint(loadProcAddress("glGetDoublei_v"), &getDoublei_v); + AssignGLEntryPoint(loadProcAddress("glGetFloati_v"), &getFloati_v); + AssignGLEntryPoint(loadProcAddress("glGetProgramBinary"), &getProgramBinary); + AssignGLEntryPoint(loadProcAddress("glGetProgramPipelineInfoLog"), &getProgramPipelineInfoLog); + AssignGLEntryPoint(loadProcAddress("glGetProgramPipelineiv"), &getProgramPipelineiv); + AssignGLEntryPoint(loadProcAddress("glGetShaderPrecisionFormat"), &getShaderPrecisionFormat); + AssignGLEntryPoint(loadProcAddress("glGetVertexAttribLdv"), &getVertexAttribLdv); + AssignGLEntryPoint(loadProcAddress("glIsProgramPipeline"), &isProgramPipeline); + AssignGLEntryPoint(loadProcAddress("glProgramBinary"), &programBinary); + AssignGLEntryPoint(loadProcAddress("glProgramParameteri"), &programParameteri); + AssignGLEntryPoint(loadProcAddress("glProgramUniform1d"), &programUniform1d); + AssignGLEntryPoint(loadProcAddress("glProgramUniform1dv"), &programUniform1dv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform1f"), &programUniform1f); + AssignGLEntryPoint(loadProcAddress("glProgramUniform1fv"), &programUniform1fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform1i"), &programUniform1i); + AssignGLEntryPoint(loadProcAddress("glProgramUniform1iv"), &programUniform1iv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform1ui"), &programUniform1ui); + AssignGLEntryPoint(loadProcAddress("glProgramUniform1uiv"), &programUniform1uiv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform2d"), &programUniform2d); + AssignGLEntryPoint(loadProcAddress("glProgramUniform2dv"), &programUniform2dv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform2f"), &programUniform2f); + AssignGLEntryPoint(loadProcAddress("glProgramUniform2fv"), &programUniform2fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform2i"), &programUniform2i); + AssignGLEntryPoint(loadProcAddress("glProgramUniform2iv"), &programUniform2iv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform2ui"), &programUniform2ui); + AssignGLEntryPoint(loadProcAddress("glProgramUniform2uiv"), &programUniform2uiv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform3d"), &programUniform3d); + AssignGLEntryPoint(loadProcAddress("glProgramUniform3dv"), &programUniform3dv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform3f"), &programUniform3f); + AssignGLEntryPoint(loadProcAddress("glProgramUniform3fv"), &programUniform3fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform3i"), &programUniform3i); + AssignGLEntryPoint(loadProcAddress("glProgramUniform3iv"), &programUniform3iv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform3ui"), &programUniform3ui); + AssignGLEntryPoint(loadProcAddress("glProgramUniform3uiv"), &programUniform3uiv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform4d"), &programUniform4d); + AssignGLEntryPoint(loadProcAddress("glProgramUniform4dv"), &programUniform4dv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform4f"), &programUniform4f); + AssignGLEntryPoint(loadProcAddress("glProgramUniform4fv"), &programUniform4fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform4i"), &programUniform4i); + AssignGLEntryPoint(loadProcAddress("glProgramUniform4iv"), &programUniform4iv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform4ui"), &programUniform4ui); + AssignGLEntryPoint(loadProcAddress("glProgramUniform4uiv"), &programUniform4uiv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2dv"), &programUniformMatrix2dv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2fv"), &programUniformMatrix2fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2x3dv"), &programUniformMatrix2x3dv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2x3fv"), &programUniformMatrix2x3fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2x4dv"), &programUniformMatrix2x4dv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2x4fv"), &programUniformMatrix2x4fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3dv"), &programUniformMatrix3dv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3fv"), &programUniformMatrix3fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3x2dv"), &programUniformMatrix3x2dv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3x2fv"), &programUniformMatrix3x2fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3x4dv"), &programUniformMatrix3x4dv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3x4fv"), &programUniformMatrix3x4fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4dv"), &programUniformMatrix4dv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4fv"), &programUniformMatrix4fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4x2dv"), &programUniformMatrix4x2dv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4x2fv"), &programUniformMatrix4x2fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4x3dv"), &programUniformMatrix4x3dv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4x3fv"), &programUniformMatrix4x3fv); + AssignGLEntryPoint(loadProcAddress("glReleaseShaderCompiler"), &releaseShaderCompiler); + AssignGLEntryPoint(loadProcAddress("glScissorArrayv"), &scissorArrayv); + AssignGLEntryPoint(loadProcAddress("glScissorIndexed"), &scissorIndexed); + AssignGLEntryPoint(loadProcAddress("glScissorIndexedv"), &scissorIndexedv); + AssignGLEntryPoint(loadProcAddress("glShaderBinary"), &shaderBinary); + AssignGLEntryPoint(loadProcAddress("glUseProgramStages"), &useProgramStages); + AssignGLEntryPoint(loadProcAddress("glValidateProgramPipeline"), &validateProgramPipeline); + AssignGLEntryPoint(loadProcAddress("glVertexAttribL1d"), &vertexAttribL1d); + AssignGLEntryPoint(loadProcAddress("glVertexAttribL1dv"), &vertexAttribL1dv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribL2d"), &vertexAttribL2d); + AssignGLEntryPoint(loadProcAddress("glVertexAttribL2dv"), &vertexAttribL2dv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribL3d"), &vertexAttribL3d); + AssignGLEntryPoint(loadProcAddress("glVertexAttribL3dv"), &vertexAttribL3dv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribL4d"), &vertexAttribL4d); + AssignGLEntryPoint(loadProcAddress("glVertexAttribL4dv"), &vertexAttribL4dv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribLPointer"), &vertexAttribLPointer); + AssignGLEntryPoint(loadProcAddress("glViewportArrayv"), &viewportArrayv); + AssignGLEntryPoint(loadProcAddress("glViewportIndexedf"), &viewportIndexedf); + AssignGLEntryPoint(loadProcAddress("glViewportIndexedfv"), &viewportIndexedfv); + } + + // 4.2 + if (isAtLeastGL(gl::Version(4, 2))) + { + AssignGLEntryPoint(loadProcAddress("glBindImageTexture"), &bindImageTexture); + AssignGLEntryPoint(loadProcAddress("glDrawArraysInstancedBaseInstance"), &drawArraysInstancedBaseInstance); + AssignGLEntryPoint(loadProcAddress("glDrawElementsInstancedBaseInstance"), &drawElementsInstancedBaseInstance); + AssignGLEntryPoint(loadProcAddress("glDrawElementsInstancedBaseVertexBaseInstance"), &drawElementsInstancedBaseVertexBaseInstance); + AssignGLEntryPoint(loadProcAddress("glDrawTransformFeedbackInstanced"), &drawTransformFeedbackInstanced); + AssignGLEntryPoint(loadProcAddress("glDrawTransformFeedbackStreamInstanced"), &drawTransformFeedbackStreamInstanced); + AssignGLEntryPoint(loadProcAddress("glGetActiveAtomicCounterBufferiv"), &getActiveAtomicCounterBufferiv); + AssignGLEntryPoint(loadProcAddress("glGetInternalformativ"), &getInternalformativ); + AssignGLEntryPoint(loadProcAddress("glMemoryBarrier"), &memoryBarrier); + AssignGLEntryPoint(loadProcAddress("glTexStorage1D"), &texStorage1D); + AssignGLEntryPoint(loadProcAddress("glTexStorage2D"), &texStorage2D); + AssignGLEntryPoint(loadProcAddress("glTexStorage3D"), &texStorage3D); + } + + // 4.3 + if (isAtLeastGL(gl::Version(4, 3))) + { + AssignGLEntryPoint(loadProcAddress("glBindVertexBuffer"), &bindVertexBuffer); + AssignGLEntryPoint(loadProcAddress("glClearBufferData"), &clearBufferData); + AssignGLEntryPoint(loadProcAddress("glClearBufferSubData"), &clearBufferSubData); + AssignGLEntryPoint(loadProcAddress("glCopyImageSubData"), ©ImageSubData); + AssignGLEntryPoint(loadProcAddress("glDebugMessageCallback"), &debugMessageCallback); + AssignGLEntryPoint(loadProcAddress("glDebugMessageControl"), &debugMessageControl); + AssignGLEntryPoint(loadProcAddress("glDebugMessageInsert"), &debugMessageInsert); + AssignGLEntryPoint(loadProcAddress("glDispatchCompute"), &dispatchCompute); + AssignGLEntryPoint(loadProcAddress("glDispatchComputeIndirect"), &dispatchComputeIndirect); + AssignGLEntryPoint(loadProcAddress("glFramebufferParameteri"), &framebufferParameteri); + AssignGLEntryPoint(loadProcAddress("glGetDebugMessageLog"), &getDebugMessageLog); + AssignGLEntryPoint(loadProcAddress("glGetFramebufferParameteriv"), &getFramebufferParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetInternalformati64v"), &getInternalformati64v); + AssignGLEntryPoint(loadProcAddress("glGetPointerv"), &getPointerv); + AssignGLEntryPoint(loadProcAddress("glGetObjectLabel"), &getObjectLabel); + AssignGLEntryPoint(loadProcAddress("glGetObjectPtrLabel"), &getObjectPtrLabel); + AssignGLEntryPoint(loadProcAddress("glGetProgramInterfaceiv"), &getProgramInterfaceiv); + AssignGLEntryPoint(loadProcAddress("glGetProgramResourceIndex"), &getProgramResourceIndex); + AssignGLEntryPoint(loadProcAddress("glGetProgramResourceLocation"), &getProgramResourceLocation); + AssignGLEntryPoint(loadProcAddress("glGetProgramResourceLocationIndex"), &getProgramResourceLocationIndex); + AssignGLEntryPoint(loadProcAddress("glGetProgramResourceName"), &getProgramResourceName); + AssignGLEntryPoint(loadProcAddress("glGetProgramResourceiv"), &getProgramResourceiv); + AssignGLEntryPoint(loadProcAddress("glInvalidateBufferData"), &invalidateBufferData); + AssignGLEntryPoint(loadProcAddress("glInvalidateBufferSubData"), &invalidateBufferSubData); + AssignGLEntryPoint(loadProcAddress("glInvalidateFramebuffer"), &invalidateFramebuffer); + AssignGLEntryPoint(loadProcAddress("glInvalidateSubFramebuffer"), &invalidateSubFramebuffer); + AssignGLEntryPoint(loadProcAddress("glInvalidateTexImage"), &invalidateTexImage); + AssignGLEntryPoint(loadProcAddress("glInvalidateTexSubImage"), &invalidateTexSubImage); + AssignGLEntryPoint(loadProcAddress("glMultiDrawArraysIndirect"), &multiDrawArraysIndirect); + AssignGLEntryPoint(loadProcAddress("glMultiDrawElementsIndirect"), &multiDrawElementsIndirect); + AssignGLEntryPoint(loadProcAddress("glObjectLabel"), &objectLabel); + AssignGLEntryPoint(loadProcAddress("glObjectPtrLabel"), &objectPtrLabel); + AssignGLEntryPoint(loadProcAddress("glPopDebugGroup"), &popDebugGroup); + AssignGLEntryPoint(loadProcAddress("glPushDebugGroup"), &pushDebugGroup); + AssignGLEntryPoint(loadProcAddress("glShaderStorageBlockBinding"), &shaderStorageBlockBinding); + AssignGLEntryPoint(loadProcAddress("glTexBufferRange"), &texBufferRange); + AssignGLEntryPoint(loadProcAddress("glTexStorage2DMultisample"), &texStorage2DMultisample); + AssignGLEntryPoint(loadProcAddress("glTexStorage3DMultisample"), &texStorage3DMultisample); + AssignGLEntryPoint(loadProcAddress("glTextureView"), &textureView); + AssignGLEntryPoint(loadProcAddress("glVertexAttribBinding"), &vertexAttribBinding); + AssignGLEntryPoint(loadProcAddress("glVertexAttribFormat"), &vertexAttribFormat); + AssignGLEntryPoint(loadProcAddress("glVertexAttribIFormat"), &vertexAttribIFormat); + AssignGLEntryPoint(loadProcAddress("glVertexAttribLFormat"), &vertexAttribLFormat); + AssignGLEntryPoint(loadProcAddress("glVertexBindingDivisor"), &vertexBindingDivisor); + } + + // 4.4 + if (isAtLeastGL(gl::Version(4, 4))) + { + AssignGLEntryPoint(loadProcAddress("glBindBuffersBase"), &bindBuffersBase); + AssignGLEntryPoint(loadProcAddress("glBindBuffersRange"), &bindBuffersRange); + AssignGLEntryPoint(loadProcAddress("glBindImageTextures"), &bindImageTextures); + AssignGLEntryPoint(loadProcAddress("glBindSamplers"), &bindSamplers); + AssignGLEntryPoint(loadProcAddress("glBindTextures"), &bindTextures); + AssignGLEntryPoint(loadProcAddress("glBindVertexBuffers"), &bindVertexBuffers); + AssignGLEntryPoint(loadProcAddress("glBufferStorage"), &bufferStorage); + AssignGLEntryPoint(loadProcAddress("glClearTexImage"), &clearTexImage); + AssignGLEntryPoint(loadProcAddress("glClearTexSubImage"), &clearTexSubImage); + } + + // 4.5 + if (isAtLeastGL(gl::Version(4, 5))) + { + AssignGLEntryPoint(loadProcAddress("glBindTextureUnit"), &bindTextureUnit); + AssignGLEntryPoint(loadProcAddress("glBlitNamedFramebuffer"), &blitNamedFramebuffer); + AssignGLEntryPoint(loadProcAddress("glCheckNamedFramebufferStatus"), &checkNamedFramebufferStatus); + AssignGLEntryPoint(loadProcAddress("glClearNamedBufferData"), &clearNamedBufferData); + AssignGLEntryPoint(loadProcAddress("glClearNamedBufferSubData"), &clearNamedBufferSubData); + AssignGLEntryPoint(loadProcAddress("glClearNamedFramebufferfi"), &clearNamedFramebufferfi); + AssignGLEntryPoint(loadProcAddress("glClearNamedFramebufferfv"), &clearNamedFramebufferfv); + AssignGLEntryPoint(loadProcAddress("glClearNamedFramebufferiv"), &clearNamedFramebufferiv); + AssignGLEntryPoint(loadProcAddress("glClearNamedFramebufferuiv"), &clearNamedFramebufferuiv); + AssignGLEntryPoint(loadProcAddress("glClipControl"), &clipControl); + AssignGLEntryPoint(loadProcAddress("glCompressedTextureSubImage1D"), &compressedTextureSubImage1D); + AssignGLEntryPoint(loadProcAddress("glCompressedTextureSubImage2D"), &compressedTextureSubImage2D); + AssignGLEntryPoint(loadProcAddress("glCompressedTextureSubImage3D"), &compressedTextureSubImage3D); + AssignGLEntryPoint(loadProcAddress("glCopyNamedBufferSubData"), ©NamedBufferSubData); + AssignGLEntryPoint(loadProcAddress("glCopyTextureSubImage1D"), ©TextureSubImage1D); + AssignGLEntryPoint(loadProcAddress("glCopyTextureSubImage2D"), ©TextureSubImage2D); + AssignGLEntryPoint(loadProcAddress("glCopyTextureSubImage3D"), ©TextureSubImage3D); + AssignGLEntryPoint(loadProcAddress("glCreateBuffers"), &createBuffers); + AssignGLEntryPoint(loadProcAddress("glCreateFramebuffers"), &createFramebuffers); + AssignGLEntryPoint(loadProcAddress("glCreateProgramPipelines"), &createProgramPipelines); + AssignGLEntryPoint(loadProcAddress("glCreateQueries"), &createQueries); + AssignGLEntryPoint(loadProcAddress("glCreateRenderbuffers"), &createRenderbuffers); + AssignGLEntryPoint(loadProcAddress("glCreateSamplers"), &createSamplers); + AssignGLEntryPoint(loadProcAddress("glCreateTextures"), &createTextures); + AssignGLEntryPoint(loadProcAddress("glCreateTransformFeedbacks"), &createTransformFeedbacks); + AssignGLEntryPoint(loadProcAddress("glCreateVertexArrays"), &createVertexArrays); + AssignGLEntryPoint(loadProcAddress("glDisableVertexArrayAttrib"), &disableVertexArrayAttrib); + AssignGLEntryPoint(loadProcAddress("glEnableVertexArrayAttrib"), &enableVertexArrayAttrib); + AssignGLEntryPoint(loadProcAddress("glFlushMappedNamedBufferRange"), &flushMappedNamedBufferRange); + AssignGLEntryPoint(loadProcAddress("glGenerateTextureMipmap"), &generateTextureMipmap); + AssignGLEntryPoint(loadProcAddress("glGetCompressedTextureImage"), &getCompressedTextureImage); + AssignGLEntryPoint(loadProcAddress("glGetCompressedTextureSubImage"), &getCompressedTextureSubImage); + AssignGLEntryPoint(loadProcAddress("glGetGraphicsResetStatus"), &getGraphicsResetStatus); + AssignGLEntryPoint(loadProcAddress("glGetNamedBufferParameteri64v"), &getNamedBufferParameteri64v); + AssignGLEntryPoint(loadProcAddress("glGetNamedBufferParameteriv"), &getNamedBufferParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetNamedBufferPointerv"), &getNamedBufferPointerv); + AssignGLEntryPoint(loadProcAddress("glGetNamedBufferSubData"), &getNamedBufferSubData); + AssignGLEntryPoint(loadProcAddress("glGetNamedFramebufferAttachmentParameteriv"), &getNamedFramebufferAttachmentParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetNamedFramebufferParameteriv"), &getNamedFramebufferParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetNamedRenderbufferParameteriv"), &getNamedRenderbufferParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetQueryBufferObjecti64v"), &getQueryBufferObjecti64v); + AssignGLEntryPoint(loadProcAddress("glGetQueryBufferObjectiv"), &getQueryBufferObjectiv); + AssignGLEntryPoint(loadProcAddress("glGetQueryBufferObjectui64v"), &getQueryBufferObjectui64v); + AssignGLEntryPoint(loadProcAddress("glGetQueryBufferObjectuiv"), &getQueryBufferObjectuiv); + AssignGLEntryPoint(loadProcAddress("glGetTextureImage"), &getTextureImage); + AssignGLEntryPoint(loadProcAddress("glGetTextureLevelParameterfv"), &getTextureLevelParameterfv); + AssignGLEntryPoint(loadProcAddress("glGetTextureLevelParameteriv"), &getTextureLevelParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetTextureParameterIiv"), &getTextureParameterIiv); + AssignGLEntryPoint(loadProcAddress("glGetTextureParameterIuiv"), &getTextureParameterIuiv); + AssignGLEntryPoint(loadProcAddress("glGetTextureParameterfv"), &getTextureParameterfv); + AssignGLEntryPoint(loadProcAddress("glGetTextureParameteriv"), &getTextureParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetTextureSubImage"), &getTextureSubImage); + AssignGLEntryPoint(loadProcAddress("glGetTransformFeedbacki64_v"), &getTransformFeedbacki64_v); + AssignGLEntryPoint(loadProcAddress("glGetTransformFeedbacki_v"), &getTransformFeedbacki_v); + AssignGLEntryPoint(loadProcAddress("glGetTransformFeedbackiv"), &getTransformFeedbackiv); + AssignGLEntryPoint(loadProcAddress("glGetVertexArrayIndexed64iv"), &getVertexArrayIndexed64iv); + AssignGLEntryPoint(loadProcAddress("glGetVertexArrayIndexediv"), &getVertexArrayIndexediv); + AssignGLEntryPoint(loadProcAddress("glGetVertexArrayiv"), &getVertexArrayiv); + AssignGLEntryPoint(loadProcAddress("glGetnCompressedTexImage"), &getnCompressedTexImage); + AssignGLEntryPoint(loadProcAddress("glGetnTexImage"), &getnTexImage); + AssignGLEntryPoint(loadProcAddress("glGetnUniformdv"), &getnUniformdv); + AssignGLEntryPoint(loadProcAddress("glGetnUniformfv"), &getnUniformfv); + AssignGLEntryPoint(loadProcAddress("glGetnUniformiv"), &getnUniformiv); + AssignGLEntryPoint(loadProcAddress("glGetnUniformuiv"), &getnUniformuiv); + AssignGLEntryPoint(loadProcAddress("glInvalidateNamedFramebufferData"), &invalidateNamedFramebufferData); + AssignGLEntryPoint(loadProcAddress("glInvalidateNamedFramebufferSubData"), &invalidateNamedFramebufferSubData); + AssignGLEntryPoint(loadProcAddress("glMapNamedBuffer"), &mapNamedBuffer); + AssignGLEntryPoint(loadProcAddress("glMapNamedBufferRange"), &mapNamedBufferRange); + AssignGLEntryPoint(loadProcAddress("glMemoryBarrierByRegion"), &memoryBarrierByRegion); + AssignGLEntryPoint(loadProcAddress("glNamedBufferData"), &namedBufferData); + AssignGLEntryPoint(loadProcAddress("glNamedBufferStorage"), &namedBufferStorage); + AssignGLEntryPoint(loadProcAddress("glNamedBufferSubData"), &namedBufferSubData); + AssignGLEntryPoint(loadProcAddress("glNamedFramebufferDrawBuffer"), &namedFramebufferDrawBuffer); + AssignGLEntryPoint(loadProcAddress("glNamedFramebufferDrawBuffers"), &namedFramebufferDrawBuffers); + AssignGLEntryPoint(loadProcAddress("glNamedFramebufferParameteri"), &namedFramebufferParameteri); + AssignGLEntryPoint(loadProcAddress("glNamedFramebufferReadBuffer"), &namedFramebufferReadBuffer); + AssignGLEntryPoint(loadProcAddress("glNamedFramebufferRenderbuffer"), &namedFramebufferRenderbuffer); + AssignGLEntryPoint(loadProcAddress("glNamedFramebufferTexture"), &namedFramebufferTexture); + AssignGLEntryPoint(loadProcAddress("glNamedFramebufferTextureLayer"), &namedFramebufferTextureLayer); + AssignGLEntryPoint(loadProcAddress("glNamedRenderbufferStorage"), &namedRenderbufferStorage); + AssignGLEntryPoint(loadProcAddress("glNamedRenderbufferStorageMultisample"), &namedRenderbufferStorageMultisample); + AssignGLEntryPoint(loadProcAddress("glReadnPixels"), &readnPixels); + AssignGLEntryPoint(loadProcAddress("glTextureBarrier"), &textureBarrier); + AssignGLEntryPoint(loadProcAddress("glTextureBuffer"), &textureBuffer); + AssignGLEntryPoint(loadProcAddress("glTextureBufferRange"), &textureBufferRange); + AssignGLEntryPoint(loadProcAddress("glTextureParameterIiv"), &textureParameterIiv); + AssignGLEntryPoint(loadProcAddress("glTextureParameterIuiv"), &textureParameterIuiv); + AssignGLEntryPoint(loadProcAddress("glTextureParameterf"), &textureParameterf); + AssignGLEntryPoint(loadProcAddress("glTextureParameterfv"), &textureParameterfv); + AssignGLEntryPoint(loadProcAddress("glTextureParameteri"), &textureParameteri); + AssignGLEntryPoint(loadProcAddress("glTextureParameteriv"), &textureParameteriv); + AssignGLEntryPoint(loadProcAddress("glTextureStorage1D"), &textureStorage1D); + AssignGLEntryPoint(loadProcAddress("glTextureStorage2D"), &textureStorage2D); + AssignGLEntryPoint(loadProcAddress("glTextureStorage2DMultisample"), &textureStorage2DMultisample); + AssignGLEntryPoint(loadProcAddress("glTextureStorage3D"), &textureStorage3D); + AssignGLEntryPoint(loadProcAddress("glTextureStorage3DMultisample"), &textureStorage3DMultisample); + AssignGLEntryPoint(loadProcAddress("glTextureSubImage1D"), &textureSubImage1D); + AssignGLEntryPoint(loadProcAddress("glTextureSubImage2D"), &textureSubImage2D); + AssignGLEntryPoint(loadProcAddress("glTextureSubImage3D"), &textureSubImage3D); + AssignGLEntryPoint(loadProcAddress("glTransformFeedbackBufferBase"), &transformFeedbackBufferBase); + AssignGLEntryPoint(loadProcAddress("glTransformFeedbackBufferRange"), &transformFeedbackBufferRange); + AssignGLEntryPoint(loadProcAddress("glUnmapNamedBuffer"), &unmapNamedBuffer); + AssignGLEntryPoint(loadProcAddress("glVertexArrayAttribBinding"), &vertexArrayAttribBinding); + AssignGLEntryPoint(loadProcAddress("glVertexArrayAttribFormat"), &vertexArrayAttribFormat); + AssignGLEntryPoint(loadProcAddress("glVertexArrayAttribIFormat"), &vertexArrayAttribIFormat); + AssignGLEntryPoint(loadProcAddress("glVertexArrayAttribLFormat"), &vertexArrayAttribLFormat); + AssignGLEntryPoint(loadProcAddress("glVertexArrayBindingDivisor"), &vertexArrayBindingDivisor); + AssignGLEntryPoint(loadProcAddress("glVertexArrayElementBuffer"), &vertexArrayElementBuffer); + AssignGLEntryPoint(loadProcAddress("glVertexArrayVertexBuffer"), &vertexArrayVertexBuffer); + AssignGLEntryPoint(loadProcAddress("glVertexArrayVertexBuffers"), &vertexArrayVertexBuffers); + } + + // clang-format on +} + +void FunctionsGL::initializeProcsGLES() +{ + // No profiles in GLES + profile = 0; + + // clang-format off + + // GL_NV_path_rendering + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glMatrixLoadfEXT"), &matrixLoadEXT); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGenPathsNV"), &genPathsNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glDeletePathsNV"), &delPathsNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathCommandsNV"), &pathCommandsNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glIsPathNV"), &isPathNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathParameterfNV"), &setPathParameterfNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathParameteriNV"), &setPathParameteriNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGetPathParameterfvNV"), &getPathParameterfNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGetPathParameterivNV"), &getPathParameteriNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathStencilFuncNV"), &pathStencilFuncNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilFillPathNV"), &stencilFillPathNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilStrokePathNV"), &stencilStrokePathNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverFillPathNV"), &coverFillPathNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverStrokePathNV"), &coverStrokePathNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverFillPathNV"), &stencilThenCoverFillPathNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverStrokePathNV"), &stencilThenCoverStrokePathNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverFillPathInstancedNV"), &coverFillPathInstancedNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverStrokePathInstancedNV"), &coverStrokePathInstancedNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilFillPathInstancedNV"), &stencilFillPathInstancedNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilStrokePathInstancedNV"), &stencilStrokePathInstancedNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverFillPathInstancedNV"), &stencilThenCoverFillPathInstancedNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverStrokePathInstancedNV"), &stencilThenCoverStrokePathInstancedNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glProgramPathFragmentInputGenNV"), &programPathFragmentInputGenNV); + + // GL_OES_texture_3D + AssignGLExtensionEntryPoint(extensions, "GL_OES_texture_3D", loadProcAddress("glTexImage3DOES"), &texImage3D); + AssignGLExtensionEntryPoint(extensions, "GL_OES_texture_3D", loadProcAddress("glTexSubImage3DOES"), &texSubImage3D); + AssignGLExtensionEntryPoint(extensions, "GL_OES_texture_3D", loadProcAddress("glCopyTexSubImage3DOES"), ©TexSubImage3D); + + // GL_NV_framebuffer_mixed_samples + AssignGLExtensionEntryPoint(extensions, "GL_NV_framebuffer_mixed_samples", loadProcAddress("glCoverageModulationNV"), &coverageModulationNV); + + // GL_NV_fence + AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glDeleteFencesNV"), &deleteFencesNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glGenFencesNV"), &genFencesNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glIsFenceNV"), &isFenceNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glTestFenceNV"), &testFenceNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glGetFenceivNV"), &getFenceivNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glFinishFenceNV"), &finishFenceNV); + AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glSetFenceNV"), &setFenceNV); + + // GL_EXT_texture_storage + AssignGLExtensionEntryPoint(extensions, "GL_EXT_texture_storage", loadProcAddress("glTexStorage2DEXT"), &texStorage2D); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_texture_storage GL_OES_texture3D", loadProcAddress("glTexStorage3DEXT"), &texStorage3D); + + // GL_OES_vertex_array_object + AssignGLExtensionEntryPoint(extensions, "GL_OES_vertex_array_object", loadProcAddress("glBindVertexArray"), &bindVertexArray); + AssignGLExtensionEntryPoint(extensions, "GL_OES_vertex_array_object", loadProcAddress("glDeleteVertexArrays"), &deleteVertexArrays); + AssignGLExtensionEntryPoint(extensions, "GL_OES_vertex_array_object", loadProcAddress("glGenVertexArrays"), &genVertexArrays); + AssignGLExtensionEntryPoint(extensions, "GL_OES_vertex_array_object", loadProcAddress("glIsVertexArray"), &isVertexArray); + + // GL_EXT_map_buffer_range + AssignGLExtensionEntryPoint(extensions, "GL_EXT_map_buffer_range", loadProcAddress("glMapBufferRangeEXT"), &mapBufferRange); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_map_buffer_range", loadProcAddress("glFlushMappedBufferRangeEXT"), &flushMappedBufferRange); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_map_buffer_range", loadProcAddress("glUnmapBufferOES"), &unmapBuffer); + + // GL_OES_mapbuffer + AssignGLExtensionEntryPoint(extensions, "GL_OES_mapbuffer", loadProcAddress("glMapBufferOES"), &mapBuffer); + AssignGLExtensionEntryPoint(extensions, "GL_OES_mapbuffer", loadProcAddress("glUnmapBufferOES"), &unmapBuffer); + + // GL_KHR_debug + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glDebugMessageControlKHR"), &debugMessageControl); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glDebugMessageInsertKHR"), &debugMessageInsert); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glDebugMessageCallbackKHR"), &debugMessageCallback); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glGetDebugMessageLogKHR"), &getDebugMessageLog); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glGetPointervKHR"), &getPointerv); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glPushDebugGroupKHR"), &pushDebugGroup); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glPopDebugGroupKHR"), &popDebugGroup); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glObjectLabelKHR"), &objectLabel); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glGetObjectLabelKHR"), &getObjectLabel); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glObjectPtrLabelKHR"), &objectPtrLabel); + AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glGetObjectPtrLabelKHR"), &getObjectPtrLabel); + + // GL_EXT_draw_instanced + AssignGLExtensionEntryPoint(extensions, "GL_EXT_draw_instanced", loadProcAddress("glVertexAttribDivisorEXT"), &vertexAttribDivisor); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_draw_instanced", loadProcAddress("glDrawArraysInstancedEXT"), &drawArraysInstanced); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_draw_instanced", loadProcAddress("glDrawElementsInstancedEXT"), &drawElementsInstanced); + + // GL_EXT_occlusion_query_boolean + AssignGLExtensionEntryPoint(extensions, "GL_EXT_occlusion_query_boolean", loadProcAddress("glGenQueriesEXT"), &genQueries); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_occlusion_query_boolean", loadProcAddress("glDeleteQueriesEXT"), &deleteQueries); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_occlusion_query_boolean", loadProcAddress("glIsQueryEXT"), &isQuery); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_occlusion_query_boolean", loadProcAddress("glBeginQueryEXT"), &beginQuery); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_occlusion_query_boolean", loadProcAddress("glEndQueryEXT"), &endQuery); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_occlusion_query_boolean", loadProcAddress("glGetQueryivEXT"), &getQueryiv); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_occlusion_query_boolean", loadProcAddress("glGetQueryObjectuivEXT"), &getQueryObjectuiv); + + // GL_EXT_disjoint_timer_query + AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glGenQueriesEXT"), &genQueries); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glDeleteQueriesEXT"), &deleteQueries); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glIsQueryEXT"), &isQuery); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glBeginQueryEXT"), &beginQuery); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glEndQueryEXT"), &endQuery); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glQueryCounterEXT"), &queryCounter); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glGetQueryivEXT"), &getQueryiv); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glGetQueryObjectivEXT"), &getQueryObjectiv); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glGetQueryObjectuivEXT"), &getQueryObjectuiv); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glGetQueryObjecti64vEXT"), &getQueryObjecti64v); + AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glGetQueryObjectui64vEXT"), &getQueryObjectui64v); + + // GL_OES_EGL_image + AssignGLExtensionEntryPoint(extensions, "GL_OES_EGL_image", loadProcAddress("glEGLImageTargetRenderbufferStorageOES"), &eglImageTargetRenderbufferStorageOES); + AssignGLExtensionEntryPoint(extensions, "GL_OES_EGL_image", loadProcAddress("glEGLImageTargetTexture2DOES"), &eglImageTargetTexture2DOES); + + // GL_OES_get_program_binary + AssignGLExtensionEntryPoint(extensions, "GL_OES_get_program_binary", loadProcAddress("glGetProgramBinaryOES"), &getProgramBinary); + AssignGLExtensionEntryPoint(extensions, "GL_OES_get_program_binary", loadProcAddress("glProgramBinaryOES"), &programBinary); + + // GL_EXT_robustness + AssignGLExtensionEntryPoint(extensions, "GL_EXT_robustness", loadProcAddress("glGetGraphicsResetStatusEXT"), &getGraphicsResetStatus); + + // GL_KHR_robustness + AssignGLExtensionEntryPoint(extensions, "GL_KHR_robustness", loadProcAddress("glGetGraphicsResetStatusKHR"), &getGraphicsResetStatus); + + // 2.0 + if (isAtLeastGLES(gl::Version(2, 0))) + { + AssignGLEntryPoint(loadProcAddress("glActiveTexture"), &activeTexture); + AssignGLEntryPoint(loadProcAddress("glAttachShader"), &attachShader); + AssignGLEntryPoint(loadProcAddress("glBindAttribLocation"), &bindAttribLocation); + AssignGLEntryPoint(loadProcAddress("glBindBuffer"), &bindBuffer); + AssignGLEntryPoint(loadProcAddress("glBindFramebuffer"), &bindFramebuffer); + AssignGLEntryPoint(loadProcAddress("glBindRenderbuffer"), &bindRenderbuffer); + AssignGLEntryPoint(loadProcAddress("glBindTexture"), &bindTexture); + AssignGLEntryPoint(loadProcAddress("glBlendColor"), &blendColor); + AssignGLEntryPoint(loadProcAddress("glBlendEquation"), &blendEquation); + AssignGLEntryPoint(loadProcAddress("glBlendEquationSeparate"), &blendEquationSeparate); + AssignGLEntryPoint(loadProcAddress("glBlendFunc"), &blendFunc); + AssignGLEntryPoint(loadProcAddress("glBlendFuncSeparate"), &blendFuncSeparate); + AssignGLEntryPoint(loadProcAddress("glBufferData"), &bufferData); + AssignGLEntryPoint(loadProcAddress("glBufferSubData"), &bufferSubData); + AssignGLEntryPoint(loadProcAddress("glCheckFramebufferStatus"), &checkFramebufferStatus); + AssignGLEntryPoint(loadProcAddress("glClear"), &clear); + AssignGLEntryPoint(loadProcAddress("glClearColor"), &clearColor); + AssignGLEntryPoint(loadProcAddress("glClearDepthf"), &clearDepthf); + AssignGLEntryPoint(loadProcAddress("glClearStencil"), &clearStencil); + AssignGLEntryPoint(loadProcAddress("glColorMask"), &colorMask); + AssignGLEntryPoint(loadProcAddress("glCompileShader"), &compileShader); + AssignGLEntryPoint(loadProcAddress("glCompressedTexImage2D"), &compressedTexImage2D); + AssignGLEntryPoint(loadProcAddress("glCompressedTexSubImage2D"), &compressedTexSubImage2D); + AssignGLEntryPoint(loadProcAddress("glCopyTexImage2D"), ©TexImage2D); + AssignGLEntryPoint(loadProcAddress("glCopyTexSubImage2D"), ©TexSubImage2D); + AssignGLEntryPoint(loadProcAddress("glCreateProgram"), &createProgram); + AssignGLEntryPoint(loadProcAddress("glCreateShader"), &createShader); + AssignGLEntryPoint(loadProcAddress("glCullFace"), &cullFace); + AssignGLEntryPoint(loadProcAddress("glDeleteBuffers"), &deleteBuffers); + AssignGLEntryPoint(loadProcAddress("glDeleteFramebuffers"), &deleteFramebuffers); + AssignGLEntryPoint(loadProcAddress("glDeleteProgram"), &deleteProgram); + AssignGLEntryPoint(loadProcAddress("glDeleteRenderbuffers"), &deleteRenderbuffers); + AssignGLEntryPoint(loadProcAddress("glDeleteShader"), &deleteShader); + AssignGLEntryPoint(loadProcAddress("glDeleteTextures"), &deleteTextures); + AssignGLEntryPoint(loadProcAddress("glDepthFunc"), &depthFunc); + AssignGLEntryPoint(loadProcAddress("glDepthMask"), &depthMask); + AssignGLEntryPoint(loadProcAddress("glDepthRangef"), &depthRangef); + AssignGLEntryPoint(loadProcAddress("glDetachShader"), &detachShader); + AssignGLEntryPoint(loadProcAddress("glDisable"), &disable); + AssignGLEntryPoint(loadProcAddress("glDisableVertexAttribArray"), &disableVertexAttribArray); + AssignGLEntryPoint(loadProcAddress("glDrawArrays"), &drawArrays); + AssignGLEntryPoint(loadProcAddress("glDrawElements"), &drawElements); + AssignGLEntryPoint(loadProcAddress("glEnable"), &enable); + AssignGLEntryPoint(loadProcAddress("glEnableVertexAttribArray"), &enableVertexAttribArray); + AssignGLEntryPoint(loadProcAddress("glFinish"), &finish); + AssignGLEntryPoint(loadProcAddress("glFlush"), &flush); + AssignGLEntryPoint(loadProcAddress("glFramebufferRenderbuffer"), &framebufferRenderbuffer); + AssignGLEntryPoint(loadProcAddress("glFramebufferTexture2D"), &framebufferTexture2D); + AssignGLEntryPoint(loadProcAddress("glFrontFace"), &frontFace); + AssignGLEntryPoint(loadProcAddress("glGenBuffers"), &genBuffers); + AssignGLEntryPoint(loadProcAddress("glGenerateMipmap"), &generateMipmap); + AssignGLEntryPoint(loadProcAddress("glGenFramebuffers"), &genFramebuffers); + AssignGLEntryPoint(loadProcAddress("glGenRenderbuffers"), &genRenderbuffers); + AssignGLEntryPoint(loadProcAddress("glGenTextures"), &genTextures); + AssignGLEntryPoint(loadProcAddress("glGetActiveAttrib"), &getActiveAttrib); + AssignGLEntryPoint(loadProcAddress("glGetActiveUniform"), &getActiveUniform); + AssignGLEntryPoint(loadProcAddress("glGetAttachedShaders"), &getAttachedShaders); + AssignGLEntryPoint(loadProcAddress("glGetAttribLocation"), &getAttribLocation); + AssignGLEntryPoint(loadProcAddress("glGetBooleanv"), &getBooleanv); + AssignGLEntryPoint(loadProcAddress("glGetBufferParameteriv"), &getBufferParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetError"), &getError); + AssignGLEntryPoint(loadProcAddress("glGetFloatv"), &getFloatv); + AssignGLEntryPoint(loadProcAddress("glGetFramebufferAttachmentParameteriv"), &getFramebufferAttachmentParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetIntegerv"), &getIntegerv); + AssignGLEntryPoint(loadProcAddress("glGetProgramiv"), &getProgramiv); + AssignGLEntryPoint(loadProcAddress("glGetProgramInfoLog"), &getProgramInfoLog); + AssignGLEntryPoint(loadProcAddress("glGetRenderbufferParameteriv"), &getRenderbufferParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetShaderiv"), &getShaderiv); + AssignGLEntryPoint(loadProcAddress("glGetShaderInfoLog"), &getShaderInfoLog); + AssignGLEntryPoint(loadProcAddress("glGetShaderPrecisionFormat"), &getShaderPrecisionFormat); + AssignGLEntryPoint(loadProcAddress("glGetShaderSource"), &getShaderSource); + AssignGLEntryPoint(loadProcAddress("glGetString"), &getString); + AssignGLEntryPoint(loadProcAddress("glGetTexParameterfv"), &getTexParameterfv); + AssignGLEntryPoint(loadProcAddress("glGetTexParameteriv"), &getTexParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetUniformfv"), &getUniformfv); + AssignGLEntryPoint(loadProcAddress("glGetUniformiv"), &getUniformiv); + AssignGLEntryPoint(loadProcAddress("glGetUniformLocation"), &getUniformLocation); + AssignGLEntryPoint(loadProcAddress("glGetVertexAttribfv"), &getVertexAttribfv); + AssignGLEntryPoint(loadProcAddress("glGetVertexAttribiv"), &getVertexAttribiv); + AssignGLEntryPoint(loadProcAddress("glGetVertexAttribPointerv"), &getVertexAttribPointerv); + AssignGLEntryPoint(loadProcAddress("glHint"), &hint); + AssignGLEntryPoint(loadProcAddress("glIsBuffer"), &isBuffer); + AssignGLEntryPoint(loadProcAddress("glIsEnabled"), &isEnabled); + AssignGLEntryPoint(loadProcAddress("glIsFramebuffer"), &isFramebuffer); + AssignGLEntryPoint(loadProcAddress("glIsProgram"), &isProgram); + AssignGLEntryPoint(loadProcAddress("glIsRenderbuffer"), &isRenderbuffer); + AssignGLEntryPoint(loadProcAddress("glIsShader"), &isShader); + AssignGLEntryPoint(loadProcAddress("glIsTexture"), &isTexture); + AssignGLEntryPoint(loadProcAddress("glLineWidth"), &lineWidth); + AssignGLEntryPoint(loadProcAddress("glLinkProgram"), &linkProgram); + AssignGLEntryPoint(loadProcAddress("glPixelStorei"), &pixelStorei); + AssignGLEntryPoint(loadProcAddress("glPolygonOffset"), &polygonOffset); + AssignGLEntryPoint(loadProcAddress("glReadPixels"), &readPixels); + AssignGLEntryPoint(loadProcAddress("glReleaseShaderCompiler"), &releaseShaderCompiler); + AssignGLEntryPoint(loadProcAddress("glRenderbufferStorage"), &renderbufferStorage); + AssignGLEntryPoint(loadProcAddress("glSampleCoverage"), &sampleCoverage); + AssignGLEntryPoint(loadProcAddress("glScissor"), &scissor); + AssignGLEntryPoint(loadProcAddress("glShaderBinary"), &shaderBinary); + AssignGLEntryPoint(loadProcAddress("glShaderSource"), &shaderSource); + AssignGLEntryPoint(loadProcAddress("glStencilFunc"), &stencilFunc); + AssignGLEntryPoint(loadProcAddress("glStencilFuncSeparate"), &stencilFuncSeparate); + AssignGLEntryPoint(loadProcAddress("glStencilMask"), &stencilMask); + AssignGLEntryPoint(loadProcAddress("glStencilMaskSeparate"), &stencilMaskSeparate); + AssignGLEntryPoint(loadProcAddress("glStencilOp"), &stencilOp); + AssignGLEntryPoint(loadProcAddress("glStencilOpSeparate"), &stencilOpSeparate); + AssignGLEntryPoint(loadProcAddress("glTexImage2D"), &texImage2D); + AssignGLEntryPoint(loadProcAddress("glTexParameterf"), &texParameterf); + AssignGLEntryPoint(loadProcAddress("glTexParameterfv"), &texParameterfv); + AssignGLEntryPoint(loadProcAddress("glTexParameteri"), &texParameteri); + AssignGLEntryPoint(loadProcAddress("glTexParameteriv"), &texParameteriv); + AssignGLEntryPoint(loadProcAddress("glTexSubImage2D"), &texSubImage2D); + AssignGLEntryPoint(loadProcAddress("glUniform1f"), &uniform1f); + AssignGLEntryPoint(loadProcAddress("glUniform1fv"), &uniform1fv); + AssignGLEntryPoint(loadProcAddress("glUniform1i"), &uniform1i); + AssignGLEntryPoint(loadProcAddress("glUniform1iv"), &uniform1iv); + AssignGLEntryPoint(loadProcAddress("glUniform2f"), &uniform2f); + AssignGLEntryPoint(loadProcAddress("glUniform2fv"), &uniform2fv); + AssignGLEntryPoint(loadProcAddress("glUniform2i"), &uniform2i); + AssignGLEntryPoint(loadProcAddress("glUniform2iv"), &uniform2iv); + AssignGLEntryPoint(loadProcAddress("glUniform3f"), &uniform3f); + AssignGLEntryPoint(loadProcAddress("glUniform3fv"), &uniform3fv); + AssignGLEntryPoint(loadProcAddress("glUniform3i"), &uniform3i); + AssignGLEntryPoint(loadProcAddress("glUniform3iv"), &uniform3iv); + AssignGLEntryPoint(loadProcAddress("glUniform4f"), &uniform4f); + AssignGLEntryPoint(loadProcAddress("glUniform4fv"), &uniform4fv); + AssignGLEntryPoint(loadProcAddress("glUniform4i"), &uniform4i); + AssignGLEntryPoint(loadProcAddress("glUniform4iv"), &uniform4iv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix2fv"), &uniformMatrix2fv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix3fv"), &uniformMatrix3fv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix4fv"), &uniformMatrix4fv); + AssignGLEntryPoint(loadProcAddress("glUseProgram"), &useProgram); + AssignGLEntryPoint(loadProcAddress("glValidateProgram"), &validateProgram); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib1f"), &vertexAttrib1f); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib1fv"), &vertexAttrib1fv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib2f"), &vertexAttrib2f); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib2fv"), &vertexAttrib2fv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib3f"), &vertexAttrib3f); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib3fv"), &vertexAttrib3fv); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4f"), &vertexAttrib4f); + AssignGLEntryPoint(loadProcAddress("glVertexAttrib4fv"), &vertexAttrib4fv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribPointer"), &vertexAttribPointer); + AssignGLEntryPoint(loadProcAddress("glViewport"), &viewport); + } + + // 3.0 + if (isAtLeastGLES(gl::Version(3, 0))) + { + AssignGLEntryPoint(loadProcAddress("glReadBuffer"), &readBuffer); + AssignGLEntryPoint(loadProcAddress("glDrawRangeElements"), &drawRangeElements); + AssignGLEntryPoint(loadProcAddress("glTexImage3D"), &texImage3D); + AssignGLEntryPoint(loadProcAddress("glTexSubImage3D"), &texSubImage3D); + AssignGLEntryPoint(loadProcAddress("glCopyTexSubImage3D"), ©TexSubImage3D); + AssignGLEntryPoint(loadProcAddress("glCompressedTexImage3D"), &compressedTexImage3D); + AssignGLEntryPoint(loadProcAddress("glCompressedTexSubImage3D"), &compressedTexSubImage3D); + AssignGLEntryPoint(loadProcAddress("glGenQueries"), &genQueries); + AssignGLEntryPoint(loadProcAddress("glDeleteQueries"), &deleteQueries); + AssignGLEntryPoint(loadProcAddress("glIsQuery"), &isQuery); + AssignGLEntryPoint(loadProcAddress("glBeginQuery"), &beginQuery); + AssignGLEntryPoint(loadProcAddress("glEndQuery"), &endQuery); + AssignGLEntryPoint(loadProcAddress("glGetQueryiv"), &getQueryiv); + AssignGLEntryPoint(loadProcAddress("glGetQueryObjectuiv"), &getQueryObjectuiv); + AssignGLEntryPoint(loadProcAddress("glUnmapBuffer"), &unmapBuffer); + AssignGLEntryPoint(loadProcAddress("glGetBufferPointerv"), &getBufferPointerv); + AssignGLEntryPoint(loadProcAddress("glDrawBuffers"), &drawBuffers); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix2x3fv"), &uniformMatrix2x3fv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix3x2fv"), &uniformMatrix3x2fv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix2x4fv"), &uniformMatrix2x4fv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix4x2fv"), &uniformMatrix4x2fv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix3x4fv"), &uniformMatrix3x4fv); + AssignGLEntryPoint(loadProcAddress("glUniformMatrix4x3fv"), &uniformMatrix4x3fv); + AssignGLEntryPoint(loadProcAddress("glBlitFramebuffer"), &blitFramebuffer); + AssignGLEntryPoint(loadProcAddress("glRenderbufferStorageMultisample"), &renderbufferStorageMultisample); + AssignGLEntryPoint(loadProcAddress("glFramebufferTextureLayer"), &framebufferTextureLayer); + AssignGLEntryPoint(loadProcAddress("glMapBufferRange"), &mapBufferRange); + AssignGLEntryPoint(loadProcAddress("glFlushMappedBufferRange"), &flushMappedBufferRange); + AssignGLEntryPoint(loadProcAddress("glBindVertexArray"), &bindVertexArray); + AssignGLEntryPoint(loadProcAddress("glDeleteVertexArrays"), &deleteVertexArrays); + AssignGLEntryPoint(loadProcAddress("glGenVertexArrays"), &genVertexArrays); + AssignGLEntryPoint(loadProcAddress("glIsVertexArray"), &isVertexArray); + AssignGLEntryPoint(loadProcAddress("glGetIntegeri_v"), &getIntegeri_v); + AssignGLEntryPoint(loadProcAddress("glBeginTransformFeedback"), &beginTransformFeedback); + AssignGLEntryPoint(loadProcAddress("glEndTransformFeedback"), &endTransformFeedback); + AssignGLEntryPoint(loadProcAddress("glBindBufferRange"), &bindBufferRange); + AssignGLEntryPoint(loadProcAddress("glBindBufferBase"), &bindBufferBase); + AssignGLEntryPoint(loadProcAddress("glTransformFeedbackVaryings"), &transformFeedbackVaryings); + AssignGLEntryPoint(loadProcAddress("glGetTransformFeedbackVarying"), &getTransformFeedbackVarying); + AssignGLEntryPoint(loadProcAddress("glVertexAttribIPointer"), &vertexAttribIPointer); + AssignGLEntryPoint(loadProcAddress("glGetVertexAttribIiv"), &getVertexAttribIiv); + AssignGLEntryPoint(loadProcAddress("glGetVertexAttribIuiv"), &getVertexAttribIuiv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI4i"), &vertexAttribI4i); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI4ui"), &vertexAttribI4ui); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI4iv"), &vertexAttribI4iv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribI4uiv"), &vertexAttribI4uiv); + AssignGLEntryPoint(loadProcAddress("glGetUniformuiv"), &getUniformuiv); + AssignGLEntryPoint(loadProcAddress("glGetFragDataLocation"), &getFragDataLocation); + AssignGLEntryPoint(loadProcAddress("glUniform1ui"), &uniform1ui); + AssignGLEntryPoint(loadProcAddress("glUniform2ui"), &uniform2ui); + AssignGLEntryPoint(loadProcAddress("glUniform3ui"), &uniform3ui); + AssignGLEntryPoint(loadProcAddress("glUniform4ui"), &uniform4ui); + AssignGLEntryPoint(loadProcAddress("glUniform1uiv"), &uniform1uiv); + AssignGLEntryPoint(loadProcAddress("glUniform2uiv"), &uniform2uiv); + AssignGLEntryPoint(loadProcAddress("glUniform3uiv"), &uniform3uiv); + AssignGLEntryPoint(loadProcAddress("glUniform4uiv"), &uniform4uiv); + AssignGLEntryPoint(loadProcAddress("glClearBufferiv"), &clearBufferiv); + AssignGLEntryPoint(loadProcAddress("glClearBufferuiv"), &clearBufferuiv); + AssignGLEntryPoint(loadProcAddress("glClearBufferfv"), &clearBufferfv); + AssignGLEntryPoint(loadProcAddress("glClearBufferfi"), &clearBufferfi); + AssignGLEntryPoint(loadProcAddress("glGetStringi"), &getStringi); + AssignGLEntryPoint(loadProcAddress("glCopyBufferSubData"), ©BufferSubData); + AssignGLEntryPoint(loadProcAddress("glGetUniformIndices"), &getUniformIndices); + AssignGLEntryPoint(loadProcAddress("glGetActiveUniformsiv"), &getActiveUniformsiv); + AssignGLEntryPoint(loadProcAddress("glGetUniformBlockIndex"), &getUniformBlockIndex); + AssignGLEntryPoint(loadProcAddress("glGetActiveUniformBlockiv"), &getActiveUniformBlockiv); + AssignGLEntryPoint(loadProcAddress("glGetActiveUniformBlockName"), &getActiveUniformBlockName); + AssignGLEntryPoint(loadProcAddress("glUniformBlockBinding"), &uniformBlockBinding); + AssignGLEntryPoint(loadProcAddress("glDrawArraysInstanced"), &drawArraysInstanced); + AssignGLEntryPoint(loadProcAddress("glDrawElementsInstanced"), &drawElementsInstanced); + AssignGLEntryPoint(loadProcAddress("glFenceSync"), &fenceSync); + AssignGLEntryPoint(loadProcAddress("glIsSync"), &isSync); + AssignGLEntryPoint(loadProcAddress("glDeleteSync"), &deleteSync); + AssignGLEntryPoint(loadProcAddress("glClientWaitSync"), &clientWaitSync); + AssignGLEntryPoint(loadProcAddress("glWaitSync"), &waitSync); + AssignGLEntryPoint(loadProcAddress("glGetInteger64v"), &getInteger64v); + AssignGLEntryPoint(loadProcAddress("glGetSynciv"), &getSynciv); + AssignGLEntryPoint(loadProcAddress("glGetInteger64i_v"), &getInteger64i_v); + AssignGLEntryPoint(loadProcAddress("glGetBufferParameteri64v"), &getBufferParameteri64v); + AssignGLEntryPoint(loadProcAddress("glGenSamplers"), &genSamplers); + AssignGLEntryPoint(loadProcAddress("glDeleteSamplers"), &deleteSamplers); + AssignGLEntryPoint(loadProcAddress("glIsSampler"), &isSampler); + AssignGLEntryPoint(loadProcAddress("glBindSampler"), &bindSampler); + AssignGLEntryPoint(loadProcAddress("glSamplerParameteri"), &samplerParameteri); + AssignGLEntryPoint(loadProcAddress("glSamplerParameteriv"), &samplerParameteriv); + AssignGLEntryPoint(loadProcAddress("glSamplerParameterf"), &samplerParameterf); + AssignGLEntryPoint(loadProcAddress("glSamplerParameterfv"), &samplerParameterfv); + AssignGLEntryPoint(loadProcAddress("glGetSamplerParameteriv"), &getSamplerParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetSamplerParameterfv"), &getSamplerParameterfv); + AssignGLEntryPoint(loadProcAddress("glVertexAttribDivisor"), &vertexAttribDivisor); + AssignGLEntryPoint(loadProcAddress("glBindTransformFeedback"), &bindTransformFeedback); + AssignGLEntryPoint(loadProcAddress("glDeleteTransformFeedbacks"), &deleteTransformFeedbacks); + AssignGLEntryPoint(loadProcAddress("glGenTransformFeedbacks"), &genTransformFeedbacks); + AssignGLEntryPoint(loadProcAddress("glIsTransformFeedback"), &isTransformFeedback); + AssignGLEntryPoint(loadProcAddress("glPauseTransformFeedback"), &pauseTransformFeedback); + AssignGLEntryPoint(loadProcAddress("glResumeTransformFeedback"), &resumeTransformFeedback); + AssignGLEntryPoint(loadProcAddress("glGetProgramBinary"), &getProgramBinary); + AssignGLEntryPoint(loadProcAddress("glProgramBinary"), &programBinary); + AssignGLEntryPoint(loadProcAddress("glProgramParameteri"), &programParameteri); + AssignGLEntryPoint(loadProcAddress("glInvalidateFramebuffer"), &invalidateFramebuffer); + AssignGLEntryPoint(loadProcAddress("glInvalidateSubFramebuffer"), &invalidateSubFramebuffer); + AssignGLEntryPoint(loadProcAddress("glTexStorage2D"), &texStorage2D); + AssignGLEntryPoint(loadProcAddress("glTexStorage3D"), &texStorage3D); + AssignGLEntryPoint(loadProcAddress("glGetInternalformativ"), &getInternalformativ); + } + + // 3.1 + if (isAtLeastGLES(gl::Version(3, 1))) + { + AssignGLEntryPoint(loadProcAddress("glDispatchCompute"), &dispatchCompute); + AssignGLEntryPoint(loadProcAddress("glDispatchComputeIndirect"), &dispatchComputeIndirect); + AssignGLEntryPoint(loadProcAddress("glDrawArraysIndirect"), &drawArraysIndirect); + AssignGLEntryPoint(loadProcAddress("glDrawElementsIndirect"), &drawElementsIndirect); + AssignGLEntryPoint(loadProcAddress("glFramebufferParameteri"), &framebufferParameteri); + AssignGLEntryPoint(loadProcAddress("glGetFramebufferParameteriv"), &getFramebufferParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetProgramInterfaceiv"), &getProgramInterfaceiv); + AssignGLEntryPoint(loadProcAddress("glGetProgramResourceIndex"), &getProgramResourceIndex); + AssignGLEntryPoint(loadProcAddress("glGetProgramResourceName"), &getProgramResourceName); + AssignGLEntryPoint(loadProcAddress("glGetProgramResourceiv"), &getProgramResourceiv); + AssignGLEntryPoint(loadProcAddress("glGetProgramResourceLocation"), &getProgramResourceLocation); + AssignGLEntryPoint(loadProcAddress("glUseProgramStages"), &useProgramStages); + AssignGLEntryPoint(loadProcAddress("glActiveShaderProgram"), &activeShaderProgram); + AssignGLEntryPoint(loadProcAddress("glCreateShaderProgramv"), &createShaderProgramv); + AssignGLEntryPoint(loadProcAddress("glBindProgramPipeline"), &bindProgramPipeline); + AssignGLEntryPoint(loadProcAddress("glDeleteProgramPipelines"), &deleteProgramPipelines); + AssignGLEntryPoint(loadProcAddress("glGenProgramPipelines"), &genProgramPipelines); + AssignGLEntryPoint(loadProcAddress("glIsProgramPipeline"), &isProgramPipeline); + AssignGLEntryPoint(loadProcAddress("glGetProgramPipelineiv"), &getProgramPipelineiv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform1i"), &programUniform1i); + AssignGLEntryPoint(loadProcAddress("glProgramUniform2i"), &programUniform2i); + AssignGLEntryPoint(loadProcAddress("glProgramUniform3i"), &programUniform3i); + AssignGLEntryPoint(loadProcAddress("glProgramUniform4i"), &programUniform4i); + AssignGLEntryPoint(loadProcAddress("glProgramUniform1ui"), &programUniform1ui); + AssignGLEntryPoint(loadProcAddress("glProgramUniform2ui"), &programUniform2ui); + AssignGLEntryPoint(loadProcAddress("glProgramUniform3ui"), &programUniform3ui); + AssignGLEntryPoint(loadProcAddress("glProgramUniform4ui"), &programUniform4ui); + AssignGLEntryPoint(loadProcAddress("glProgramUniform1f"), &programUniform1f); + AssignGLEntryPoint(loadProcAddress("glProgramUniform2f"), &programUniform2f); + AssignGLEntryPoint(loadProcAddress("glProgramUniform3f"), &programUniform3f); + AssignGLEntryPoint(loadProcAddress("glProgramUniform4f"), &programUniform4f); + AssignGLEntryPoint(loadProcAddress("glProgramUniform1iv"), &programUniform1iv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform2iv"), &programUniform2iv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform3iv"), &programUniform3iv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform4iv"), &programUniform4iv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform1uiv"), &programUniform1uiv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform2uiv"), &programUniform2uiv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform3uiv"), &programUniform3uiv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform4uiv"), &programUniform4uiv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform1fv"), &programUniform1fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform2fv"), &programUniform2fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform3fv"), &programUniform3fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniform4fv"), &programUniform4fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2fv"), &programUniformMatrix2fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3fv"), &programUniformMatrix3fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4fv"), &programUniformMatrix4fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2x3fv"), &programUniformMatrix2x3fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3x2fv"), &programUniformMatrix3x2fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2x4fv"), &programUniformMatrix2x4fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4x2fv"), &programUniformMatrix4x2fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3x4fv"), &programUniformMatrix3x4fv); + AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4x3fv"), &programUniformMatrix4x3fv); + AssignGLEntryPoint(loadProcAddress("glValidateProgramPipeline"), &validateProgramPipeline); + AssignGLEntryPoint(loadProcAddress("glGetProgramPipelineInfoLog"), &getProgramPipelineInfoLog); + AssignGLEntryPoint(loadProcAddress("glBindImageTexture"), &bindImageTexture); + AssignGLEntryPoint(loadProcAddress("glGetBooleani_v"), &getBooleani_v); + AssignGLEntryPoint(loadProcAddress("glMemoryBarrier"), &memoryBarrier); + AssignGLEntryPoint(loadProcAddress("glMemoryBarrierByRegion"), &memoryBarrierByRegion); + AssignGLEntryPoint(loadProcAddress("glTexStorage2DMultisample"), &texStorage2DMultisample); + AssignGLEntryPoint(loadProcAddress("glGetMultisamplefv"), &getMultisamplefv); + AssignGLEntryPoint(loadProcAddress("glSampleMaski"), &sampleMaski); + AssignGLEntryPoint(loadProcAddress("glGetTexLevelParameteriv"), &getTexLevelParameteriv); + AssignGLEntryPoint(loadProcAddress("glGetTexLevelParameterfv"), &getTexLevelParameterfv); + AssignGLEntryPoint(loadProcAddress("glBindVertexBuffer"), &bindVertexBuffer); + AssignGLEntryPoint(loadProcAddress("glVertexAttribFormat"), &vertexAttribFormat); + AssignGLEntryPoint(loadProcAddress("glVertexAttribIFormat"), &vertexAttribIFormat); + AssignGLEntryPoint(loadProcAddress("glVertexAttribBinding"), &vertexAttribBinding); + AssignGLEntryPoint(loadProcAddress("glVertexBindingDivisor"), &vertexBindingDivisor); + } + + // 3.2 + if (isAtLeastGLES(gl::Version(3, 2))) + { + AssignGLEntryPoint(loadProcAddress("glBlendBarrier"), &blendBarrier); + AssignGLEntryPoint(loadProcAddress("glCopyImageSubData"), ©ImageSubData); + AssignGLEntryPoint(loadProcAddress("glDebugMessageControl"), &debugMessageControl); + AssignGLEntryPoint(loadProcAddress("glDebugMessageInsert"), &debugMessageInsert); + AssignGLEntryPoint(loadProcAddress("glDebugMessageCallback"), &debugMessageCallback); + AssignGLEntryPoint(loadProcAddress("glGetDebugMessageLog"), &getDebugMessageLog); + AssignGLEntryPoint(loadProcAddress("glPushDebugGroup"), &pushDebugGroup); + AssignGLEntryPoint(loadProcAddress("glPopDebugGroup"), &popDebugGroup); + AssignGLEntryPoint(loadProcAddress("glObjectLabel"), &objectLabel); + AssignGLEntryPoint(loadProcAddress("glGetObjectLabel"), &getObjectLabel); + AssignGLEntryPoint(loadProcAddress("glObjectPtrLabel"), &objectPtrLabel); + AssignGLEntryPoint(loadProcAddress("glGetObjectPtrLabel"), &getObjectPtrLabel); + AssignGLEntryPoint(loadProcAddress("glGetPointerv"), &getPointerv); + AssignGLEntryPoint(loadProcAddress("glEnablei"), &enablei); + AssignGLEntryPoint(loadProcAddress("glDisablei"), &disablei); + AssignGLEntryPoint(loadProcAddress("glBlendEquationi"), &blendEquationi); + AssignGLEntryPoint(loadProcAddress("glBlendEquationSeparatei"), &blendEquationSeparatei); + AssignGLEntryPoint(loadProcAddress("glBlendFunci"), &blendFunci); + AssignGLEntryPoint(loadProcAddress("glBlendFuncSeparatei"), &blendFuncSeparatei); + AssignGLEntryPoint(loadProcAddress("glColorMaski"), &colorMaski); + AssignGLEntryPoint(loadProcAddress("glIsEnabledi"), &isEnabledi); + AssignGLEntryPoint(loadProcAddress("glDrawElementsBaseVertex"), &drawElementsBaseVertex); + AssignGLEntryPoint(loadProcAddress("glDrawRangeElementsBaseVertex"), &drawRangeElementsBaseVertex); + AssignGLEntryPoint(loadProcAddress("glDrawElementsInstancedBaseVertex"), &drawElementsInstancedBaseVertex); + AssignGLEntryPoint(loadProcAddress("glFramebufferTexture"), &framebufferTexture); + AssignGLEntryPoint(loadProcAddress("glPrimitiveBoundingBox"), &primitiveBoundingBox); + AssignGLEntryPoint(loadProcAddress("glGetGraphicsResetStatus"), &getGraphicsResetStatus); + AssignGLEntryPoint(loadProcAddress("glReadnPixels"), &readnPixels); + AssignGLEntryPoint(loadProcAddress("glGetnUniformfv"), &getnUniformfv); + AssignGLEntryPoint(loadProcAddress("glGetnUniformiv"), &getnUniformiv); + AssignGLEntryPoint(loadProcAddress("glGetnUniformuiv"), &getnUniformuiv); + AssignGLEntryPoint(loadProcAddress("glMinSampleShading"), &minSampleShading); + AssignGLEntryPoint(loadProcAddress("glPatchParameteri"), &patchParameteri); + AssignGLEntryPoint(loadProcAddress("glTexParameterIiv"), &texParameterIiv); + AssignGLEntryPoint(loadProcAddress("glTexParameterIuiv"), &texParameterIuiv); + AssignGLEntryPoint(loadProcAddress("glGetTexParameterIiv"), &getTexParameterIiv); + AssignGLEntryPoint(loadProcAddress("glGetTexParameterIuiv"), &getTexParameterIuiv); + AssignGLEntryPoint(loadProcAddress("glSamplerParameterIiv"), &samplerParameterIiv); + AssignGLEntryPoint(loadProcAddress("glSamplerParameterIuiv"), &samplerParameterIuiv); + AssignGLEntryPoint(loadProcAddress("glGetSamplerParameterIiv"), &getSamplerParameterIiv); + AssignGLEntryPoint(loadProcAddress("glGetSamplerParameterIuiv"), &getSamplerParameterIuiv); + AssignGLEntryPoint(loadProcAddress("glTexBuffer"), &texBuffer); + AssignGLEntryPoint(loadProcAddress("glTexBufferRange"), &texBufferRange); + AssignGLEntryPoint(loadProcAddress("glTexStorage3DMultisample"), &texStorage3DMultisample); + } + + // clang-format on +} + +bool FunctionsGL::isAtLeastGL(const gl::Version &glVersion) const +{ + return standard == STANDARD_GL_DESKTOP && version >= glVersion; +} + +bool FunctionsGL::isAtMostGL(const gl::Version &glVersion) const +{ + return standard == STANDARD_GL_DESKTOP && glVersion >= version; +} + +bool FunctionsGL::isAtLeastGLES(const gl::Version &glesVersion) const +{ + return standard == STANDARD_GL_ES && version >= glesVersion; +} + +bool FunctionsGL::isAtMostGLES(const gl::Version &glesVersion) const +{ + return standard == STANDARD_GL_ES && glesVersion >= version; +} + +bool FunctionsGL::hasExtension(const std::string &ext) const +{ + return std::find(extensions.begin(), extensions.end(), ext) != extensions.end(); +} + +bool FunctionsGL::hasGLExtension(const std::string &ext) const +{ + return standard == STANDARD_GL_DESKTOP && hasExtension(ext); +} + +bool FunctionsGL::hasGLESExtension(const std::string &ext) const +{ + return standard == STANDARD_GL_ES && hasExtension(ext); +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.h b/gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.h new file mode 100755 index 000000000..fa8634e57 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.h @@ -0,0 +1,791 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FunctionsGL.h: Defines the FuntionsGL class to contain loaded GL functions + +#ifndef LIBANGLE_RENDERER_GL_FUNCTIONSGL_H_ +#define LIBANGLE_RENDERER_GL_FUNCTIONSGL_H_ + +#include "common/debug.h" +#include "libANGLE/Version.h" +#include "libANGLE/renderer/gl/functionsgl_enums.h" +#include "libANGLE/renderer/gl/functionsgl_typedefs.h" + +namespace rx +{ + +enum StandardGL +{ + STANDARD_GL_DESKTOP, + STANDARD_GL_ES, +}; + +class FunctionsGL +{ + public: + FunctionsGL(); + virtual ~FunctionsGL(); + + void initialize(); + + // Version information + gl::Version version; + StandardGL standard; + GLint profile; + bool isAtLeastGL(const gl::Version &glVersion) const; + bool isAtMostGL(const gl::Version &glVersion) const; + bool isAtLeastGLES(const gl::Version &glesVersion) const; + bool isAtMostGLES(const gl::Version &glesVersion) const; + + // Extensions + std::vector<std::string> extensions; + bool hasExtension(const std::string &ext) const; + bool hasGLExtension(const std::string &ext) const; + bool hasGLESExtension(const std::string &ext) const; + + // Entry Points + // 1.0 + PFNGLBLENDFUNCPROC blendFunc; + PFNGLCLEARPROC clear; + PFNGLCLEARCOLORPROC clearColor; + PFNGLCLEARDEPTHPROC clearDepth; + PFNGLCLEARSTENCILPROC clearStencil; + PFNGLCOLORMASKPROC colorMask; + PFNGLCULLFACEPROC cullFace; + PFNGLDEPTHFUNCPROC depthFunc; + PFNGLDEPTHMASKPROC depthMask; + PFNGLDEPTHRANGEPROC depthRange; + PFNGLDISABLEPROC disable; + PFNGLDRAWBUFFERPROC drawBuffer; + PFNGLENABLEPROC enable; + PFNGLFINISHPROC finish; + PFNGLFLUSHPROC flush; + PFNGLFRONTFACEPROC frontFace; + PFNGLGETBOOLEANVPROC getBooleanv; + PFNGLGETDOUBLEVPROC getDoublev; + PFNGLGETERRORPROC getError; + PFNGLGETFLOATVPROC getFloatv; + PFNGLGETINTEGERVPROC getIntegerv; + PFNGLGETSTRINGPROC getString; + PFNGLGETTEXIMAGEPROC getTexImage; + PFNGLGETTEXLEVELPARAMETERFVPROC getTexLevelParameterfv; + PFNGLGETTEXLEVELPARAMETERIVPROC getTexLevelParameteriv; + PFNGLGETTEXPARAMETERFVPROC getTexParameterfv; + PFNGLGETTEXPARAMETERIVPROC getTexParameteriv; + PFNGLHINTPROC hint; + PFNGLISENABLEDPROC isEnabled; + PFNGLLINEWIDTHPROC lineWidth; + PFNGLLOGICOPPROC logicOp; + PFNGLPIXELSTOREFPROC pixelStoref; + PFNGLPIXELSTOREIPROC pixelStorei; + PFNGLPOINTSIZEPROC pointSize; + PFNGLPOLYGONMODEPROC polygonMode; + PFNGLREADBUFFERPROC readBuffer; + PFNGLREADPIXELSPROC readPixels; + PFNGLSCISSORPROC scissor; + PFNGLSTENCILFUNCPROC stencilFunc; + PFNGLSTENCILMASKPROC stencilMask; + PFNGLSTENCILOPPROC stencilOp; + PFNGLTEXIMAGE1DPROC texImage1D; + PFNGLTEXIMAGE2DPROC texImage2D; + PFNGLTEXPARAMETERFPROC texParameterf; + PFNGLTEXPARAMETERFVPROC texParameterfv; + PFNGLTEXPARAMETERIPROC texParameteri; + PFNGLTEXPARAMETERIVPROC texParameteriv; + PFNGLVIEWPORTPROC viewport; + + // 1.1 + PFNGLBINDTEXTUREPROC bindTexture; + PFNGLCOPYTEXIMAGE1DPROC copyTexImage1D; + PFNGLCOPYTEXIMAGE2DPROC copyTexImage2D; + PFNGLCOPYTEXSUBIMAGE1DPROC copyTexSubImage1D; + PFNGLCOPYTEXSUBIMAGE2DPROC copyTexSubImage2D; + PFNGLDELETETEXTURESPROC deleteTextures; + PFNGLDRAWARRAYSPROC drawArrays; + PFNGLDRAWELEMENTSPROC drawElements; + PFNGLGENTEXTURESPROC genTextures; + PFNGLISTEXTUREPROC isTexture; + PFNGLPOLYGONOFFSETPROC polygonOffset; + PFNGLTEXSUBIMAGE1DPROC texSubImage1D; + PFNGLTEXSUBIMAGE2DPROC texSubImage2D; + + // 1.2 + PFNGLBLENDCOLORPROC blendColor; + PFNGLBLENDEQUATIONPROC blendEquation; + PFNGLCOPYTEXSUBIMAGE3DPROC copyTexSubImage3D; + PFNGLDRAWRANGEELEMENTSPROC drawRangeElements; + PFNGLTEXIMAGE3DPROC texImage3D; + PFNGLTEXSUBIMAGE3DPROC texSubImage3D; + + // 1.2 Extensions + PFNGLDELETEFENCESNVPROC deleteFencesNV; + PFNGLGENFENCESNVPROC genFencesNV; + PFNGLISFENCENVPROC isFenceNV; + PFNGLTESTFENCENVPROC testFenceNV; + PFNGLGETFENCEIVNVPROC getFenceivNV; + PFNGLFINISHFENCENVPROC finishFenceNV; + PFNGLSETFENCENVPROC setFenceNV; + + // 1.3 + PFNGLACTIVETEXTUREPROC activeTexture; + PFNGLCOMPRESSEDTEXIMAGE1DPROC compressedTexImage1D; + PFNGLCOMPRESSEDTEXIMAGE2DPROC compressedTexImage2D; + PFNGLCOMPRESSEDTEXIMAGE3DPROC compressedTexImage3D; + PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC compressedTexSubImage1D; + PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC compressedTexSubImage2D; + PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC compressedTexSubImage3D; + PFNGLGETCOMPRESSEDTEXIMAGEPROC getCompressedTexImage; + PFNGLSAMPLECOVERAGEPROC sampleCoverage; + + // 1.4 + PFNGLBLENDFUNCSEPARATEPROC blendFuncSeparate; + PFNGLMULTIDRAWARRAYSPROC multiDrawArrays; + PFNGLMULTIDRAWELEMENTSPROC multiDrawElements; + PFNGLPOINTPARAMETERFPROC pointParameterf; + PFNGLPOINTPARAMETERFVPROC pointParameterfv; + PFNGLPOINTPARAMETERIPROC pointParameteri; + PFNGLPOINTPARAMETERIVPROC pointParameteriv; + + // 1.5 + PFNGLBEGINQUERYPROC beginQuery; + PFNGLBINDBUFFERPROC bindBuffer; + PFNGLBUFFERDATAPROC bufferData; + PFNGLBUFFERSUBDATAPROC bufferSubData; + PFNGLDELETEBUFFERSPROC deleteBuffers; + PFNGLDELETEQUERIESPROC deleteQueries; + PFNGLENDQUERYPROC endQuery; + PFNGLGENBUFFERSPROC genBuffers; + PFNGLGENQUERIESPROC genQueries; + PFNGLGETBUFFERPARAMETERIVPROC getBufferParameteriv; + PFNGLGETBUFFERPOINTERVPROC getBufferPointerv; + PFNGLGETBUFFERSUBDATAPROC getBufferSubData; + PFNGLGETQUERYOBJECTIVPROC getQueryObjectiv; + PFNGLGETQUERYOBJECTUIVPROC getQueryObjectuiv; + PFNGLGETQUERYIVPROC getQueryiv; + PFNGLISBUFFERPROC isBuffer; + PFNGLISQUERYPROC isQuery; + PFNGLMAPBUFFERPROC mapBuffer; + PFNGLUNMAPBUFFERPROC unmapBuffer; + + // 2.0 + PFNGLATTACHSHADERPROC attachShader; + PFNGLBINDATTRIBLOCATIONPROC bindAttribLocation; + PFNGLBLENDEQUATIONSEPARATEPROC blendEquationSeparate; + PFNGLCOMPILESHADERPROC compileShader; + PFNGLCREATEPROGRAMPROC createProgram; + PFNGLCREATESHADERPROC createShader; + PFNGLDELETEPROGRAMPROC deleteProgram; + PFNGLDELETESHADERPROC deleteShader; + PFNGLDETACHSHADERPROC detachShader; + PFNGLDISABLEVERTEXATTRIBARRAYPROC disableVertexAttribArray; + PFNGLDRAWBUFFERSPROC drawBuffers; + PFNGLENABLEVERTEXATTRIBARRAYPROC enableVertexAttribArray; + PFNGLGETACTIVEATTRIBPROC getActiveAttrib; + PFNGLGETACTIVEUNIFORMPROC getActiveUniform; + PFNGLGETATTACHEDSHADERSPROC getAttachedShaders; + PFNGLGETATTRIBLOCATIONPROC getAttribLocation; + PFNGLGETPROGRAMINFOLOGPROC getProgramInfoLog; + PFNGLGETPROGRAMIVPROC getProgramiv; + PFNGLGETSHADERINFOLOGPROC getShaderInfoLog; + PFNGLGETSHADERSOURCEPROC getShaderSource; + PFNGLGETSHADERIVPROC getShaderiv; + PFNGLGETUNIFORMLOCATIONPROC getUniformLocation; + PFNGLGETUNIFORMFVPROC getUniformfv; + PFNGLGETUNIFORMIVPROC getUniformiv; + PFNGLGETVERTEXATTRIBPOINTERVPROC getVertexAttribPointerv; + PFNGLGETVERTEXATTRIBDVPROC getVertexAttribdv; + PFNGLGETVERTEXATTRIBFVPROC getVertexAttribfv; + PFNGLGETVERTEXATTRIBIVPROC getVertexAttribiv; + PFNGLISPROGRAMPROC isProgram; + PFNGLISSHADERPROC isShader; + PFNGLLINKPROGRAMPROC linkProgram; + PFNGLSHADERSOURCEPROC shaderSource; + PFNGLSTENCILFUNCSEPARATEPROC stencilFuncSeparate; + PFNGLSTENCILMASKSEPARATEPROC stencilMaskSeparate; + PFNGLSTENCILOPSEPARATEPROC stencilOpSeparate; + PFNGLUNIFORM1FPROC uniform1f; + PFNGLUNIFORM1FVPROC uniform1fv; + PFNGLUNIFORM1IPROC uniform1i; + PFNGLUNIFORM1IVPROC uniform1iv; + PFNGLUNIFORM2FPROC uniform2f; + PFNGLUNIFORM2FVPROC uniform2fv; + PFNGLUNIFORM2IPROC uniform2i; + PFNGLUNIFORM2IVPROC uniform2iv; + PFNGLUNIFORM3FPROC uniform3f; + PFNGLUNIFORM3FVPROC uniform3fv; + PFNGLUNIFORM3IPROC uniform3i; + PFNGLUNIFORM3IVPROC uniform3iv; + PFNGLUNIFORM4FPROC uniform4f; + PFNGLUNIFORM4FVPROC uniform4fv; + PFNGLUNIFORM4IPROC uniform4i; + PFNGLUNIFORM4IVPROC uniform4iv; + PFNGLUNIFORMMATRIX2FVPROC uniformMatrix2fv; + PFNGLUNIFORMMATRIX3FVPROC uniformMatrix3fv; + PFNGLUNIFORMMATRIX4FVPROC uniformMatrix4fv; + PFNGLUSEPROGRAMPROC useProgram; + PFNGLVALIDATEPROGRAMPROC validateProgram; + PFNGLVERTEXATTRIB1DPROC vertexAttrib1d; + PFNGLVERTEXATTRIB1DVPROC vertexAttrib1dv; + PFNGLVERTEXATTRIB1FPROC vertexAttrib1f; + PFNGLVERTEXATTRIB1FVPROC vertexAttrib1fv; + PFNGLVERTEXATTRIB1SPROC vertexAttrib1s; + PFNGLVERTEXATTRIB1SVPROC vertexAttrib1sv; + PFNGLVERTEXATTRIB2DPROC vertexAttrib2d; + PFNGLVERTEXATTRIB2DVPROC vertexAttrib2dv; + PFNGLVERTEXATTRIB2FPROC vertexAttrib2f; + PFNGLVERTEXATTRIB2FVPROC vertexAttrib2fv; + PFNGLVERTEXATTRIB2SPROC vertexAttrib2s; + PFNGLVERTEXATTRIB2SVPROC vertexAttrib2sv; + PFNGLVERTEXATTRIB3DPROC vertexAttrib3d; + PFNGLVERTEXATTRIB3DVPROC vertexAttrib3dv; + PFNGLVERTEXATTRIB3FPROC vertexAttrib3f; + PFNGLVERTEXATTRIB3FVPROC vertexAttrib3fv; + PFNGLVERTEXATTRIB3SPROC vertexAttrib3s; + PFNGLVERTEXATTRIB3SVPROC vertexAttrib3sv; + PFNGLVERTEXATTRIB4NBVPROC vertexAttrib4Nbv; + PFNGLVERTEXATTRIB4NIVPROC vertexAttrib4Niv; + PFNGLVERTEXATTRIB4NSVPROC vertexAttrib4Nsv; + PFNGLVERTEXATTRIB4NUBPROC vertexAttrib4Nub; + PFNGLVERTEXATTRIB4NUBVPROC vertexAttrib4Nubv; + PFNGLVERTEXATTRIB4NUIVPROC vertexAttrib4Nuiv; + PFNGLVERTEXATTRIB4NUSVPROC vertexAttrib4Nusv; + PFNGLVERTEXATTRIB4BVPROC vertexAttrib4bv; + PFNGLVERTEXATTRIB4DPROC vertexAttrib4d; + PFNGLVERTEXATTRIB4DVPROC vertexAttrib4dv; + PFNGLVERTEXATTRIB4FPROC vertexAttrib4f; + PFNGLVERTEXATTRIB4FVPROC vertexAttrib4fv; + PFNGLVERTEXATTRIB4IVPROC vertexAttrib4iv; + PFNGLVERTEXATTRIB4SPROC vertexAttrib4s; + PFNGLVERTEXATTRIB4SVPROC vertexAttrib4sv; + PFNGLVERTEXATTRIB4UBVPROC vertexAttrib4ubv; + PFNGLVERTEXATTRIB4UIVPROC vertexAttrib4uiv; + PFNGLVERTEXATTRIB4USVPROC vertexAttrib4usv; + PFNGLVERTEXATTRIBPOINTERPROC vertexAttribPointer; + + // 2.1 + PFNGLUNIFORMMATRIX2X3FVPROC uniformMatrix2x3fv; + PFNGLUNIFORMMATRIX2X4FVPROC uniformMatrix2x4fv; + PFNGLUNIFORMMATRIX3X2FVPROC uniformMatrix3x2fv; + PFNGLUNIFORMMATRIX3X4FVPROC uniformMatrix3x4fv; + PFNGLUNIFORMMATRIX4X2FVPROC uniformMatrix4x2fv; + PFNGLUNIFORMMATRIX4X3FVPROC uniformMatrix4x3fv; + + // 3.0 + PFNGLBEGINCONDITIONALRENDERPROC beginConditionalRender; + PFNGLBEGINTRANSFORMFEEDBACKPROC beginTransformFeedback; + PFNGLBINDBUFFERBASEPROC bindBufferBase; + PFNGLBINDBUFFERRANGEPROC bindBufferRange; + PFNGLBINDFRAGDATALOCATIONPROC bindFragDataLocation; + PFNGLBINDFRAMEBUFFERPROC bindFramebuffer; + PFNGLBINDRENDERBUFFERPROC bindRenderbuffer; + PFNGLBINDVERTEXARRAYPROC bindVertexArray; + PFNGLBLITFRAMEBUFFERPROC blitFramebuffer; + PFNGLCHECKFRAMEBUFFERSTATUSPROC checkFramebufferStatus; + PFNGLCLAMPCOLORPROC clampColor; + PFNGLCLEARBUFFERFIPROC clearBufferfi; + PFNGLCLEARBUFFERFVPROC clearBufferfv; + PFNGLCLEARBUFFERIVPROC clearBufferiv; + PFNGLCLEARBUFFERUIVPROC clearBufferuiv; + PFNGLCOLORMASKIPROC colorMaski; + PFNGLDELETEFRAMEBUFFERSPROC deleteFramebuffers; + PFNGLDELETERENDERBUFFERSPROC deleteRenderbuffers; + PFNGLDELETEVERTEXARRAYSPROC deleteVertexArrays; + PFNGLDISABLEIPROC disablei; + PFNGLENABLEIPROC enablei; + PFNGLENDCONDITIONALRENDERPROC endConditionalRender; + PFNGLENDTRANSFORMFEEDBACKPROC endTransformFeedback; + PFNGLFLUSHMAPPEDBUFFERRANGEPROC flushMappedBufferRange; + PFNGLFRAMEBUFFERRENDERBUFFERPROC framebufferRenderbuffer; + PFNGLFRAMEBUFFERTEXTURE1DPROC framebufferTexture1D; + PFNGLFRAMEBUFFERTEXTURE2DPROC framebufferTexture2D; + PFNGLFRAMEBUFFERTEXTURE3DPROC framebufferTexture3D; + PFNGLFRAMEBUFFERTEXTURELAYERPROC framebufferTextureLayer; + PFNGLGENFRAMEBUFFERSPROC genFramebuffers; + PFNGLGENRENDERBUFFERSPROC genRenderbuffers; + PFNGLGENVERTEXARRAYSPROC genVertexArrays; + PFNGLGENERATEMIPMAPPROC generateMipmap; + PFNGLGETBOOLEANI_VPROC getBooleani_v; + PFNGLGETFRAGDATALOCATIONPROC getFragDataLocation; + PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC getFramebufferAttachmentParameteriv; + PFNGLGETINTEGERI_VPROC getIntegeri_v; + PFNGLGETRENDERBUFFERPARAMETERIVPROC getRenderbufferParameteriv; + PFNGLGETSTRINGIPROC getStringi; + PFNGLGETTEXPARAMETERIIVPROC getTexParameterIiv; + PFNGLGETTEXPARAMETERIUIVPROC getTexParameterIuiv; + PFNGLGETTRANSFORMFEEDBACKVARYINGPROC getTransformFeedbackVarying; + PFNGLGETUNIFORMUIVPROC getUniformuiv; + PFNGLGETVERTEXATTRIBIIVPROC getVertexAttribIiv; + PFNGLGETVERTEXATTRIBIUIVPROC getVertexAttribIuiv; + PFNGLISENABLEDIPROC isEnabledi; + PFNGLISFRAMEBUFFERPROC isFramebuffer; + PFNGLISRENDERBUFFERPROC isRenderbuffer; + PFNGLISVERTEXARRAYPROC isVertexArray; + PFNGLMAPBUFFERRANGEPROC mapBufferRange; + PFNGLRENDERBUFFERSTORAGEPROC renderbufferStorage; + PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC renderbufferStorageMultisample; + PFNGLTEXPARAMETERIIVPROC texParameterIiv; + PFNGLTEXPARAMETERIUIVPROC texParameterIuiv; + PFNGLTRANSFORMFEEDBACKVARYINGSPROC transformFeedbackVaryings; + PFNGLUNIFORM1UIPROC uniform1ui; + PFNGLUNIFORM1UIVPROC uniform1uiv; + PFNGLUNIFORM2UIPROC uniform2ui; + PFNGLUNIFORM2UIVPROC uniform2uiv; + PFNGLUNIFORM3UIPROC uniform3ui; + PFNGLUNIFORM3UIVPROC uniform3uiv; + PFNGLUNIFORM4UIPROC uniform4ui; + PFNGLUNIFORM4UIVPROC uniform4uiv; + PFNGLVERTEXATTRIBI1IPROC vertexAttribI1i; + PFNGLVERTEXATTRIBI1IVPROC vertexAttribI1iv; + PFNGLVERTEXATTRIBI1UIPROC vertexAttribI1ui; + PFNGLVERTEXATTRIBI1UIVPROC vertexAttribI1uiv; + PFNGLVERTEXATTRIBI2IPROC vertexAttribI2i; + PFNGLVERTEXATTRIBI2IVPROC vertexAttribI2iv; + PFNGLVERTEXATTRIBI2UIPROC vertexAttribI2ui; + PFNGLVERTEXATTRIBI2UIVPROC vertexAttribI2uiv; + PFNGLVERTEXATTRIBI3IPROC vertexAttribI3i; + PFNGLVERTEXATTRIBI3IVPROC vertexAttribI3iv; + PFNGLVERTEXATTRIBI3UIPROC vertexAttribI3ui; + PFNGLVERTEXATTRIBI3UIVPROC vertexAttribI3uiv; + PFNGLVERTEXATTRIBI4BVPROC vertexAttribI4bv; + PFNGLVERTEXATTRIBI4IPROC vertexAttribI4i; + PFNGLVERTEXATTRIBI4IVPROC vertexAttribI4iv; + PFNGLVERTEXATTRIBI4SVPROC vertexAttribI4sv; + PFNGLVERTEXATTRIBI4UBVPROC vertexAttribI4ubv; + PFNGLVERTEXATTRIBI4UIPROC vertexAttribI4ui; + PFNGLVERTEXATTRIBI4UIVPROC vertexAttribI4uiv; + PFNGLVERTEXATTRIBI4USVPROC vertexAttribI4usv; + PFNGLVERTEXATTRIBIPOINTERPROC vertexAttribIPointer; + + // 3.1 + PFNGLCOPYBUFFERSUBDATAPROC copyBufferSubData; + PFNGLDRAWARRAYSINSTANCEDPROC drawArraysInstanced; + PFNGLDRAWELEMENTSINSTANCEDPROC drawElementsInstanced; + PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC getActiveUniformBlockName; + PFNGLGETACTIVEUNIFORMBLOCKIVPROC getActiveUniformBlockiv; + PFNGLGETACTIVEUNIFORMNAMEPROC getActiveUniformName; + PFNGLGETACTIVEUNIFORMSIVPROC getActiveUniformsiv; + PFNGLGETUNIFORMBLOCKINDEXPROC getUniformBlockIndex; + PFNGLGETUNIFORMINDICESPROC getUniformIndices; + PFNGLPRIMITIVERESTARTINDEXPROC primitiveRestartIndex; + PFNGLTEXBUFFERPROC texBuffer; + PFNGLUNIFORMBLOCKBINDINGPROC uniformBlockBinding; + + // 3.2 + PFNGLCLIENTWAITSYNCPROC clientWaitSync; + PFNGLDELETESYNCPROC deleteSync; + PFNGLDRAWELEMENTSBASEVERTEXPROC drawElementsBaseVertex; + PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC drawElementsInstancedBaseVertex; + PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC drawRangeElementsBaseVertex; + PFNGLFENCESYNCPROC fenceSync; + PFNGLFRAMEBUFFERTEXTUREPROC framebufferTexture; + PFNGLGETBUFFERPARAMETERI64VPROC getBufferParameteri64v; + PFNGLGETINTEGER64I_VPROC getInteger64i_v; + PFNGLGETINTEGER64VPROC getInteger64v; + PFNGLGETMULTISAMPLEFVPROC getMultisamplefv; + PFNGLGETSYNCIVPROC getSynciv; + PFNGLISSYNCPROC isSync; + PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC multiDrawElementsBaseVertex; + PFNGLPROVOKINGVERTEXPROC provokingVertex; + PFNGLSAMPLEMASKIPROC sampleMaski; + PFNGLTEXIMAGE2DMULTISAMPLEPROC texImage2DMultisample; + PFNGLTEXIMAGE3DMULTISAMPLEPROC texImage3DMultisample; + PFNGLWAITSYNCPROC waitSync; + + // NV_path_rendering (originally written against 3.2 compatibility profile) + PFNGLMATRIXLOADFEXTPROC matrixLoadEXT; + PFNGLGENPATHSNVPROC genPathsNV; + PFNGLDELETEPATHSNVPROC delPathsNV; + PFNGLPATHCOMMANDSNVPROC pathCommandsNV; + PFNGLISPATHNVPROC isPathNV; + PFNGLPATHPARAMETERFNVPROC setPathParameterfNV; + PFNGLPATHPARAMETERINVPROC setPathParameteriNV; + PFNGLGETPATHPARAMETERFVNVPROC getPathParameterfNV; + PFNGLGETPATHPARAMETERIVNVPROC getPathParameteriNV; + PFNGLPATHSTENCILFUNCNVPROC pathStencilFuncNV; + PFNGLSTENCILFILLPATHNVPROC stencilFillPathNV; + PFNGLSTENCILSTROKEPATHNVPROC stencilStrokePathNV; + PFNGLCOVERFILLPATHNVPROC coverFillPathNV; + PFNGLCOVERSTROKEPATHNVPROC coverStrokePathNV; + PFNGLSTENCILTHENCOVERFILLPATHNVPROC stencilThenCoverFillPathNV; + PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC stencilThenCoverStrokePathNV; + PFNGLCOVERFILLPATHINSTANCEDNVPROC coverFillPathInstancedNV; + PFNGLCOVERSTROKEPATHINSTANCEDNVPROC coverStrokePathInstancedNV; + PFNGLSTENCILFILLPATHINSTANCEDNVPROC stencilFillPathInstancedNV; + PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC stencilStrokePathInstancedNV; + PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC stencilThenCoverFillPathInstancedNV; + PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC stencilThenCoverStrokePathInstancedNV; + PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC programPathFragmentInputGenNV; + + // 3.3 + PFNGLBINDFRAGDATALOCATIONINDEXEDPROC bindFragDataLocationIndexed; + PFNGLBINDSAMPLERPROC bindSampler; + PFNGLDELETESAMPLERSPROC deleteSamplers; + PFNGLGENSAMPLERSPROC genSamplers; + PFNGLGETFRAGDATAINDEXPROC getFragDataIndex; + PFNGLGETQUERYOBJECTI64VPROC getQueryObjecti64v; + PFNGLGETQUERYOBJECTUI64VPROC getQueryObjectui64v; + PFNGLGETSAMPLERPARAMETERIIVPROC getSamplerParameterIiv; + PFNGLGETSAMPLERPARAMETERIUIVPROC getSamplerParameterIuiv; + PFNGLGETSAMPLERPARAMETERFVPROC getSamplerParameterfv; + PFNGLGETSAMPLERPARAMETERIVPROC getSamplerParameteriv; + PFNGLISSAMPLERPROC isSampler; + PFNGLQUERYCOUNTERPROC queryCounter; + PFNGLSAMPLERPARAMETERIIVPROC samplerParameterIiv; + PFNGLSAMPLERPARAMETERIUIVPROC samplerParameterIuiv; + PFNGLSAMPLERPARAMETERFPROC samplerParameterf; + PFNGLSAMPLERPARAMETERFVPROC samplerParameterfv; + PFNGLSAMPLERPARAMETERIPROC samplerParameteri; + PFNGLSAMPLERPARAMETERIVPROC samplerParameteriv; + PFNGLVERTEXATTRIBDIVISORPROC vertexAttribDivisor; + PFNGLVERTEXATTRIBP1UIPROC vertexAttribP1ui; + PFNGLVERTEXATTRIBP1UIVPROC vertexAttribP1uiv; + PFNGLVERTEXATTRIBP2UIPROC vertexAttribP2ui; + PFNGLVERTEXATTRIBP2UIVPROC vertexAttribP2uiv; + PFNGLVERTEXATTRIBP3UIPROC vertexAttribP3ui; + PFNGLVERTEXATTRIBP3UIVPROC vertexAttribP3uiv; + PFNGLVERTEXATTRIBP4UIPROC vertexAttribP4ui; + PFNGLVERTEXATTRIBP4UIVPROC vertexAttribP4uiv; + + // 4.0 + PFNGLBEGINQUERYINDEXEDPROC beginQueryIndexed; + PFNGLBINDTRANSFORMFEEDBACKPROC bindTransformFeedback; + PFNGLBLENDEQUATIONSEPARATEIPROC blendEquationSeparatei; + PFNGLBLENDEQUATIONIPROC blendEquationi; + PFNGLBLENDFUNCSEPARATEIPROC blendFuncSeparatei; + PFNGLBLENDFUNCIPROC blendFunci; + PFNGLDELETETRANSFORMFEEDBACKSPROC deleteTransformFeedbacks; + PFNGLDRAWARRAYSINDIRECTPROC drawArraysIndirect; + PFNGLDRAWELEMENTSINDIRECTPROC drawElementsIndirect; + PFNGLDRAWTRANSFORMFEEDBACKPROC drawTransformFeedback; + PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC drawTransformFeedbackStream; + PFNGLENDQUERYINDEXEDPROC endQueryIndexed; + PFNGLGENTRANSFORMFEEDBACKSPROC genTransformFeedbacks; + PFNGLGETACTIVESUBROUTINENAMEPROC getActiveSubroutineName; + PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC getActiveSubroutineUniformName; + PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC getActiveSubroutineUniformiv; + PFNGLGETPROGRAMSTAGEIVPROC getProgramStageiv; + PFNGLGETQUERYINDEXEDIVPROC getQueryIndexediv; + PFNGLGETSUBROUTINEINDEXPROC getSubroutineIndex; + PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC getSubroutineUniformLocation; + PFNGLGETUNIFORMSUBROUTINEUIVPROC getUniformSubroutineuiv; + PFNGLGETUNIFORMDVPROC getUniformdv; + PFNGLISTRANSFORMFEEDBACKPROC isTransformFeedback; + PFNGLMINSAMPLESHADINGPROC minSampleShading; + PFNGLPATCHPARAMETERFVPROC patchParameterfv; + PFNGLPATCHPARAMETERIPROC patchParameteri; + PFNGLPAUSETRANSFORMFEEDBACKPROC pauseTransformFeedback; + PFNGLRESUMETRANSFORMFEEDBACKPROC resumeTransformFeedback; + PFNGLUNIFORM1DPROC uniform1d; + PFNGLUNIFORM1DVPROC uniform1dv; + PFNGLUNIFORM2DPROC uniform2d; + PFNGLUNIFORM2DVPROC uniform2dv; + PFNGLUNIFORM3DPROC uniform3d; + PFNGLUNIFORM3DVPROC uniform3dv; + PFNGLUNIFORM4DPROC uniform4d; + PFNGLUNIFORM4DVPROC uniform4dv; + PFNGLUNIFORMMATRIX2DVPROC uniformMatrix2dv; + PFNGLUNIFORMMATRIX2X3DVPROC uniformMatrix2x3dv; + PFNGLUNIFORMMATRIX2X4DVPROC uniformMatrix2x4dv; + PFNGLUNIFORMMATRIX3DVPROC uniformMatrix3dv; + PFNGLUNIFORMMATRIX3X2DVPROC uniformMatrix3x2dv; + PFNGLUNIFORMMATRIX3X4DVPROC uniformMatrix3x4dv; + PFNGLUNIFORMMATRIX4DVPROC uniformMatrix4dv; + PFNGLUNIFORMMATRIX4X2DVPROC uniformMatrix4x2dv; + PFNGLUNIFORMMATRIX4X3DVPROC uniformMatrix4x3dv; + PFNGLUNIFORMSUBROUTINESUIVPROC uniformSubroutinesuiv; + + // 4.1 + PFNGLACTIVESHADERPROGRAMPROC activeShaderProgram; + PFNGLBINDPROGRAMPIPELINEPROC bindProgramPipeline; + PFNGLCLEARDEPTHFPROC clearDepthf; + PFNGLCREATESHADERPROGRAMVPROC createShaderProgramv; + PFNGLDELETEPROGRAMPIPELINESPROC deleteProgramPipelines; + PFNGLDEPTHRANGEARRAYVPROC depthRangeArrayv; + PFNGLDEPTHRANGEINDEXEDPROC depthRangeIndexed; + PFNGLDEPTHRANGEFPROC depthRangef; + PFNGLGENPROGRAMPIPELINESPROC genProgramPipelines; + PFNGLGETDOUBLEI_VPROC getDoublei_v; + PFNGLGETFLOATI_VPROC getFloati_v; + PFNGLGETPROGRAMBINARYPROC getProgramBinary; + PFNGLGETPROGRAMPIPELINEINFOLOGPROC getProgramPipelineInfoLog; + PFNGLGETPROGRAMPIPELINEIVPROC getProgramPipelineiv; + PFNGLGETSHADERPRECISIONFORMATPROC getShaderPrecisionFormat; + PFNGLGETVERTEXATTRIBLDVPROC getVertexAttribLdv; + PFNGLISPROGRAMPIPELINEPROC isProgramPipeline; + PFNGLPROGRAMBINARYPROC programBinary; + PFNGLPROGRAMPARAMETERIPROC programParameteri; + PFNGLPROGRAMUNIFORM1DPROC programUniform1d; + PFNGLPROGRAMUNIFORM1DVPROC programUniform1dv; + PFNGLPROGRAMUNIFORM1FPROC programUniform1f; + PFNGLPROGRAMUNIFORM1FVPROC programUniform1fv; + PFNGLPROGRAMUNIFORM1IPROC programUniform1i; + PFNGLPROGRAMUNIFORM1IVPROC programUniform1iv; + PFNGLPROGRAMUNIFORM1UIPROC programUniform1ui; + PFNGLPROGRAMUNIFORM1UIVPROC programUniform1uiv; + PFNGLPROGRAMUNIFORM2DPROC programUniform2d; + PFNGLPROGRAMUNIFORM2DVPROC programUniform2dv; + PFNGLPROGRAMUNIFORM2FPROC programUniform2f; + PFNGLPROGRAMUNIFORM2FVPROC programUniform2fv; + PFNGLPROGRAMUNIFORM2IPROC programUniform2i; + PFNGLPROGRAMUNIFORM2IVPROC programUniform2iv; + PFNGLPROGRAMUNIFORM2UIPROC programUniform2ui; + PFNGLPROGRAMUNIFORM2UIVPROC programUniform2uiv; + PFNGLPROGRAMUNIFORM3DPROC programUniform3d; + PFNGLPROGRAMUNIFORM3DVPROC programUniform3dv; + PFNGLPROGRAMUNIFORM3FPROC programUniform3f; + PFNGLPROGRAMUNIFORM3FVPROC programUniform3fv; + PFNGLPROGRAMUNIFORM3IPROC programUniform3i; + PFNGLPROGRAMUNIFORM3IVPROC programUniform3iv; + PFNGLPROGRAMUNIFORM3UIPROC programUniform3ui; + PFNGLPROGRAMUNIFORM3UIVPROC programUniform3uiv; + PFNGLPROGRAMUNIFORM4DPROC programUniform4d; + PFNGLPROGRAMUNIFORM4DVPROC programUniform4dv; + PFNGLPROGRAMUNIFORM4FPROC programUniform4f; + PFNGLPROGRAMUNIFORM4FVPROC programUniform4fv; + PFNGLPROGRAMUNIFORM4IPROC programUniform4i; + PFNGLPROGRAMUNIFORM4IVPROC programUniform4iv; + PFNGLPROGRAMUNIFORM4UIPROC programUniform4ui; + PFNGLPROGRAMUNIFORM4UIVPROC programUniform4uiv; + PFNGLPROGRAMUNIFORMMATRIX2DVPROC programUniformMatrix2dv; + PFNGLPROGRAMUNIFORMMATRIX2FVPROC programUniformMatrix2fv; + PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC programUniformMatrix2x3dv; + PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC programUniformMatrix2x3fv; + PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC programUniformMatrix2x4dv; + PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC programUniformMatrix2x4fv; + PFNGLPROGRAMUNIFORMMATRIX3DVPROC programUniformMatrix3dv; + PFNGLPROGRAMUNIFORMMATRIX3FVPROC programUniformMatrix3fv; + PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC programUniformMatrix3x2dv; + PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC programUniformMatrix3x2fv; + PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC programUniformMatrix3x4dv; + PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC programUniformMatrix3x4fv; + PFNGLPROGRAMUNIFORMMATRIX4DVPROC programUniformMatrix4dv; + PFNGLPROGRAMUNIFORMMATRIX4FVPROC programUniformMatrix4fv; + PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC programUniformMatrix4x2dv; + PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC programUniformMatrix4x2fv; + PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC programUniformMatrix4x3dv; + PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC programUniformMatrix4x3fv; + PFNGLRELEASESHADERCOMPILERPROC releaseShaderCompiler; + PFNGLSCISSORARRAYVPROC scissorArrayv; + PFNGLSCISSORINDEXEDPROC scissorIndexed; + PFNGLSCISSORINDEXEDVPROC scissorIndexedv; + PFNGLSHADERBINARYPROC shaderBinary; + PFNGLUSEPROGRAMSTAGESPROC useProgramStages; + PFNGLVALIDATEPROGRAMPIPELINEPROC validateProgramPipeline; + PFNGLVERTEXATTRIBL1DPROC vertexAttribL1d; + PFNGLVERTEXATTRIBL1DVPROC vertexAttribL1dv; + PFNGLVERTEXATTRIBL2DPROC vertexAttribL2d; + PFNGLVERTEXATTRIBL2DVPROC vertexAttribL2dv; + PFNGLVERTEXATTRIBL3DPROC vertexAttribL3d; + PFNGLVERTEXATTRIBL3DVPROC vertexAttribL3dv; + PFNGLVERTEXATTRIBL4DPROC vertexAttribL4d; + PFNGLVERTEXATTRIBL4DVPROC vertexAttribL4dv; + PFNGLVERTEXATTRIBLPOINTERPROC vertexAttribLPointer; + PFNGLVIEWPORTARRAYVPROC viewportArrayv; + PFNGLVIEWPORTINDEXEDFPROC viewportIndexedf; + PFNGLVIEWPORTINDEXEDFVPROC viewportIndexedfv; + + // 4.2 + PFNGLBINDIMAGETEXTUREPROC bindImageTexture; + PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC drawArraysInstancedBaseInstance; + PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC drawElementsInstancedBaseInstance; + PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC drawElementsInstancedBaseVertexBaseInstance; + PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC drawTransformFeedbackInstanced; + PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC drawTransformFeedbackStreamInstanced; + PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC getActiveAtomicCounterBufferiv; + PFNGLGETINTERNALFORMATIVPROC getInternalformativ; + PFNGLMEMORYBARRIERPROC memoryBarrier; + PFNGLTEXSTORAGE1DPROC texStorage1D; + PFNGLTEXSTORAGE2DPROC texStorage2D; + PFNGLTEXSTORAGE3DPROC texStorage3D; + + // 4.3 + PFNGLBINDVERTEXBUFFERPROC bindVertexBuffer; + PFNGLCLEARBUFFERDATAPROC clearBufferData; + PFNGLCLEARBUFFERSUBDATAPROC clearBufferSubData; + PFNGLCOPYIMAGESUBDATAPROC copyImageSubData; + PFNGLDEBUGMESSAGECALLBACKPROC debugMessageCallback; + PFNGLDEBUGMESSAGECONTROLPROC debugMessageControl; + PFNGLDEBUGMESSAGEINSERTPROC debugMessageInsert; + PFNGLDISPATCHCOMPUTEPROC dispatchCompute; + PFNGLDISPATCHCOMPUTEINDIRECTPROC dispatchComputeIndirect; + PFNGLFRAMEBUFFERPARAMETERIPROC framebufferParameteri; + PFNGLGETDEBUGMESSAGELOGPROC getDebugMessageLog; + PFNGLGETFRAMEBUFFERPARAMETERIVPROC getFramebufferParameteriv; + PFNGLGETINTERNALFORMATI64VPROC getInternalformati64v; + PFNGLGETPOINTERVPROC getPointerv; + PFNGLGETOBJECTLABELPROC getObjectLabel; + PFNGLGETOBJECTPTRLABELPROC getObjectPtrLabel; + PFNGLGETPROGRAMINTERFACEIVPROC getProgramInterfaceiv; + PFNGLGETPROGRAMRESOURCEINDEXPROC getProgramResourceIndex; + PFNGLGETPROGRAMRESOURCELOCATIONPROC getProgramResourceLocation; + PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC getProgramResourceLocationIndex; + PFNGLGETPROGRAMRESOURCENAMEPROC getProgramResourceName; + PFNGLGETPROGRAMRESOURCEIVPROC getProgramResourceiv; + PFNGLINVALIDATEBUFFERDATAPROC invalidateBufferData; + PFNGLINVALIDATEBUFFERSUBDATAPROC invalidateBufferSubData; + PFNGLINVALIDATEFRAMEBUFFERPROC invalidateFramebuffer; + PFNGLINVALIDATESUBFRAMEBUFFERPROC invalidateSubFramebuffer; + PFNGLINVALIDATETEXIMAGEPROC invalidateTexImage; + PFNGLINVALIDATETEXSUBIMAGEPROC invalidateTexSubImage; + PFNGLMULTIDRAWARRAYSINDIRECTPROC multiDrawArraysIndirect; + PFNGLMULTIDRAWELEMENTSINDIRECTPROC multiDrawElementsIndirect; + PFNGLOBJECTLABELPROC objectLabel; + PFNGLOBJECTPTRLABELPROC objectPtrLabel; + PFNGLPOPDEBUGGROUPPROC popDebugGroup; + PFNGLPUSHDEBUGGROUPPROC pushDebugGroup; + PFNGLSHADERSTORAGEBLOCKBINDINGPROC shaderStorageBlockBinding; + PFNGLTEXBUFFERRANGEPROC texBufferRange; + PFNGLTEXSTORAGE2DMULTISAMPLEPROC texStorage2DMultisample; + PFNGLTEXSTORAGE3DMULTISAMPLEPROC texStorage3DMultisample; + PFNGLTEXTUREVIEWPROC textureView; + PFNGLVERTEXATTRIBBINDINGPROC vertexAttribBinding; + PFNGLVERTEXATTRIBFORMATPROC vertexAttribFormat; + PFNGLVERTEXATTRIBIFORMATPROC vertexAttribIFormat; + PFNGLVERTEXATTRIBLFORMATPROC vertexAttribLFormat; + PFNGLVERTEXBINDINGDIVISORPROC vertexBindingDivisor; + PFNGLCOVERAGEMODULATIONNVPROC coverageModulationNV; + + // 4.4 + PFNGLBINDBUFFERSBASEPROC bindBuffersBase; + PFNGLBINDBUFFERSRANGEPROC bindBuffersRange; + PFNGLBINDIMAGETEXTURESPROC bindImageTextures; + PFNGLBINDSAMPLERSPROC bindSamplers; + PFNGLBINDTEXTURESPROC bindTextures; + PFNGLBINDVERTEXBUFFERSPROC bindVertexBuffers; + PFNGLBUFFERSTORAGEPROC bufferStorage; + PFNGLCLEARTEXIMAGEPROC clearTexImage; + PFNGLCLEARTEXSUBIMAGEPROC clearTexSubImage; + + // 4.5 + PFNGLBINDTEXTUREUNITPROC bindTextureUnit; + PFNGLBLITNAMEDFRAMEBUFFERPROC blitNamedFramebuffer; + PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC checkNamedFramebufferStatus; + PFNGLCLEARNAMEDBUFFERDATAPROC clearNamedBufferData; + PFNGLCLEARNAMEDBUFFERSUBDATAPROC clearNamedBufferSubData; + PFNGLCLEARNAMEDFRAMEBUFFERFIPROC clearNamedFramebufferfi; + PFNGLCLEARNAMEDFRAMEBUFFERFVPROC clearNamedFramebufferfv; + PFNGLCLEARNAMEDFRAMEBUFFERIVPROC clearNamedFramebufferiv; + PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC clearNamedFramebufferuiv; + PFNGLCLIPCONTROLPROC clipControl; + PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC compressedTextureSubImage1D; + PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC compressedTextureSubImage2D; + PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC compressedTextureSubImage3D; + PFNGLCOPYNAMEDBUFFERSUBDATAPROC copyNamedBufferSubData; + PFNGLCOPYTEXTURESUBIMAGE1DPROC copyTextureSubImage1D; + PFNGLCOPYTEXTURESUBIMAGE2DPROC copyTextureSubImage2D; + PFNGLCOPYTEXTURESUBIMAGE3DPROC copyTextureSubImage3D; + PFNGLCREATEBUFFERSPROC createBuffers; + PFNGLCREATEFRAMEBUFFERSPROC createFramebuffers; + PFNGLCREATEPROGRAMPIPELINESPROC createProgramPipelines; + PFNGLCREATEQUERIESPROC createQueries; + PFNGLCREATERENDERBUFFERSPROC createRenderbuffers; + PFNGLCREATESAMPLERSPROC createSamplers; + PFNGLCREATETEXTURESPROC createTextures; + PFNGLCREATETRANSFORMFEEDBACKSPROC createTransformFeedbacks; + PFNGLCREATEVERTEXARRAYSPROC createVertexArrays; + PFNGLDISABLEVERTEXARRAYATTRIBPROC disableVertexArrayAttrib; + PFNGLENABLEVERTEXARRAYATTRIBPROC enableVertexArrayAttrib; + PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC flushMappedNamedBufferRange; + PFNGLGENERATETEXTUREMIPMAPPROC generateTextureMipmap; + PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC getCompressedTextureImage; + PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC getCompressedTextureSubImage; + PFNGLGETGRAPHICSRESETSTATUSPROC getGraphicsResetStatus; + PFNGLGETNAMEDBUFFERPARAMETERI64VPROC getNamedBufferParameteri64v; + PFNGLGETNAMEDBUFFERPARAMETERIVPROC getNamedBufferParameteriv; + PFNGLGETNAMEDBUFFERPOINTERVPROC getNamedBufferPointerv; + PFNGLGETNAMEDBUFFERSUBDATAPROC getNamedBufferSubData; + PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC getNamedFramebufferAttachmentParameteriv; + PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC getNamedFramebufferParameteriv; + PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC getNamedRenderbufferParameteriv; + PFNGLGETQUERYBUFFEROBJECTI64VPROC getQueryBufferObjecti64v; + PFNGLGETQUERYBUFFEROBJECTIVPROC getQueryBufferObjectiv; + PFNGLGETQUERYBUFFEROBJECTUI64VPROC getQueryBufferObjectui64v; + PFNGLGETQUERYBUFFEROBJECTUIVPROC getQueryBufferObjectuiv; + PFNGLGETTEXTUREIMAGEPROC getTextureImage; + PFNGLGETTEXTURELEVELPARAMETERFVPROC getTextureLevelParameterfv; + PFNGLGETTEXTURELEVELPARAMETERIVPROC getTextureLevelParameteriv; + PFNGLGETTEXTUREPARAMETERIIVPROC getTextureParameterIiv; + PFNGLGETTEXTUREPARAMETERIUIVPROC getTextureParameterIuiv; + PFNGLGETTEXTUREPARAMETERFVPROC getTextureParameterfv; + PFNGLGETTEXTUREPARAMETERIVPROC getTextureParameteriv; + PFNGLGETTEXTURESUBIMAGEPROC getTextureSubImage; + PFNGLGETTRANSFORMFEEDBACKI64_VPROC getTransformFeedbacki64_v; + PFNGLGETTRANSFORMFEEDBACKI_VPROC getTransformFeedbacki_v; + PFNGLGETTRANSFORMFEEDBACKIVPROC getTransformFeedbackiv; + PFNGLGETVERTEXARRAYINDEXED64IVPROC getVertexArrayIndexed64iv; + PFNGLGETVERTEXARRAYINDEXEDIVPROC getVertexArrayIndexediv; + PFNGLGETVERTEXARRAYIVPROC getVertexArrayiv; + PFNGLGETNCOMPRESSEDTEXIMAGEPROC getnCompressedTexImage; + PFNGLGETNTEXIMAGEPROC getnTexImage; + PFNGLGETNUNIFORMDVPROC getnUniformdv; + PFNGLGETNUNIFORMFVPROC getnUniformfv; + PFNGLGETNUNIFORMIVPROC getnUniformiv; + PFNGLGETNUNIFORMUIVPROC getnUniformuiv; + PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC invalidateNamedFramebufferData; + PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC invalidateNamedFramebufferSubData; + PFNGLMAPNAMEDBUFFERPROC mapNamedBuffer; + PFNGLMAPNAMEDBUFFERRANGEPROC mapNamedBufferRange; + PFNGLMEMORYBARRIERBYREGIONPROC memoryBarrierByRegion; + PFNGLNAMEDBUFFERDATAPROC namedBufferData; + PFNGLNAMEDBUFFERSTORAGEPROC namedBufferStorage; + PFNGLNAMEDBUFFERSUBDATAPROC namedBufferSubData; + PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC namedFramebufferDrawBuffer; + PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC namedFramebufferDrawBuffers; + PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC namedFramebufferParameteri; + PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC namedFramebufferReadBuffer; + PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC namedFramebufferRenderbuffer; + PFNGLNAMEDFRAMEBUFFERTEXTUREPROC namedFramebufferTexture; + PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC namedFramebufferTextureLayer; + PFNGLNAMEDRENDERBUFFERSTORAGEPROC namedRenderbufferStorage; + PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC namedRenderbufferStorageMultisample; + PFNGLREADNPIXELSPROC readnPixels; + PFNGLTEXTUREBARRIERPROC textureBarrier; + PFNGLTEXTUREBUFFERPROC textureBuffer; + PFNGLTEXTUREBUFFERRANGEPROC textureBufferRange; + PFNGLTEXTUREPARAMETERIIVPROC textureParameterIiv; + PFNGLTEXTUREPARAMETERIUIVPROC textureParameterIuiv; + PFNGLTEXTUREPARAMETERFPROC textureParameterf; + PFNGLTEXTUREPARAMETERFVPROC textureParameterfv; + PFNGLTEXTUREPARAMETERIPROC textureParameteri; + PFNGLTEXTUREPARAMETERIVPROC textureParameteriv; + PFNGLTEXTURESTORAGE1DPROC textureStorage1D; + PFNGLTEXTURESTORAGE2DPROC textureStorage2D; + PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC textureStorage2DMultisample; + PFNGLTEXTURESTORAGE3DPROC textureStorage3D; + PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC textureStorage3DMultisample; + PFNGLTEXTURESUBIMAGE1DPROC textureSubImage1D; + PFNGLTEXTURESUBIMAGE2DPROC textureSubImage2D; + PFNGLTEXTURESUBIMAGE3DPROC textureSubImage3D; + PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC transformFeedbackBufferBase; + PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC transformFeedbackBufferRange; + PFNGLUNMAPNAMEDBUFFERPROC unmapNamedBuffer; + PFNGLVERTEXARRAYATTRIBBINDINGPROC vertexArrayAttribBinding; + PFNGLVERTEXARRAYATTRIBFORMATPROC vertexArrayAttribFormat; + PFNGLVERTEXARRAYATTRIBIFORMATPROC vertexArrayAttribIFormat; + PFNGLVERTEXARRAYATTRIBLFORMATPROC vertexArrayAttribLFormat; + PFNGLVERTEXARRAYBINDINGDIVISORPROC vertexArrayBindingDivisor; + PFNGLVERTEXARRAYELEMENTBUFFERPROC vertexArrayElementBuffer; + PFNGLVERTEXARRAYVERTEXBUFFERPROC vertexArrayVertexBuffer; + PFNGLVERTEXARRAYVERTEXBUFFERSPROC vertexArrayVertexBuffers; + + // ES 3.2 + PFNGLBLENDBARRIERPROC blendBarrier; + PFNGLPRIMITIVEBOUNDINGBOXPROC primitiveBoundingBox; + + // ES extensions + PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC eglImageTargetRenderbufferStorageOES; + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC eglImageTargetTexture2DOES; + + private: + void initializeProcsDesktopGL(); + void initializeProcsGLES(); + + virtual void *loadProcAddress(const std::string &function) = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_FUNCTIONSGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/PathGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/PathGL.cpp new file mode 100755 index 000000000..a859bd759 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/PathGL.cpp @@ -0,0 +1,38 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// PathGL.cpp: Implementation for PathGL class. + +#include "libANGLE/renderer/gl/PathGL.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" + +namespace rx +{ + +PathGL::PathGL(const FunctionsGL *functions, GLuint path) : mFunctions(functions), mPathID(path) +{ +} + +PathGL::~PathGL() +{ +} + +gl::Error PathGL::setCommands(GLsizei numCommands, + const GLubyte *commands, + GLsizei numCoords, + GLenum coordType, + const void *coords) +{ + mFunctions->pathCommandsNV(mPathID, numCommands, commands, numCoords, coordType, coords); + return gl::Error(GL_NO_ERROR); +} + +void PathGL::setPathParameter(GLenum pname, GLfloat value) +{ + mFunctions->setPathParameterfNV(mPathID, pname, value); +} + +} // rx
\ No newline at end of file diff --git a/gfx/angle/src/libANGLE/renderer/gl/PathGL.h b/gfx/angle/src/libANGLE/renderer/gl/PathGL.h new file mode 100755 index 000000000..461d39aec --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/PathGL.h @@ -0,0 +1,44 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// PathGL.h: Class definition for CHROMIUM_path_rendering path object for the +// GL backend. + +#ifndef LIBANGLE_RENDERER_GL_PATHIMPL_H_ +#define LIBANGLE_RENDERER_GL_PATHIMPL_H_ + +#include "libANGLE/renderer/PathImpl.h" + +namespace rx +{ + +class FunctionsGL; + +class PathGL : public PathImpl +{ + public: + PathGL(const FunctionsGL *functions, GLuint path); + ~PathGL(); + + gl::Error setCommands(GLsizei numCommands, + const GLubyte *commands, + GLsizei numCoords, + GLenum coordType, + const void *coords) override; + + void setPathParameter(GLenum pname, GLfloat value) override; + + GLuint getPathID() const { return mPathID; } + + private: + const FunctionsGL *mFunctions; + + GLuint mPathID; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_GL_PATHIMPL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/ProgramGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/ProgramGL.cpp new file mode 100755 index 000000000..88c7df720 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/ProgramGL.cpp @@ -0,0 +1,588 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ProgramGL.cpp: Implements the class methods for ProgramGL. + +#include "libANGLE/renderer/gl/ProgramGL.h" + +#include "common/angleutils.h" +#include "common/debug.h" +#include "common/string_utils.h" +#include "common/utilities.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/ShaderGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" +#include "libANGLE/renderer/gl/WorkaroundsGL.h" +#include "libANGLE/Uniform.h" +#include "platform/Platform.h" + +namespace rx +{ + +ProgramGL::ProgramGL(const gl::ProgramState &data, + const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + StateManagerGL *stateManager, + bool enablePathRendering) + : ProgramImpl(data), + mFunctions(functions), + mWorkarounds(workarounds), + mStateManager(stateManager), + mEnablePathRendering(enablePathRendering), + mProgramID(0) +{ + ASSERT(mFunctions); + ASSERT(mStateManager); + + mProgramID = mFunctions->createProgram(); +} + +ProgramGL::~ProgramGL() +{ + mFunctions->deleteProgram(mProgramID); + mProgramID = 0; +} + +LinkResult ProgramGL::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) +{ + preLink(); + + // Read the binary format, size and blob + GLenum binaryFormat = stream->readInt<GLenum>(); + GLint binaryLength = stream->readInt<GLint>(); + const uint8_t *binary = stream->data() + stream->offset(); + stream->skip(binaryLength); + + // Load the binary + mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength); + + // Verify that the program linked + if (!checkLinkStatus(infoLog)) + { + return false; + } + + postLink(); + + return true; +} + +gl::Error ProgramGL::save(gl::BinaryOutputStream *stream) +{ + GLint binaryLength = 0; + mFunctions->getProgramiv(mProgramID, GL_PROGRAM_BINARY_LENGTH, &binaryLength); + + std::vector<uint8_t> binary(binaryLength); + GLenum binaryFormat = GL_NONE; + mFunctions->getProgramBinary(mProgramID, binaryLength, &binaryLength, &binaryFormat, + &binary[0]); + + stream->writeInt(binaryFormat); + stream->writeInt(binaryLength); + stream->writeBytes(&binary[0], binaryLength); + + return gl::Error(GL_NO_ERROR); +} + +void ProgramGL::setBinaryRetrievableHint(bool retrievable) +{ + // glProgramParameteri isn't always available on ES backends. + if (mFunctions->programParameteri) + { + mFunctions->programParameteri(mProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, + retrievable ? GL_TRUE : GL_FALSE); + } +} + +LinkResult ProgramGL::link(const gl::ContextState &data, gl::InfoLog &infoLog) +{ + preLink(); + + if (mState.getAttachedComputeShader()) + { + const ShaderGL *computeShaderGL = GetImplAs<ShaderGL>(mState.getAttachedComputeShader()); + + mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID()); + + // Link and verify + mFunctions->linkProgram(mProgramID); + + // Detach the shaders + mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID()); + } + else + { + // Set the transform feedback state + std::vector<const GLchar *> transformFeedbackVaryings; + for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames()) + { + transformFeedbackVaryings.push_back(tfVarying.c_str()); + } + + if (transformFeedbackVaryings.empty()) + { + if (mFunctions->transformFeedbackVaryings) + { + mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr, + mState.getTransformFeedbackBufferMode()); + } + } + else + { + ASSERT(mFunctions->transformFeedbackVaryings); + mFunctions->transformFeedbackVaryings( + mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()), + &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode()); + } + + const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mState.getAttachedVertexShader()); + const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader()); + + // Attach the shaders + mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID()); + mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID()); + + // Bind attribute locations to match the GL layer. + for (const sh::Attribute &attribute : mState.getAttributes()) + { + if (!attribute.staticUse) + { + continue; + } + + mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.name.c_str()); + } + + // Link and verify + mFunctions->linkProgram(mProgramID); + + // Detach the shaders + mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID()); + mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID()); + } + + // Verify the link + if (!checkLinkStatus(infoLog)) + { + return false; + } + + if (mWorkarounds.alwaysCallUseProgramAfterLink) + { + mStateManager->forceUseProgram(mProgramID); + } + + postLink(); + + return true; +} + +GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/) +{ + // TODO(jmadill): implement validate + return true; +} + +void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniform1fv(uniLoc(location), count, v); +} + +void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniform2fv(uniLoc(location), count, v); +} + +void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniform3fv(uniLoc(location), count, v); +} + +void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniform4fv(uniLoc(location), count, v); +} + +void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniform1iv(uniLoc(location), count, v); + + const gl::VariableLocation &locationEntry = mState.getUniformLocations()[location]; + + size_t samplerIndex = mUniformIndexToSamplerIndex[locationEntry.index]; + if (samplerIndex != GL_INVALID_INDEX) + { + std::vector<GLuint> &boundTextureUnits = mSamplerBindings[samplerIndex].boundTextureUnits; + + size_t copyCount = + std::min<size_t>(count, boundTextureUnits.size() - locationEntry.element); + std::copy(v, v + copyCount, boundTextureUnits.begin() + locationEntry.element); + } +} + +void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniform2iv(uniLoc(location), count, v); +} + +void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniform3iv(uniLoc(location), count, v); +} + +void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniform4iv(uniLoc(location), count, v); +} + +void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniform1uiv(uniLoc(location), count, v); +} + +void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniform2uiv(uniLoc(location), count, v); +} + +void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniform3uiv(uniLoc(location), count, v); +} + +void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniform4uiv(uniLoc(location), count, v); +} + +void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value); +} + +void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value); +} + +void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value); +} + +void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value); +} + +void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value); +} + +void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value); +} + +void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value); +} + +void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value); +} + +void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + mStateManager->useProgram(mProgramID); + mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value); +} + +void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) +{ + // Lazy init + if (mUniformBlockRealLocationMap.empty()) + { + mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size()); + for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks()) + { + const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex(); + GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str()); + mUniformBlockRealLocationMap.push_back(blockIndex); + } + } + + GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex]; + if (realBlockIndex != GL_INVALID_INDEX) + { + mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding); + } +} + +GLuint ProgramGL::getProgramID() const +{ + return mProgramID; +} + +const std::vector<SamplerBindingGL> &ProgramGL::getAppliedSamplerUniforms() const +{ + return mSamplerBindings; +} + +bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const +{ + ASSERT(mProgramID != 0u); + + GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str()); + if (blockIndex == GL_INVALID_INDEX) + { + *sizeOut = 0; + return false; + } + + GLint dataSize = 0; + mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, + &dataSize); + *sizeOut = static_cast<size_t>(dataSize); + return true; +} + +bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName, + sh::BlockMemberInfo *memberInfoOut) const +{ + GLuint uniformIndex; + const GLchar *memberNameGLStr = memberUniformName.c_str(); + mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex); + + if (uniformIndex == GL_INVALID_INDEX) + { + *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo(); + return false; + } + + mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET, + &memberInfoOut->offset); + mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE, + &memberInfoOut->arrayStride); + mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE, + &memberInfoOut->matrixStride); + + // TODO(jmadill): possibly determine this at the gl::Program level. + GLint isRowMajorMatrix = 0; + mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR, + &isRowMajorMatrix); + memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE; + return true; +} + +void ProgramGL::setPathFragmentInputGen(const std::string &inputName, + GLenum genMode, + GLint components, + const GLfloat *coeffs) +{ + ASSERT(mEnablePathRendering); + + for (const auto &input : mPathRenderingFragmentInputs) + { + if (input.name == inputName) + { + mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode, + components, coeffs); + ASSERT(mFunctions->getError() == GL_NO_ERROR); + return; + } + } + +} + +void ProgramGL::preLink() +{ + // Reset the program state + mUniformRealLocationMap.clear(); + mUniformBlockRealLocationMap.clear(); + mSamplerBindings.clear(); + mUniformIndexToSamplerIndex.clear(); + mPathRenderingFragmentInputs.clear(); +} + +bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog) +{ + GLint linkStatus = GL_FALSE; + mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus); + if (linkStatus == GL_FALSE) + { + // Linking failed, put the error into the info log + GLint infoLogLength = 0; + mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength); + + std::string warning; + + // Info log length includes the null terminator, so 1 means that the info log is an empty + // string. + if (infoLogLength > 1) + { + std::vector<char> buf(infoLogLength); + mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]); + + mFunctions->deleteProgram(mProgramID); + mProgramID = 0; + + infoLog << buf.data(); + + warning = FormatString("Program link failed unexpectedly: %s", buf.data()); + } + else + { + warning = "Program link failed unexpectedly with no info log."; + } + ANGLEPlatformCurrent()->logWarning(warning.c_str()); + TRACE("\n%s", warning.c_str()); + + // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case + return false; + } + + return true; +} + +void ProgramGL::postLink() +{ + // Query the uniform information + ASSERT(mUniformRealLocationMap.empty()); + const auto &uniformLocations = mState.getUniformLocations(); + const auto &uniforms = mState.getUniforms(); + mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX); + for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++) + { + const auto &entry = uniformLocations[uniformLocation]; + if (!entry.used) + { + continue; + } + + // From the spec: + // "Locations for sequential array indices are not required to be sequential." + const gl::LinkedUniform &uniform = uniforms[entry.index]; + std::stringstream fullNameStr; + fullNameStr << uniform.name; + if (uniform.isArray()) + { + fullNameStr << "[" << entry.element << "]"; + } + const std::string &fullName = fullNameStr.str(); + + GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str()); + mUniformRealLocationMap[uniformLocation] = realLocation; + } + + mUniformIndexToSamplerIndex.resize(mState.getUniforms().size(), GL_INVALID_INDEX); + + for (size_t uniformId = 0; uniformId < uniforms.size(); ++uniformId) + { + const gl::LinkedUniform &linkedUniform = uniforms[uniformId]; + + if (!linkedUniform.isSampler() || !linkedUniform.staticUse) + continue; + + mUniformIndexToSamplerIndex[uniformId] = mSamplerBindings.size(); + + // If uniform is a sampler type, insert it into the mSamplerBindings array + SamplerBindingGL samplerBinding; + samplerBinding.textureType = gl::SamplerTypeToTextureType(linkedUniform.type); + samplerBinding.boundTextureUnits.resize(linkedUniform.elementCount(), 0); + mSamplerBindings.push_back(samplerBinding); + } + + // Discover CHROMIUM_path_rendering fragment inputs if enabled. + if (!mEnablePathRendering) + return; + + GLint numFragmentInputs = 0; + mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES, + &numFragmentInputs); + if (numFragmentInputs <= 0) + return; + + GLint maxNameLength = 0; + mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH, + &maxNameLength); + ASSERT(maxNameLength); + + for (GLint i = 0; i < numFragmentInputs; ++i) + { + std::string name; + name.resize(maxNameLength); + + GLsizei nameLen = 0; + mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength, + &nameLen, &name[0]); + name.resize(nameLen); + + // Ignore built-ins + if (angle::BeginsWith(name, "gl_")) + continue; + + const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE}; + GLint queryResults[ArraySize(kQueryProperties)]; + GLsizei queryLength = 0; + + mFunctions->getProgramResourceiv( + mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)), + kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength, + queryResults); + + ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties))); + + PathRenderingFragmentInput baseElementInput; + baseElementInput.name = name; + baseElementInput.location = queryResults[0]; + mPathRenderingFragmentInputs.push_back(std::move(baseElementInput)); + + // If the input is an array it's denoted by [0] suffix on the variable + // name. We'll then create an entry per each array index where index > 0 + if (angle::EndsWith(name, "[0]")) + { + // drop the suffix + name.resize(name.size() - 3); + + const auto arraySize = queryResults[1]; + const auto baseLocation = queryResults[0]; + + for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex) + { + PathRenderingFragmentInput arrayElementInput; + arrayElementInput.name = name + "[" + ToString(arrayIndex) + "]"; + arrayElementInput.location = baseLocation + arrayIndex; + mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput)); + } + } + } +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/ProgramGL.h b/gfx/angle/src/libANGLE/renderer/gl/ProgramGL.h new file mode 100755 index 000000000..88e2245fa --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/ProgramGL.h @@ -0,0 +1,118 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ProgramGL.h: Defines the class interface for ProgramGL. + +#ifndef LIBANGLE_RENDERER_GL_PROGRAMGL_H_ +#define LIBANGLE_RENDERER_GL_PROGRAMGL_H_ + +#include <string> +#include <vector> + +#include "libANGLE/renderer/gl/WorkaroundsGL.h" +#include "libANGLE/renderer/ProgramImpl.h" + +namespace rx +{ + +class FunctionsGL; +class StateManagerGL; + +struct SamplerBindingGL +{ + GLenum textureType; + std::vector<GLuint> boundTextureUnits; +}; + +class ProgramGL : public ProgramImpl +{ + public: + ProgramGL(const gl::ProgramState &data, + const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + StateManagerGL *stateManager, + bool enablePathRendering); + ~ProgramGL() override; + + LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override; + gl::Error save(gl::BinaryOutputStream *stream) override; + void setBinaryRetrievableHint(bool retrievable) override; + + LinkResult link(const gl::ContextState &data, gl::InfoLog &infoLog) override; + GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override; + + void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override; + void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) override; + void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) override; + void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) override; + void setUniform1iv(GLint location, GLsizei count, const GLint *v) override; + void setUniform2iv(GLint location, GLsizei count, const GLint *v) override; + void setUniform3iv(GLint location, GLsizei count, const GLint *v) override; + void setUniform4iv(GLint location, GLsizei count, const GLint *v) override; + void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) override; + void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) override; + void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) override; + void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) override; + void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override; + void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override; + void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override; + void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override; + void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override; + void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override; + void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override; + void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override; + void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override; + + void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override; + + bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override; + bool getUniformBlockMemberInfo(const std::string &memberUniformName, + sh::BlockMemberInfo *memberInfoOut) const override; + + void setPathFragmentInputGen(const std::string &inputName, + GLenum genMode, + GLint components, + const GLfloat *coeffs) override; + + GLuint getProgramID() const; + const std::vector<SamplerBindingGL> &getAppliedSamplerUniforms() const; + + private: + void preLink(); + bool checkLinkStatus(gl::InfoLog &infoLog); + void postLink(); + + // Helper function, makes it simpler to type. + GLint uniLoc(GLint glLocation) const { return mUniformRealLocationMap[glLocation]; } + + const FunctionsGL *mFunctions; + const WorkaroundsGL &mWorkarounds; + StateManagerGL *mStateManager; + + std::vector<GLint> mUniformRealLocationMap; + std::vector<GLuint> mUniformBlockRealLocationMap; + + // An array of the samplers that are used by the program + std::vector<SamplerBindingGL> mSamplerBindings; + + // A map from a mData.getUniforms() index to a mSamplerBindings index. + std::vector<size_t> mUniformIndexToSamplerIndex; + + struct PathRenderingFragmentInput + { + std::string name; + GLint location; + }; + std::vector<PathRenderingFragmentInput> mPathRenderingFragmentInputs; + + bool mEnablePathRendering; + + GLuint mProgramID; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_PROGRAMGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/QueryGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/QueryGL.cpp new file mode 100755 index 000000000..6d9df5d76 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/QueryGL.cpp @@ -0,0 +1,222 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// QueryGL.cpp: Implements the class methods for QueryGL. + +#include "libANGLE/renderer/gl/QueryGL.h" + +#include "common/debug.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" + +namespace +{ + +GLuint64 MergeQueryResults(GLenum type, GLuint64 currentResult, GLuint64 newResult) +{ + switch (type) + { + case GL_ANY_SAMPLES_PASSED: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: + return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE; + + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + return currentResult + newResult; + + case GL_TIME_ELAPSED: + return currentResult + newResult; + + case GL_TIMESTAMP: + return newResult; + + default: + UNREACHABLE(); + return 0; + } +} + +} // anonymous namespace + +namespace rx +{ + +QueryGL::QueryGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager) + : QueryImpl(type), + mType(type), + mFunctions(functions), + mStateManager(stateManager), + mActiveQuery(0), + mPendingQueries(), + mResultSum(0) +{ +} + +QueryGL::~QueryGL() +{ + mStateManager->deleteQuery(mActiveQuery); + mStateManager->onDeleteQueryObject(this); + while (!mPendingQueries.empty()) + { + mStateManager->deleteQuery(mPendingQueries.front()); + mPendingQueries.pop_front(); + } +} + +gl::Error QueryGL::begin() +{ + mResultSum = 0; + mStateManager->onBeginQuery(this); + return resume(); +} + +gl::Error QueryGL::end() +{ + return pause(); +} + +gl::Error QueryGL::queryCounter() +{ + ASSERT(mType == GL_TIMESTAMP); + + // Directly create a query for the timestamp and add it to the pending query queue, as timestamp + // queries do not have the traditional begin/end block and never need to be paused/resumed + GLuint query; + mFunctions->genQueries(1, &query); + mFunctions->queryCounter(query, GL_TIMESTAMP); + mPendingQueries.push_back(query); + + return gl::Error(GL_NO_ERROR); +} + +template <typename T> +gl::Error QueryGL::getResultBase(T *params) +{ + ASSERT(mActiveQuery == 0); + + gl::Error error = flush(true); + if (error.isError()) + { + return error; + } + + ASSERT(mPendingQueries.empty()); + *params = static_cast<T>(mResultSum); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error QueryGL::getResult(GLint *params) +{ + return getResultBase(params); +} + +gl::Error QueryGL::getResult(GLuint *params) +{ + return getResultBase(params); +} + +gl::Error QueryGL::getResult(GLint64 *params) +{ + return getResultBase(params); +} + +gl::Error QueryGL::getResult(GLuint64 *params) +{ + return getResultBase(params); +} + +gl::Error QueryGL::isResultAvailable(bool *available) +{ + ASSERT(mActiveQuery == 0); + + gl::Error error = flush(false); + if (error.isError()) + { + return error; + } + + *available = mPendingQueries.empty(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error QueryGL::pause() +{ + if (mActiveQuery != 0) + { + mStateManager->endQuery(mType, mActiveQuery); + + mPendingQueries.push_back(mActiveQuery); + mActiveQuery = 0; + } + + // Flush to make sure the pending queries don't add up too much. + gl::Error error = flush(false); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error QueryGL::resume() +{ + if (mActiveQuery == 0) + { + // Flush to make sure the pending queries don't add up too much. + gl::Error error = flush(false); + if (error.isError()) + { + return error; + } + + mFunctions->genQueries(1, &mActiveQuery); + mStateManager->beginQuery(mType, mActiveQuery); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error QueryGL::flush(bool force) +{ + while (!mPendingQueries.empty()) + { + GLuint id = mPendingQueries.front(); + if (!force) + { + GLuint resultAvailable = 0; + mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT_AVAILABLE, &resultAvailable); + if (resultAvailable == GL_FALSE) + { + return gl::Error(GL_NO_ERROR); + } + } + + // Even though getQueryObjectui64v was introduced for timer queries, there is nothing in the + // standard that says that it doesn't work for any other queries. It also passes on all the + // trybots, so we use it if it is available + if (mFunctions->getQueryObjectui64v != nullptr) + { + GLuint64 result = 0; + mFunctions->getQueryObjectui64v(id, GL_QUERY_RESULT, &result); + mResultSum = MergeQueryResults(mType, mResultSum, result); + } + else + { + GLuint result = 0; + mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT, &result); + mResultSum = MergeQueryResults(mType, mResultSum, static_cast<GLuint64>(result)); + } + + mStateManager->deleteQuery(id); + + mPendingQueries.pop_front(); + } + + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/QueryGL.h b/gfx/angle/src/libANGLE/renderer/gl/QueryGL.h new file mode 100755 index 000000000..5e280b1f7 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/QueryGL.h @@ -0,0 +1,64 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// QueryGL.h: Defines the class interface for QueryGL. + +#ifndef LIBANGLE_RENDERER_GL_QUERYGL_H_ +#define LIBANGLE_RENDERER_GL_QUERYGL_H_ + +#include <deque> + +#include "libANGLE/renderer/QueryImpl.h" + +namespace rx +{ + +class FunctionsGL; +class StateManagerGL; + +class QueryGL : public QueryImpl +{ + public: + QueryGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager); + ~QueryGL() override; + + gl::Error begin() override; + gl::Error end() override; + gl::Error queryCounter() override; + gl::Error getResult(GLint *params) override; + gl::Error getResult(GLuint *params) override; + gl::Error getResult(GLint64 *params) override; + gl::Error getResult(GLuint64 *params) override; + gl::Error isResultAvailable(bool *available) override; + + // OpenGL is only allowed to have one query of each type active at any given time. Since ANGLE + // virtualizes contexts, queries need to be able to be paused and resumed. + // A query is "paused" by ending it and pushing the ID into a list of queries awaiting readback. + // When it is "resumed", a new query is generated and started. + // When a result is required, the queries are "flushed" by iterating over the list of pending + // queries and merging their results. + gl::Error pause(); + gl::Error resume(); + + private: + gl::Error flush(bool force); + + template <typename T> + gl::Error getResultBase(T *params); + + GLenum mType; + + const FunctionsGL *mFunctions; + StateManagerGL *mStateManager; + + GLuint mActiveQuery; + std::deque<GLuint> mPendingQueries; + GLuint64 mResultSum; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_QUERYGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/RenderbufferGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/RenderbufferGL.cpp new file mode 100755 index 000000000..bfc2bb254 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/RenderbufferGL.cpp @@ -0,0 +1,96 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderbufferGL.cpp: Implements the class methods for RenderbufferGL. + +#include "libANGLE/renderer/gl/RenderbufferGL.h" + +#include "common/debug.h" +#include "libANGLE/Caps.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" +#include "libANGLE/renderer/gl/formatutilsgl.h" +#include "libANGLE/renderer/gl/renderergl_utils.h" + +namespace rx +{ +RenderbufferGL::RenderbufferGL(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + StateManagerGL *stateManager, + const gl::TextureCapsMap &textureCaps) + : RenderbufferImpl(), + mFunctions(functions), + mWorkarounds(workarounds), + mStateManager(stateManager), + mTextureCaps(textureCaps), + mRenderbufferID(0) +{ + mFunctions->genRenderbuffers(1, &mRenderbufferID); + mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID); +} + +RenderbufferGL::~RenderbufferGL() +{ + mStateManager->deleteRenderbuffer(mRenderbufferID); + mRenderbufferID = 0; +} + +gl::Error RenderbufferGL::setStorage(GLenum internalformat, size_t width, size_t height) +{ + mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID); + + nativegl::RenderbufferFormat renderbufferFormat = + nativegl::GetRenderbufferFormat(mFunctions, mWorkarounds, internalformat); + mFunctions->renderbufferStorage(GL_RENDERBUFFER, renderbufferFormat.internalFormat, + static_cast<GLsizei>(width), static_cast<GLsizei>(height)); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RenderbufferGL::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) +{ + mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID); + + nativegl::RenderbufferFormat renderbufferFormat = + nativegl::GetRenderbufferFormat(mFunctions, mWorkarounds, internalformat); + mFunctions->renderbufferStorageMultisample( + GL_RENDERBUFFER, static_cast<GLsizei>(samples), renderbufferFormat.internalFormat, + static_cast<GLsizei>(width), static_cast<GLsizei>(height)); + + const gl::TextureCaps &formatCaps = mTextureCaps.get(internalformat); + if (samples > formatCaps.getMaxSamples()) + { + // Before version 4.2, it is unknown if the specific internal format can support the requested number + // of samples. It is expected that GL_OUT_OF_MEMORY is returned if the renderbuffer cannot be created. + GLenum error = GL_NO_ERROR; + do + { + error = mFunctions->getError(); + if (error == GL_OUT_OF_MEMORY) + { + return gl::Error(GL_OUT_OF_MEMORY); + } + + ASSERT(error == GL_NO_ERROR); + } while (error != GL_NO_ERROR); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RenderbufferGL::setStorageEGLImageTarget(egl::Image *image) +{ + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION); +} + +GLuint RenderbufferGL::getRenderbufferID() const +{ + return mRenderbufferID; +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/RenderbufferGL.h b/gfx/angle/src/libANGLE/renderer/gl/RenderbufferGL.h new file mode 100755 index 000000000..0ff0faeae --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/RenderbufferGL.h @@ -0,0 +1,52 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderbufferGL.h: Defines the class interface for RenderbufferGL. + +#ifndef LIBANGLE_RENDERER_GL_RENDERBUFFERGL_H_ +#define LIBANGLE_RENDERER_GL_RENDERBUFFERGL_H_ + +#include "libANGLE/renderer/RenderbufferImpl.h" + +namespace gl +{ +class TextureCapsMap; +} + +namespace rx +{ + +class FunctionsGL; +class StateManagerGL; +struct WorkaroundsGL; + +class RenderbufferGL : public RenderbufferImpl +{ + public: + RenderbufferGL(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + StateManagerGL *stateManager, + const gl::TextureCapsMap &textureCaps); + ~RenderbufferGL() override; + + virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override; + virtual gl::Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) override; + virtual gl::Error setStorageEGLImageTarget(egl::Image *image) override; + + GLuint getRenderbufferID() const; + + private: + const FunctionsGL *mFunctions; + const WorkaroundsGL &mWorkarounds; + StateManagerGL *mStateManager; + const gl::TextureCapsMap &mTextureCaps; + + GLuint mRenderbufferID; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_RENDERBUFFERGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/RendererGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/RendererGL.cpp new file mode 100755 index 000000000..da1a65687 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/RendererGL.cpp @@ -0,0 +1,561 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RendererGL.cpp: Implements the class methods for RendererGL. + +#include "libANGLE/renderer/gl/RendererGL.h" + +#include <EGL/eglext.h> + +#include "common/debug.h" +#include "libANGLE/AttributeMap.h" +#include "libANGLE/ContextState.h" +#include "libANGLE/Path.h" +#include "libANGLE/Surface.h" +#include "libANGLE/renderer/gl/BlitGL.h" +#include "libANGLE/renderer/gl/BufferGL.h" +#include "libANGLE/renderer/gl/CompilerGL.h" +#include "libANGLE/renderer/gl/ContextGL.h" +#include "libANGLE/renderer/gl/FenceNVGL.h" +#include "libANGLE/renderer/gl/FenceSyncGL.h" +#include "libANGLE/renderer/gl/FramebufferGL.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/PathGL.h" +#include "libANGLE/renderer/gl/ProgramGL.h" +#include "libANGLE/renderer/gl/QueryGL.h" +#include "libANGLE/renderer/gl/RenderbufferGL.h" +#include "libANGLE/renderer/gl/SamplerGL.h" +#include "libANGLE/renderer/gl/ShaderGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" +#include "libANGLE/renderer/gl/SurfaceGL.h" +#include "libANGLE/renderer/gl/TextureGL.h" +#include "libANGLE/renderer/gl/TransformFeedbackGL.h" +#include "libANGLE/renderer/gl/VertexArrayGL.h" +#include "libANGLE/renderer/gl/renderergl_utils.h" + +namespace +{ + +std::vector<GLuint> GatherPaths(const std::vector<gl::Path *> &paths) +{ + std::vector<GLuint> ret; + ret.reserve(paths.size()); + + for (const auto *p : paths) + { + const auto *pathObj = rx::GetImplAs<rx::PathGL>(p); + ret.push_back(pathObj->getPathID()); + } + return ret; +} + +} // namespace + +#ifndef NDEBUG +static void INTERNAL_GL_APIENTRY LogGLDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, + const GLchar *message, const void *userParam) +{ + std::string sourceText; + switch (source) + { + case GL_DEBUG_SOURCE_API: sourceText = "OpenGL"; break; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: sourceText = "Windows"; break; + case GL_DEBUG_SOURCE_SHADER_COMPILER: sourceText = "Shader Compiler"; break; + case GL_DEBUG_SOURCE_THIRD_PARTY: sourceText = "Third Party"; break; + case GL_DEBUG_SOURCE_APPLICATION: sourceText = "Application"; break; + case GL_DEBUG_SOURCE_OTHER: sourceText = "Other"; break; + default: sourceText = "UNKNOWN"; break; + } + + std::string typeText; + switch (type) + { + case GL_DEBUG_TYPE_ERROR: typeText = "Error"; break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: typeText = "Deprecated behavior"; break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: typeText = "Undefined behavior"; break; + case GL_DEBUG_TYPE_PORTABILITY: typeText = "Portability"; break; + case GL_DEBUG_TYPE_PERFORMANCE: typeText = "Performance"; break; + case GL_DEBUG_TYPE_OTHER: typeText = "Other"; break; + case GL_DEBUG_TYPE_MARKER: typeText = "Marker"; break; + default: typeText = "UNKNOWN"; break; + } + + std::string severityText; + switch (severity) + { + case GL_DEBUG_SEVERITY_HIGH: severityText = "High"; break; + case GL_DEBUG_SEVERITY_MEDIUM: severityText = "Medium"; break; + case GL_DEBUG_SEVERITY_LOW: severityText = "Low"; break; + case GL_DEBUG_SEVERITY_NOTIFICATION: severityText = "Notification"; break; + default: severityText = "UNKNOWN"; break; + } + + ERR("\n\tSource: %s\n\tType: %s\n\tID: %d\n\tSeverity: %s\n\tMessage: %s", sourceText.c_str(), typeText.c_str(), id, + severityText.c_str(), message); +} +#endif + +namespace rx +{ + +RendererGL::RendererGL(const FunctionsGL *functions, const egl::AttributeMap &attribMap) + : mMaxSupportedESVersion(0, 0), + mFunctions(functions), + mStateManager(nullptr), + mBlitter(nullptr), + mHasDebugOutput(false), + mSkipDrawCalls(false), + mCapsInitialized(false) +{ + ASSERT(mFunctions); + mStateManager = new StateManagerGL(mFunctions, getNativeCaps()); + nativegl_gl::GenerateWorkarounds(mFunctions, &mWorkarounds); + mBlitter = new BlitGL(functions, mWorkarounds, mStateManager); + + mHasDebugOutput = mFunctions->isAtLeastGL(gl::Version(4, 3)) || + mFunctions->hasGLExtension("GL_KHR_debug") || + mFunctions->isAtLeastGLES(gl::Version(3, 2)) || + mFunctions->hasGLESExtension("GL_KHR_debug"); +#ifndef NDEBUG + if (mHasDebugOutput) + { + mFunctions->enable(GL_DEBUG_OUTPUT); + mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0, nullptr, GL_TRUE); + mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM, 0, nullptr, GL_TRUE); + mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW, 0, nullptr, GL_FALSE); + mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION, 0, nullptr, GL_FALSE); + mFunctions->debugMessageCallback(&LogGLDebugMessage, nullptr); + } +#endif + + EGLint deviceType = + static_cast<EGLint>(attribMap.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_NONE)); + if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE) + { + mSkipDrawCalls = true; + } + + if (mWorkarounds.initializeCurrentVertexAttributes) + { + GLint maxVertexAttribs = 0; + mFunctions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs); + + for (GLint i = 0; i < maxVertexAttribs; ++i) + { + mFunctions->vertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 1.0f); + } + } +} + +RendererGL::~RendererGL() +{ + SafeDelete(mBlitter); + SafeDelete(mStateManager); +} + +gl::Error RendererGL::flush() +{ + mFunctions->flush(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error RendererGL::finish() +{ +#ifdef NDEBUG + if (mWorkarounds.finishDoesNotCauseQueriesToBeAvailable && mHasDebugOutput) + { + mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + } +#endif + + mFunctions->finish(); + +#ifdef NDEBUG + if (mWorkarounds.finishDoesNotCauseQueriesToBeAvailable && mHasDebugOutput) + { + mFunctions->disable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + } +#endif + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RendererGL::drawArrays(const gl::ContextState &data, + GLenum mode, + GLint first, + GLsizei count) +{ + ANGLE_TRY(mStateManager->setDrawArraysState(data, first, count, 0)); + + if (!mSkipDrawCalls) + { + mFunctions->drawArrays(mode, first, count); + } + + return gl::NoError(); +} + +gl::Error RendererGL::drawArraysInstanced(const gl::ContextState &data, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount) +{ + ANGLE_TRY(mStateManager->setDrawArraysState(data, first, count, instanceCount)); + + if (!mSkipDrawCalls) + { + mFunctions->drawArraysInstanced(mode, first, count, instanceCount); + } + + return gl::NoError(); +} + +gl::Error RendererGL::drawElements(const gl::ContextState &data, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) +{ + const GLvoid *drawIndexPtr = nullptr; + ANGLE_TRY(mStateManager->setDrawElementsState(data, count, type, indices, 0, &drawIndexPtr)); + + if (!mSkipDrawCalls) + { + mFunctions->drawElements(mode, count, type, drawIndexPtr); + } + + return gl::NoError(); +} + +gl::Error RendererGL::drawElementsInstanced(const gl::ContextState &data, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange) +{ + const GLvoid *drawIndexPointer = nullptr; + ANGLE_TRY(mStateManager->setDrawElementsState(data, count, type, indices, instances, + &drawIndexPointer)); + + if (!mSkipDrawCalls) + { + mFunctions->drawElementsInstanced(mode, count, type, drawIndexPointer, instances); + } + + return gl::NoError(); +} + +gl::Error RendererGL::drawRangeElements(const gl::ContextState &data, + GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) +{ + const GLvoid *drawIndexPointer = nullptr; + ANGLE_TRY( + mStateManager->setDrawElementsState(data, count, type, indices, 0, &drawIndexPointer)); + + if (!mSkipDrawCalls) + { + mFunctions->drawRangeElements(mode, start, end, count, type, drawIndexPointer); + } + + return gl::Error(GL_NO_ERROR); +} + +void RendererGL::stencilFillPath(const gl::ContextState &state, + const gl::Path *path, + GLenum fillMode, + GLuint mask) +{ + const auto *pathObj = GetImplAs<PathGL>(path); + + mFunctions->stencilFillPathNV(pathObj->getPathID(), fillMode, mask); + + ASSERT(mFunctions->getError() == GL_NO_ERROR); +} + +void RendererGL::stencilStrokePath(const gl::ContextState &state, + const gl::Path *path, + GLint reference, + GLuint mask) +{ + const auto *pathObj = GetImplAs<PathGL>(path); + + mFunctions->stencilStrokePathNV(pathObj->getPathID(), reference, mask); + + ASSERT(mFunctions->getError() == GL_NO_ERROR); +} + +void RendererGL::coverFillPath(const gl::ContextState &state, + const gl::Path *path, + GLenum coverMode) +{ + + const auto *pathObj = GetImplAs<PathGL>(path); + mFunctions->coverFillPathNV(pathObj->getPathID(), coverMode); + + ASSERT(mFunctions->getError() == GL_NO_ERROR); +} + +void RendererGL::coverStrokePath(const gl::ContextState &state, + const gl::Path *path, + GLenum coverMode) +{ + const auto *pathObj = GetImplAs<PathGL>(path); + mFunctions->coverStrokePathNV(pathObj->getPathID(), coverMode); + + ASSERT(mFunctions->getError() == GL_NO_ERROR); +} + +void RendererGL::stencilThenCoverFillPath(const gl::ContextState &state, + const gl::Path *path, + GLenum fillMode, + GLuint mask, + GLenum coverMode) +{ + + const auto *pathObj = GetImplAs<PathGL>(path); + mFunctions->stencilThenCoverFillPathNV(pathObj->getPathID(), fillMode, mask, coverMode); + + ASSERT(mFunctions->getError() == GL_NO_ERROR); +} + +void RendererGL::stencilThenCoverStrokePath(const gl::ContextState &state, + const gl::Path *path, + GLint reference, + GLuint mask, + GLenum coverMode) +{ + + const auto *pathObj = GetImplAs<PathGL>(path); + mFunctions->stencilThenCoverStrokePathNV(pathObj->getPathID(), reference, mask, coverMode); + + ASSERT(mFunctions->getError() == GL_NO_ERROR); +} + +void RendererGL::coverFillPathInstanced(const gl::ContextState &state, + const std::vector<gl::Path *> &paths, + GLenum coverMode, + GLenum transformType, + const GLfloat *transformValues) +{ + const auto &pathObjs = GatherPaths(paths); + + mFunctions->coverFillPathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT, + &pathObjs[0], 0, coverMode, transformType, + transformValues); + + ASSERT(mFunctions->getError() == GL_NO_ERROR); +} +void RendererGL::coverStrokePathInstanced(const gl::ContextState &state, + const std::vector<gl::Path *> &paths, + GLenum coverMode, + GLenum transformType, + const GLfloat *transformValues) +{ + const auto &pathObjs = GatherPaths(paths); + + mFunctions->coverStrokePathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT, + &pathObjs[0], 0, coverMode, transformType, + transformValues); + + ASSERT(mFunctions->getError() == GL_NO_ERROR); +} +void RendererGL::stencilFillPathInstanced(const gl::ContextState &state, + const std::vector<gl::Path *> &paths, + GLenum fillMode, + GLuint mask, + GLenum transformType, + const GLfloat *transformValues) +{ + const auto &pathObjs = GatherPaths(paths); + + mFunctions->stencilFillPathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT, + &pathObjs[0], 0, fillMode, mask, transformType, + transformValues); + + ASSERT(mFunctions->getError() == GL_NO_ERROR); +} +void RendererGL::stencilStrokePathInstanced(const gl::ContextState &state, + const std::vector<gl::Path *> &paths, + GLint reference, + GLuint mask, + GLenum transformType, + const GLfloat *transformValues) +{ + const auto &pathObjs = GatherPaths(paths); + + mFunctions->stencilStrokePathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT, + &pathObjs[0], 0, reference, mask, transformType, + transformValues); + + ASSERT(mFunctions->getError() == GL_NO_ERROR); +} + +void RendererGL::stencilThenCoverFillPathInstanced(const gl::ContextState &state, + const std::vector<gl::Path *> &paths, + GLenum coverMode, + GLenum fillMode, + GLuint mask, + GLenum transformType, + const GLfloat *transformValues) +{ + const auto &pathObjs = GatherPaths(paths); + + mFunctions->stencilThenCoverFillPathInstancedNV( + static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT, &pathObjs[0], 0, fillMode, mask, + coverMode, transformType, transformValues); + + ASSERT(mFunctions->getError() == GL_NO_ERROR); +} +void RendererGL::stencilThenCoverStrokePathInstanced(const gl::ContextState &state, + const std::vector<gl::Path *> &paths, + GLenum coverMode, + GLint reference, + GLuint mask, + GLenum transformType, + const GLfloat *transformValues) +{ + const auto &pathObjs = GatherPaths(paths); + + mFunctions->stencilThenCoverStrokePathInstancedNV( + static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT, &pathObjs[0], 0, reference, mask, + coverMode, transformType, transformValues); + + ASSERT(mFunctions->getError() == GL_NO_ERROR); +} + +GLenum RendererGL::getResetStatus() +{ + return mFunctions->getGraphicsResetStatus(); +} + +ContextImpl *RendererGL::createContext(const gl::ContextState &state) +{ + return new ContextGL(state, this); +} + +void RendererGL::insertEventMarker(GLsizei length, const char *marker) +{ + mFunctions->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0, + GL_DEBUG_SEVERITY_NOTIFICATION, length, marker); +} + +void RendererGL::pushGroupMarker(GLsizei length, const char *marker) +{ + mFunctions->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, length, marker); +} + +void RendererGL::popGroupMarker() +{ + mFunctions->popDebugGroup(); +} + +std::string RendererGL::getVendorString() const +{ + return std::string(reinterpret_cast<const char*>(mFunctions->getString(GL_VENDOR))); +} + +std::string RendererGL::getRendererDescription() const +{ + std::string nativeVendorString(reinterpret_cast<const char*>(mFunctions->getString(GL_VENDOR))); + std::string nativeRendererString(reinterpret_cast<const char*>(mFunctions->getString(GL_RENDERER))); + + std::ostringstream rendererString; + rendererString << nativeVendorString << " " << nativeRendererString << " OpenGL"; + if (mFunctions->standard == STANDARD_GL_ES) + { + rendererString << " ES"; + } + rendererString << " " << mFunctions->version.major << "." << mFunctions->version.minor; + if (mFunctions->standard == STANDARD_GL_DESKTOP) + { + // Some drivers (NVIDIA) use a profile mask of 0 when in compatibility profile. + if ((mFunctions->profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0 || + (mFunctions->isAtLeastGL(gl::Version(3, 2)) && mFunctions->profile == 0)) + { + rendererString << " compatibility"; + } + else if ((mFunctions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0) + { + rendererString << " core"; + } + } + + return rendererString.str(); +} + +const gl::Version &RendererGL::getMaxSupportedESVersion() const +{ + // Force generation of caps + getNativeCaps(); + + return mMaxSupportedESVersion; +} + +void RendererGL::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, + gl::Extensions *outExtensions, + gl::Limitations * /* outLimitations */) const +{ + nativegl_gl::GenerateCaps(mFunctions, outCaps, outTextureCaps, outExtensions, &mMaxSupportedESVersion); +} + +GLint RendererGL::getGPUDisjoint() +{ + // TODO(ewell): On GLES backends we should find a way to reliably query disjoint events + return 0; +} + +GLint64 RendererGL::getTimestamp() +{ + GLint64 result = 0; + mFunctions->getInteger64v(GL_TIMESTAMP, &result); + return result; +} + +void RendererGL::ensureCapsInitialized() const +{ + if (!mCapsInitialized) + { + generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations); + mCapsInitialized = true; + } +} + +const gl::Caps &RendererGL::getNativeCaps() const +{ + ensureCapsInitialized(); + return mNativeCaps; +} + +const gl::TextureCapsMap &RendererGL::getNativeTextureCaps() const +{ + ensureCapsInitialized(); + return mNativeTextureCaps; +} + +const gl::Extensions &RendererGL::getNativeExtensions() const +{ + ensureCapsInitialized(); + return mNativeExtensions; +} + +const gl::Limitations &RendererGL::getNativeLimitations() const +{ + ensureCapsInitialized(); + return mNativeLimitations; +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/RendererGL.h b/gfx/angle/src/libANGLE/renderer/gl/RendererGL.h new file mode 100755 index 000000000..71f012055 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/RendererGL.h @@ -0,0 +1,194 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RendererGL.h: Defines the class interface for RendererGL. + +#ifndef LIBANGLE_RENDERER_GL_RENDERERGL_H_ +#define LIBANGLE_RENDERER_GL_RENDERERGL_H_ + +#include "libANGLE/Caps.h" +#include "libANGLE/Error.h" +#include "libANGLE/Version.h" +#include "libANGLE/renderer/gl/WorkaroundsGL.h" + +namespace gl +{ +class ContextState; +struct IndexRange; +class Path; +} + +namespace egl +{ +class AttributeMap; +} + +namespace sh +{ +struct BlockMemberInfo; +} + +namespace rx +{ +class BlitGL; +class ContextImpl; +class FunctionsGL; +class StateManagerGL; + +class RendererGL : angle::NonCopyable +{ + public: + RendererGL(const FunctionsGL *functions, const egl::AttributeMap &attribMap); + ~RendererGL(); + + ContextImpl *createContext(const gl::ContextState &state); + + gl::Error flush(); + gl::Error finish(); + + gl::Error drawArrays(const gl::ContextState &data, GLenum mode, GLint first, GLsizei count); + gl::Error drawArraysInstanced(const gl::ContextState &data, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount); + + gl::Error drawElements(const gl::ContextState &data, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange); + gl::Error drawElementsInstanced(const gl::ContextState &data, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange); + gl::Error drawRangeElements(const gl::ContextState &data, + GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange); + + // CHROMIUM_path_rendering implementation + void stencilFillPath(const gl::ContextState &state, + const gl::Path *path, + GLenum fillMode, + GLuint mask); + void stencilStrokePath(const gl::ContextState &state, + const gl::Path *path, + GLint reference, + GLuint mask); + void coverFillPath(const gl::ContextState &state, const gl::Path *path, GLenum coverMode); + void coverStrokePath(const gl::ContextState &state, const gl::Path *path, GLenum coverMode); + void stencilThenCoverFillPath(const gl::ContextState &state, + const gl::Path *path, + GLenum fillMode, + GLuint mask, + GLenum coverMode); + void stencilThenCoverStrokePath(const gl::ContextState &state, + const gl::Path *path, + GLint reference, + GLuint mask, + GLenum coverMode); + void coverFillPathInstanced(const gl::ContextState &state, + const std::vector<gl::Path *> &paths, + GLenum coverMode, + GLenum transformType, + const GLfloat *transformValues); + void coverStrokePathInstanced(const gl::ContextState &state, + const std::vector<gl::Path *> &paths, + GLenum coverMode, + GLenum transformType, + const GLfloat *transformValues); + void stencilFillPathInstanced(const gl::ContextState &state, + const std::vector<gl::Path *> &paths, + GLenum fillMode, + GLuint mask, + GLenum transformType, + const GLfloat *transformValues); + void stencilStrokePathInstanced(const gl::ContextState &state, + const std::vector<gl::Path *> &paths, + GLint reference, + GLuint mask, + GLenum transformType, + const GLfloat *transformValues); + + void stencilThenCoverFillPathInstanced(const gl::ContextState &state, + const std::vector<gl::Path *> &paths, + GLenum coverMode, + GLenum fillMode, + GLuint mask, + GLenum transformType, + const GLfloat *transformValues); + void stencilThenCoverStrokePathInstanced(const gl::ContextState &state, + const std::vector<gl::Path *> &paths, + GLenum coverMode, + GLint reference, + GLuint mask, + GLenum transformType, + const GLfloat *transformValues); + + GLenum getResetStatus(); + + // EXT_debug_marker + void insertEventMarker(GLsizei length, const char *marker); + void pushGroupMarker(GLsizei length, const char *marker); + void popGroupMarker(); + + std::string getVendorString() const; + std::string getRendererDescription() const; + + GLint getGPUDisjoint(); + GLint64 getTimestamp(); + + const gl::Version &getMaxSupportedESVersion() const; + const FunctionsGL *getFunctions() const { return mFunctions; } + StateManagerGL *getStateManager() const { return mStateManager; } + const WorkaroundsGL &getWorkarounds() const { return mWorkarounds; } + BlitGL *getBlitter() const { return mBlitter; } + + const gl::Caps &getNativeCaps() const; + const gl::TextureCapsMap &getNativeTextureCaps() const; + const gl::Extensions &getNativeExtensions() const; + const gl::Limitations &getNativeLimitations() const; + + private: + void ensureCapsInitialized() const; + void generateCaps(gl::Caps *outCaps, + gl::TextureCapsMap *outTextureCaps, + gl::Extensions *outExtensions, + gl::Limitations *outLimitations) const; + + mutable gl::Version mMaxSupportedESVersion; + + const FunctionsGL *mFunctions; + StateManagerGL *mStateManager; + + BlitGL *mBlitter; + + WorkaroundsGL mWorkarounds; + + bool mHasDebugOutput; + + // For performance debugging + bool mSkipDrawCalls; + + mutable bool mCapsInitialized; + mutable gl::Caps mNativeCaps; + mutable gl::TextureCapsMap mNativeTextureCaps; + mutable gl::Extensions mNativeExtensions; + mutable gl::Limitations mNativeLimitations; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_GL_RENDERERGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/SamplerGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/SamplerGL.cpp new file mode 100755 index 000000000..2a6d81583 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/SamplerGL.cpp @@ -0,0 +1,73 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SamplerGL.cpp: Defines the rx::SamplerGL class, an implementation of SamplerImpl. + +#include "libANGLE/renderer/gl/SamplerGL.h" + +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" + +namespace +{ + +template <typename T> +static inline void SyncSamplerStateMember(const rx::FunctionsGL *functions, + GLuint sampler, + const gl::SamplerState &newState, + gl::SamplerState &curState, + GLenum name, + T(gl::SamplerState::*samplerMember)) +{ + if (curState.*samplerMember != newState.*samplerMember) + { + curState.*samplerMember = newState.*samplerMember; + functions->samplerParameterf(sampler, name, static_cast<GLfloat>(curState.*samplerMember)); + } +} +} + +namespace rx +{ + +SamplerGL::SamplerGL(const FunctionsGL *functions, StateManagerGL *stateManager) + : SamplerImpl(), + mFunctions(functions), + mStateManager(stateManager), + mAppliedSamplerState(), + mSamplerID(0) +{ + mFunctions->genSamplers(1, &mSamplerID); +} + +SamplerGL::~SamplerGL() +{ + mStateManager->deleteSampler(mSamplerID); + mSamplerID = 0; +} + +void SamplerGL::syncState(const gl::SamplerState &samplerState) const +{ + // clang-format off + SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MIN_FILTER, &gl::SamplerState::minFilter); + SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MAG_FILTER, &gl::SamplerState::magFilter); + SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_WRAP_S, &gl::SamplerState::wrapS); + SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_WRAP_T, &gl::SamplerState::wrapT); + SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_WRAP_R, &gl::SamplerState::wrapR); + SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MAX_ANISOTROPY_EXT, &gl::SamplerState::maxAnisotropy); + SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MIN_LOD, &gl::SamplerState::minLod); + SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MAX_LOD, &gl::SamplerState::maxLod); + SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_COMPARE_MODE, &gl::SamplerState::compareMode); + SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_COMPARE_FUNC, &gl::SamplerState::compareFunc); + SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_SRGB_DECODE_EXT, &gl::SamplerState::sRGBDecode); + // clang-format on +} + +GLuint SamplerGL::getSamplerID() const +{ + return mSamplerID; +} +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/SamplerGL.h b/gfx/angle/src/libANGLE/renderer/gl/SamplerGL.h new file mode 100755 index 000000000..c3fcfde80 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/SamplerGL.h @@ -0,0 +1,40 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SamplerGL.h: Defines the rx::SamplerGL class, an implementation of SamplerImpl. + +#ifndef LIBANGLE_RENDERER_GL_SAMPLERGL_H_ +#define LIBANGLE_RENDERER_GL_SAMPLERGL_H_ + +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/SamplerImpl.h" + +namespace rx +{ + +class FunctionsGL; +class StateManagerGL; + +class SamplerGL : public SamplerImpl +{ + public: + SamplerGL(const FunctionsGL *functions, StateManagerGL *stateManager); + ~SamplerGL() override; + + void syncState(const gl::SamplerState &samplerState) const; + + GLuint getSamplerID() const; + + private: + const FunctionsGL *mFunctions; + StateManagerGL *mStateManager; + + mutable gl::SamplerState mAppliedSamplerState; + GLuint mSamplerID; +}; +} + +#endif // LIBANGLE_RENDERER_GL_SAMPLERGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/ShaderGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/ShaderGL.cpp new file mode 100755 index 000000000..c9145b00a --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/ShaderGL.cpp @@ -0,0 +1,143 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderGL.cpp: Implements the class methods for ShaderGL. + +#include "libANGLE/renderer/gl/ShaderGL.h" + +#include "common/debug.h" +#include "libANGLE/Compiler.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/RendererGL.h" +#include "libANGLE/renderer/gl/WorkaroundsGL.h" + +#include <iostream> + +namespace rx +{ + +ShaderGL::ShaderGL(const gl::ShaderState &data, + const FunctionsGL *functions, + const WorkaroundsGL &workarounds) + : ShaderImpl(data), mFunctions(functions), mWorkarounds(workarounds), mShaderID(0) +{ + ASSERT(mFunctions); +} + +ShaderGL::~ShaderGL() +{ + if (mShaderID != 0) + { + mFunctions->deleteShader(mShaderID); + mShaderID = 0; + } +} + +ShCompileOptions ShaderGL::prepareSourceAndReturnOptions(std::stringstream *sourceStream, + std::string * /*sourcePath*/) +{ + // Reset the previous state + if (mShaderID != 0) + { + mFunctions->deleteShader(mShaderID); + mShaderID = 0; + } + + *sourceStream << mData.getSource(); + + ShCompileOptions options = SH_INIT_GL_POSITION; + + if (mWorkarounds.doWhileGLSLCausesGPUHang) + { + options |= SH_REWRITE_DO_WHILE_LOOPS; + } + + if (mWorkarounds.emulateAbsIntFunction) + { + options |= SH_EMULATE_ABS_INT_FUNCTION; + } + + if (mWorkarounds.addAndTrueToLoopCondition) + { + options |= SH_ADD_AND_TRUE_TO_LOOP_CONDITION; + } + + if (mWorkarounds.emulateIsnanFloat) + { + options |= SH_EMULATE_ISNAN_FLOAT_FUNCTION; + } + + if (mWorkarounds.useUnusedBlocksWithStandardOrSharedLayout) + { + options |= SH_USE_UNUSED_STANDARD_SHARED_BLOCKS; + } + + if (mWorkarounds.dontRemoveInvariantForFragmentInput) + { + options |= SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT; + } + + if (mWorkarounds.removeInvariantAndCentroidForESSL3) + { + options |= SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3; + } + + return options; +} + +bool ShaderGL::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) +{ + // Translate the ESSL into GLSL + const char *translatedSourceCString = mData.getTranslatedSource().c_str(); + + // Generate a shader object and set the source + mShaderID = mFunctions->createShader(mData.getShaderType()); + mFunctions->shaderSource(mShaderID, 1, &translatedSourceCString, nullptr); + mFunctions->compileShader(mShaderID); + + // Check for compile errors from the native driver + GLint compileStatus = GL_FALSE; + mFunctions->getShaderiv(mShaderID, GL_COMPILE_STATUS, &compileStatus); + if (compileStatus == GL_FALSE) + { + // Compilation failed, put the error into the info log + GLint infoLogLength = 0; + mFunctions->getShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLogLength); + + // Info log length includes the null terminator, so 1 means that the info log is an empty + // string. + if (infoLogLength > 1) + { + std::vector<char> buf(infoLogLength); + mFunctions->getShaderInfoLog(mShaderID, infoLogLength, nullptr, &buf[0]); + + mFunctions->deleteShader(mShaderID); + mShaderID = 0; + + *infoLog = &buf[0]; + TRACE("\n%s", infoLog->c_str()); + } + else + { + TRACE("\nShader compilation failed with no info log."); + } + return false; + } + + return true; +} + +std::string ShaderGL::getDebugInfo() const +{ + return std::string(); +} + +GLuint ShaderGL::getShaderID() const +{ + return mShaderID; +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/ShaderGL.h b/gfx/angle/src/libANGLE/renderer/gl/ShaderGL.h new file mode 100755 index 000000000..0ecd89ce6 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/ShaderGL.h @@ -0,0 +1,44 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderGL.h: Defines the class interface for ShaderGL. + +#ifndef LIBANGLE_RENDERER_GL_SHADERGL_H_ +#define LIBANGLE_RENDERER_GL_SHADERGL_H_ + +#include "libANGLE/renderer/ShaderImpl.h" + +namespace rx +{ +class FunctionsGL; +struct WorkaroundsGL; + +class ShaderGL : public ShaderImpl +{ + public: + ShaderGL(const gl::ShaderState &data, + const FunctionsGL *functions, + const WorkaroundsGL &workarounds); + ~ShaderGL() override; + + // ShaderImpl implementation + ShCompileOptions prepareSourceAndReturnOptions(std::stringstream *sourceStream, + std::string *sourcePath) override; + bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override; + std::string getDebugInfo() const override; + + GLuint getShaderID() const; + + private: + const FunctionsGL *mFunctions; + const WorkaroundsGL &mWorkarounds; + + GLuint mShaderID; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_SHADERGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp new file mode 100755 index 000000000..3a227906f --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp @@ -0,0 +1,1742 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// StateManagerGL.h: Defines a class for caching applied OpenGL state + +#include "libANGLE/renderer/gl/StateManagerGL.h" + +#include <limits> +#include <string.h> + +#include "common/BitSetIterator.h" +#include "common/mathutil.h" +#include "common/matrix_utils.h" +#include "libANGLE/ContextState.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/TransformFeedback.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/Query.h" +#include "libANGLE/renderer/gl/BufferGL.h" +#include "libANGLE/renderer/gl/FramebufferGL.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/ProgramGL.h" +#include "libANGLE/renderer/gl/SamplerGL.h" +#include "libANGLE/renderer/gl/TextureGL.h" +#include "libANGLE/renderer/gl/TransformFeedbackGL.h" +#include "libANGLE/renderer/gl/VertexArrayGL.h" +#include "libANGLE/renderer/gl/QueryGL.h" + +namespace rx +{ + +static const GLenum QueryTypes[] = {GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE, + GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_TIME_ELAPSED, + GL_COMMANDS_COMPLETED_CHROMIUM}; + +StateManagerGL::IndexedBufferBinding::IndexedBufferBinding() : offset(0), size(0), buffer(0) +{ +} + +StateManagerGL::StateManagerGL(const FunctionsGL *functions, const gl::Caps &rendererCaps) + : mFunctions(functions), + mProgram(0), + mVAO(0), + mVertexAttribCurrentValues(rendererCaps.maxVertexAttributes), + mBuffers(), + mIndexedBuffers(), + mTextureUnitIndex(0), + mTextures(), + mSamplers(rendererCaps.maxCombinedTextureImageUnits, 0), + mTransformFeedback(0), + mQueries(), + mPrevDrawTransformFeedback(nullptr), + mCurrentQueries(), + mPrevDrawContext(0), + mUnpackAlignment(4), + mUnpackRowLength(0), + mUnpackSkipRows(0), + mUnpackSkipPixels(0), + mUnpackImageHeight(0), + mUnpackSkipImages(0), + mPackAlignment(4), + mPackRowLength(0), + mPackSkipRows(0), + mPackSkipPixels(0), + mFramebuffers(angle::FramebufferBindingSingletonMax, 0), + mRenderbuffer(0), + mScissorTestEnabled(false), + mScissor(0, 0, 0, 0), + mViewport(0, 0, 0, 0), + mNear(0.0f), + mFar(1.0f), + mBlendEnabled(false), + mBlendColor(0, 0, 0, 0), + mSourceBlendRGB(GL_ONE), + mDestBlendRGB(GL_ZERO), + mSourceBlendAlpha(GL_ONE), + mDestBlendAlpha(GL_ZERO), + mBlendEquationRGB(GL_FUNC_ADD), + mBlendEquationAlpha(GL_FUNC_ADD), + mColorMaskRed(true), + mColorMaskGreen(true), + mColorMaskBlue(true), + mColorMaskAlpha(true), + mSampleAlphaToCoverageEnabled(false), + mSampleCoverageEnabled(false), + mSampleCoverageValue(1.0f), + mSampleCoverageInvert(false), + mDepthTestEnabled(false), + mDepthFunc(GL_LESS), + mDepthMask(true), + mStencilTestEnabled(false), + mStencilFrontFunc(GL_ALWAYS), + mStencilFrontRef(0), + mStencilFrontValueMask(static_cast<GLuint>(-1)), + mStencilFrontStencilFailOp(GL_KEEP), + mStencilFrontStencilPassDepthFailOp(GL_KEEP), + mStencilFrontStencilPassDepthPassOp(GL_KEEP), + mStencilFrontWritemask(static_cast<GLuint>(-1)), + mStencilBackFunc(GL_ALWAYS), + mStencilBackRef(0), + mStencilBackValueMask(static_cast<GLuint>(-1)), + mStencilBackStencilFailOp(GL_KEEP), + mStencilBackStencilPassDepthFailOp(GL_KEEP), + mStencilBackStencilPassDepthPassOp(GL_KEEP), + mStencilBackWritemask(static_cast<GLuint>(-1)), + mCullFaceEnabled(false), + mCullFace(GL_BACK), + mFrontFace(GL_CCW), + mPolygonOffsetFillEnabled(false), + mPolygonOffsetFactor(0.0f), + mPolygonOffsetUnits(0.0f), + mRasterizerDiscardEnabled(false), + mLineWidth(1.0f), + mPrimitiveRestartEnabled(false), + mClearColor(0.0f, 0.0f, 0.0f, 0.0f), + mClearDepth(1.0f), + mClearStencil(0), + mFramebufferSRGBEnabled(false), + mDitherEnabled(true), + mTextureCubemapSeamlessEnabled(false), + mMultisamplingEnabled(true), + mSampleAlphaToOneEnabled(false), + mCoverageModulation(GL_NONE), + mPathStencilFunc(GL_ALWAYS), + mPathStencilRef(0), + mPathStencilMask(std::numeric_limits<GLuint>::max()), + mLocalDirtyBits() +{ + ASSERT(mFunctions); + + mTextures[GL_TEXTURE_2D].resize(rendererCaps.maxCombinedTextureImageUnits); + mTextures[GL_TEXTURE_CUBE_MAP].resize(rendererCaps.maxCombinedTextureImageUnits); + mTextures[GL_TEXTURE_2D_ARRAY].resize(rendererCaps.maxCombinedTextureImageUnits); + mTextures[GL_TEXTURE_3D].resize(rendererCaps.maxCombinedTextureImageUnits); + + mIndexedBuffers[GL_UNIFORM_BUFFER].resize(rendererCaps.maxCombinedUniformBlocks); + + for (GLenum queryType : QueryTypes) + { + mQueries[queryType] = 0; + } + + // Initialize point sprite state for desktop GL + if (mFunctions->standard == STANDARD_GL_DESKTOP) + { + mFunctions->enable(GL_PROGRAM_POINT_SIZE); + + // GL_POINT_SPRITE was deprecated in the core profile. Point rasterization is always + // performed + // as though POINT_SPRITE were enabled. + if ((mFunctions->profile & GL_CONTEXT_CORE_PROFILE_BIT) == 0) + { + mFunctions->enable(GL_POINT_SPRITE); + } + } + + angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj); + angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV); +} + +void StateManagerGL::deleteProgram(GLuint program) +{ + if (program != 0) + { + if (mProgram == program) + { + useProgram(0); + } + + mFunctions->deleteProgram(program); + } +} + +void StateManagerGL::deleteVertexArray(GLuint vao) +{ + if (vao != 0) + { + if (mVAO == vao) + { + bindVertexArray(0, 0); + } + + mFunctions->deleteVertexArrays(1, &vao); + } +} + +void StateManagerGL::deleteTexture(GLuint texture) +{ + if (texture != 0) + { + for (const auto &textureTypeIter : mTextures) + { + const std::vector<GLuint> &textureVector = textureTypeIter.second; + for (size_t textureUnitIndex = 0; textureUnitIndex < textureVector.size(); textureUnitIndex++) + { + if (textureVector[textureUnitIndex] == texture) + { + activeTexture(textureUnitIndex); + bindTexture(textureTypeIter.first, 0); + } + } + } + + mFunctions->deleteTextures(1, &texture); + } +} + +void StateManagerGL::deleteSampler(GLuint sampler) +{ + if (sampler != 0) + { + for (size_t unit = 0; unit < mSamplers.size(); unit++) + { + if (mSamplers[unit] == sampler) + { + bindSampler(unit, 0); + } + } + + mFunctions->deleteSamplers(1, &sampler); + } +} + +void StateManagerGL::deleteBuffer(GLuint buffer) +{ + if (buffer != 0) + { + for (const auto &bufferTypeIter : mBuffers) + { + if (bufferTypeIter.second == buffer) + { + bindBuffer(bufferTypeIter.first, 0); + } + } + + for (const auto &bufferTypeIter : mIndexedBuffers) + { + for (size_t bindIndex = 0; bindIndex < bufferTypeIter.second.size(); bindIndex++) + { + if (bufferTypeIter.second[bindIndex].buffer == buffer) + { + bindBufferBase(bufferTypeIter.first, bindIndex, 0); + } + } + } + + mFunctions->deleteBuffers(1, &buffer); + } +} + +void StateManagerGL::deleteFramebuffer(GLuint fbo) +{ + if (fbo != 0) + { + for (size_t binding = 0; binding < mFramebuffers.size(); ++binding) + { + if (mFramebuffers[binding] == fbo) + { + GLenum enumValue = angle::FramebufferBindingToEnum( + static_cast<angle::FramebufferBinding>(binding)); + bindFramebuffer(enumValue, 0); + } + mFunctions->deleteFramebuffers(1, &fbo); + } + } +} + +void StateManagerGL::deleteRenderbuffer(GLuint rbo) +{ + if (rbo != 0) + { + if (mRenderbuffer == rbo) + { + bindRenderbuffer(GL_RENDERBUFFER, 0); + } + + mFunctions->deleteRenderbuffers(1, &rbo); + } +} + +void StateManagerGL::deleteTransformFeedback(GLuint transformFeedback) +{ + if (transformFeedback != 0) + { + if (mTransformFeedback == transformFeedback) + { + bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); + } + + if (mPrevDrawTransformFeedback != nullptr && + mPrevDrawTransformFeedback->getTransformFeedbackID() == transformFeedback) + { + mPrevDrawTransformFeedback = nullptr; + } + + mFunctions->deleteTransformFeedbacks(1, &transformFeedback); + } +} + +void StateManagerGL::deleteQuery(GLuint query) +{ + if (query != 0) + { + for (auto &activeQuery : mQueries) + { + GLuint activeQueryID = activeQuery.second; + if (activeQueryID == query) + { + GLenum type = activeQuery.first; + endQuery(type, query); + } + } + } +} + +void StateManagerGL::useProgram(GLuint program) +{ + if (mProgram != program) + { + forceUseProgram(program); + } +} + +void StateManagerGL::forceUseProgram(GLuint program) +{ + mProgram = program; + mFunctions->useProgram(mProgram); +} + +void StateManagerGL::bindVertexArray(GLuint vao, GLuint elementArrayBuffer) +{ + if (mVAO != vao) + { + mVAO = vao; + mBuffers[GL_ELEMENT_ARRAY_BUFFER] = elementArrayBuffer; + mFunctions->bindVertexArray(vao); + } +} + +void StateManagerGL::bindBuffer(GLenum type, GLuint buffer) +{ + if (mBuffers[type] != buffer) + { + mBuffers[type] = buffer; + mFunctions->bindBuffer(type, buffer); + } +} + +void StateManagerGL::bindBufferBase(GLenum type, size_t index, GLuint buffer) +{ + auto &binding = mIndexedBuffers[type][index]; + if (binding.buffer != buffer || binding.offset != static_cast<size_t>(-1) || + binding.size != static_cast<size_t>(-1)) + { + binding.buffer = buffer; + binding.offset = static_cast<size_t>(-1); + binding.size = static_cast<size_t>(-1); + mFunctions->bindBufferBase(type, static_cast<GLuint>(index), buffer); + } +} + +void StateManagerGL::bindBufferRange(GLenum type, + size_t index, + GLuint buffer, + size_t offset, + size_t size) +{ + auto &binding = mIndexedBuffers[type][index]; + if (binding.buffer != buffer || binding.offset != offset || binding.size != size) + { + binding.buffer = buffer; + binding.offset = offset; + binding.size = size; + mFunctions->bindBufferRange(type, static_cast<GLuint>(index), buffer, offset, size); + } +} + +void StateManagerGL::activeTexture(size_t unit) +{ + if (mTextureUnitIndex != unit) + { + mTextureUnitIndex = unit; + mFunctions->activeTexture(GL_TEXTURE0 + static_cast<GLenum>(mTextureUnitIndex)); + } +} + +void StateManagerGL::bindTexture(GLenum type, GLuint texture) +{ + if (mTextures[type][mTextureUnitIndex] != texture) + { + mTextures[type][mTextureUnitIndex] = texture; + mFunctions->bindTexture(type, texture); + } +} + +void StateManagerGL::bindSampler(size_t unit, GLuint sampler) +{ + if (mSamplers[unit] != sampler) + { + mSamplers[unit] = sampler; + mFunctions->bindSampler(static_cast<GLuint>(unit), sampler); + } +} + +void StateManagerGL::setPixelUnpackState(const gl::PixelUnpackState &unpack) +{ + GLuint unpackBufferID = 0; + const gl::Buffer *unpackBuffer = unpack.pixelBuffer.get(); + if (unpackBuffer != nullptr) + { + unpackBufferID = GetImplAs<BufferGL>(unpackBuffer)->getBufferID(); + } + setPixelUnpackState(unpack.alignment, unpack.rowLength, unpack.skipRows, unpack.skipPixels, + unpack.imageHeight, unpack.skipImages, unpackBufferID); +} + +void StateManagerGL::setPixelUnpackState(GLint alignment, + GLint rowLength, + GLint skipRows, + GLint skipPixels, + GLint imageHeight, + GLint skipImages, + GLuint unpackBuffer) +{ + if (mUnpackAlignment != alignment) + { + mUnpackAlignment = alignment; + mFunctions->pixelStorei(GL_UNPACK_ALIGNMENT, mUnpackAlignment); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_ALIGNMENT); + } + + if (mUnpackRowLength != rowLength) + { + mUnpackRowLength = rowLength; + mFunctions->pixelStorei(GL_UNPACK_ROW_LENGTH, mUnpackRowLength); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_ROW_LENGTH); + } + + if (mUnpackSkipRows != skipRows) + { + mUnpackSkipRows = skipRows; + mFunctions->pixelStorei(GL_UNPACK_SKIP_ROWS, mUnpackSkipRows); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_SKIP_ROWS); + } + + if (mUnpackSkipPixels != skipPixels) + { + mUnpackSkipPixels = skipPixels; + mFunctions->pixelStorei(GL_UNPACK_SKIP_PIXELS, mUnpackSkipPixels); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_SKIP_PIXELS); + } + + if (mUnpackImageHeight != imageHeight) + { + mUnpackImageHeight = imageHeight; + mFunctions->pixelStorei(GL_UNPACK_IMAGE_HEIGHT, mUnpackImageHeight); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_IMAGE_HEIGHT); + } + + if (mUnpackSkipImages != skipImages) + { + mUnpackSkipImages = skipImages; + mFunctions->pixelStorei(GL_UNPACK_SKIP_IMAGES, mUnpackSkipImages); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_SKIP_IMAGES); + } + + bindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer); +} + +void StateManagerGL::setPixelPackState(const gl::PixelPackState &pack) +{ + GLuint packBufferID = 0; + const gl::Buffer *packBuffer = pack.pixelBuffer.get(); + if (packBuffer != nullptr) + { + packBufferID = GetImplAs<BufferGL>(packBuffer)->getBufferID(); + } + setPixelPackState(pack.alignment, pack.rowLength, pack.skipRows, pack.skipPixels, packBufferID); +} + +void StateManagerGL::setPixelPackState(GLint alignment, + GLint rowLength, + GLint skipRows, + GLint skipPixels, + GLuint packBuffer) +{ + if (mPackAlignment != alignment) + { + mPackAlignment = alignment; + mFunctions->pixelStorei(GL_PACK_ALIGNMENT, mPackAlignment); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_ALIGNMENT); + } + + if (mPackRowLength != rowLength) + { + mPackRowLength = rowLength; + mFunctions->pixelStorei(GL_PACK_ROW_LENGTH, mPackRowLength); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_ROW_LENGTH); + } + + if (mPackSkipRows != skipRows) + { + mPackSkipRows = skipRows; + mFunctions->pixelStorei(GL_PACK_SKIP_ROWS, mPackSkipRows); + + // TODO: set dirty bit once one exists + } + + if (mPackSkipPixels != skipPixels) + { + mPackSkipPixels = skipPixels; + mFunctions->pixelStorei(GL_PACK_SKIP_PIXELS, mPackSkipPixels); + + // TODO: set dirty bit once one exists + } + + bindBuffer(GL_PIXEL_PACK_BUFFER, packBuffer); +} + +void StateManagerGL::bindFramebuffer(GLenum type, GLuint framebuffer) +{ + if (type == GL_FRAMEBUFFER) + { + if (mFramebuffers[angle::FramebufferBindingRead] != framebuffer || + mFramebuffers[angle::FramebufferBindingDraw] != framebuffer) + { + mFramebuffers[angle::FramebufferBindingRead] = framebuffer; + mFramebuffers[angle::FramebufferBindingDraw] = framebuffer; + mFunctions->bindFramebuffer(GL_FRAMEBUFFER, framebuffer); + } + } + else + { + angle::FramebufferBinding binding = angle::EnumToFramebufferBinding(type); + + if (mFramebuffers[binding] != framebuffer) + { + mFramebuffers[binding] = framebuffer; + mFunctions->bindFramebuffer(type, framebuffer); + } + } +} + +void StateManagerGL::bindRenderbuffer(GLenum type, GLuint renderbuffer) +{ + ASSERT(type == GL_RENDERBUFFER); + if (mRenderbuffer != renderbuffer) + { + mRenderbuffer = renderbuffer; + mFunctions->bindRenderbuffer(type, mRenderbuffer); + } +} + +void StateManagerGL::bindTransformFeedback(GLenum type, GLuint transformFeedback) +{ + ASSERT(type == GL_TRANSFORM_FEEDBACK); + if (mTransformFeedback != transformFeedback) + { + // Pause the current transform feedback if one is active. + // To handle virtualized contexts, StateManagerGL needs to be able to bind a new transform + // feedback at any time, even if there is one active. + if (mPrevDrawTransformFeedback != nullptr && + mPrevDrawTransformFeedback->getTransformFeedbackID() != transformFeedback) + { + mPrevDrawTransformFeedback->syncPausedState(true); + mPrevDrawTransformFeedback = nullptr; + } + + mTransformFeedback = transformFeedback; + mFunctions->bindTransformFeedback(type, mTransformFeedback); + } +} + +void StateManagerGL::beginQuery(GLenum type, GLuint query) +{ + // Make sure this is a valid query type and there is no current active query of this type + ASSERT(mQueries.find(type) != mQueries.end()); + ASSERT(mQueries[type] == 0); + ASSERT(query != 0); + + mQueries[type] = query; + mFunctions->beginQuery(type, query); +} + +void StateManagerGL::endQuery(GLenum type, GLuint query) +{ + ASSERT(mQueries[type] == query); + mQueries[type] = 0; + mFunctions->endQuery(type); +} + +void StateManagerGL::onBeginQuery(QueryGL *query) +{ + mCurrentQueries.insert(query); +} + +void StateManagerGL::onDeleteQueryObject(QueryGL *query) +{ + mCurrentQueries.erase(query); +} + +gl::Error StateManagerGL::setDrawArraysState(const gl::ContextState &data, + GLint first, + GLsizei count, + GLsizei instanceCount) +{ + const gl::State &state = data.getState(); + + const gl::Program *program = state.getProgram(); + + const gl::VertexArray *vao = state.getVertexArray(); + const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao); + + gl::Error error = vaoGL->syncDrawArraysState(program->getActiveAttribLocationsMask(), first, + count, instanceCount); + if (error.isError()) + { + return error; + } + + bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getAppliedElementArrayBufferID()); + + return setGenericDrawState(data); +} + +gl::Error StateManagerGL::setDrawElementsState(const gl::ContextState &data, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instanceCount, + const GLvoid **outIndices) +{ + const gl::State &state = data.getState(); + + const gl::Program *program = state.getProgram(); + + const gl::VertexArray *vao = state.getVertexArray(); + const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao); + + gl::Error error = + vaoGL->syncDrawElementsState(program->getActiveAttribLocationsMask(), count, type, indices, + instanceCount, state.isPrimitiveRestartEnabled(), outIndices); + if (error.isError()) + { + return error; + } + + bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getAppliedElementArrayBufferID()); + + return setGenericDrawState(data); +} + +gl::Error StateManagerGL::pauseTransformFeedback(const gl::ContextState &data) +{ + // If the context is going to be changed, pause the previous context's transform feedback + if (data.getContext() != mPrevDrawContext) + { + if (mPrevDrawTransformFeedback != nullptr) + { + mPrevDrawTransformFeedback->syncPausedState(true); + } + } + return gl::Error(GL_NO_ERROR); +} + +gl::Error StateManagerGL::onMakeCurrent(const gl::ContextState &data) +{ + const gl::State &state = data.getState(); + + // If the context has changed, pause the previous context's queries + if (data.getContext() != mPrevDrawContext) + { + for (QueryGL *prevQuery : mCurrentQueries) + { + prevQuery->pause(); + } + } + mCurrentQueries.clear(); + mPrevDrawTransformFeedback = nullptr; + mPrevDrawContext = data.getContext(); + + // Set the current query state + for (GLenum queryType : QueryTypes) + { + gl::Query *query = state.getActiveQuery(queryType); + if (query != nullptr) + { + QueryGL *queryGL = GetImplAs<QueryGL>(query); + queryGL->resume(); + + mCurrentQueries.insert(queryGL); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error StateManagerGL::setGenericDrawState(const gl::ContextState &data) +{ + const gl::State &state = data.getState(); + + // Sync the current program state + const gl::Program *program = state.getProgram(); + const ProgramGL *programGL = GetImplAs<ProgramGL>(program); + useProgram(programGL->getProgramID()); + + for (size_t uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); + uniformBlockIndex++) + { + GLuint binding = program->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex)); + const auto &uniformBuffer = state.getIndexedUniformBuffer(binding); + + if (uniformBuffer.get() != nullptr) + { + BufferGL *bufferGL = GetImplAs<BufferGL>(uniformBuffer.get()); + + if (uniformBuffer.getSize() == 0) + { + bindBufferBase(GL_UNIFORM_BUFFER, binding, bufferGL->getBufferID()); + } + else + { + bindBufferRange(GL_UNIFORM_BUFFER, binding, bufferGL->getBufferID(), + uniformBuffer.getOffset(), uniformBuffer.getSize()); + } + } + } + + const std::vector<SamplerBindingGL> &appliedSamplerUniforms = programGL->getAppliedSamplerUniforms(); + for (const SamplerBindingGL &samplerUniform : appliedSamplerUniforms) + { + GLenum textureType = samplerUniform.textureType; + for (GLuint textureUnitIndex : samplerUniform.boundTextureUnits) + { + gl::Texture *texture = state.getSamplerTexture(textureUnitIndex, textureType); + if (texture != nullptr) + { + const TextureGL *textureGL = GetImplAs<TextureGL>(texture); + + if (mTextures[textureType][textureUnitIndex] != textureGL->getTextureID() || + texture->hasAnyDirtyBit() || textureGL->hasAnyDirtyBit()) + { + activeTexture(textureUnitIndex); + bindTexture(textureType, textureGL->getTextureID()); + + // TODO: Call this from the gl:: layer once other backends use dirty bits for + // texture state. + texture->syncImplState(); + } + } + else + { + if (mTextures[textureType][textureUnitIndex] != 0) + { + activeTexture(textureUnitIndex); + bindTexture(textureType, 0); + } + } + + const gl::Sampler *sampler = state.getSampler(textureUnitIndex); + if (sampler != nullptr) + { + const SamplerGL *samplerGL = GetImplAs<SamplerGL>(sampler); + samplerGL->syncState(sampler->getSamplerState()); + bindSampler(textureUnitIndex, samplerGL->getSamplerID()); + } + else + { + bindSampler(textureUnitIndex, 0); + } + } + } + + const gl::Framebuffer *framebuffer = state.getDrawFramebuffer(); + const FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer); + bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferGL->getFramebufferID()); + + // Seamless cubemaps are required for ES3 and higher contexts. + setTextureCubemapSeamlessEnabled(data.getClientMajorVersion() >= 3); + + // Set the current transform feedback state + gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback(); + if (transformFeedback) + { + TransformFeedbackGL *transformFeedbackGL = + GetImplAs<TransformFeedbackGL>(transformFeedback); + bindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackGL->getTransformFeedbackID()); + transformFeedbackGL->syncActiveState(transformFeedback->isActive(), + transformFeedback->getPrimitiveMode()); + transformFeedbackGL->syncPausedState(transformFeedback->isPaused()); + mPrevDrawTransformFeedback = transformFeedbackGL; + } + else + { + bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); + mPrevDrawTransformFeedback = nullptr; + } + + return gl::Error(GL_NO_ERROR); +} + +void StateManagerGL::setAttributeCurrentData(size_t index, + const gl::VertexAttribCurrentValueData &data) +{ + if (mVertexAttribCurrentValues[index] != data) + { + mVertexAttribCurrentValues[index] = data; + switch (mVertexAttribCurrentValues[index].Type) + { + case GL_FLOAT: + mFunctions->vertexAttrib4fv(static_cast<GLuint>(index), + mVertexAttribCurrentValues[index].FloatValues); + break; + case GL_INT: + mFunctions->vertexAttribI4iv(static_cast<GLuint>(index), + mVertexAttribCurrentValues[index].IntValues); + break; + case GL_UNSIGNED_INT: + mFunctions->vertexAttribI4uiv(static_cast<GLuint>(index), + mVertexAttribCurrentValues[index].UnsignedIntValues); + break; + default: UNREACHABLE(); + } + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_CURRENT_VALUE_0 + index); + } +} + +void StateManagerGL::setScissorTestEnabled(bool enabled) +{ + if (mScissorTestEnabled != enabled) + { + mScissorTestEnabled = enabled; + if (mScissorTestEnabled) + { + mFunctions->enable(GL_SCISSOR_TEST); + } + else + { + mFunctions->disable(GL_SCISSOR_TEST); + } + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED); + } +} + +void StateManagerGL::setScissor(const gl::Rectangle &scissor) +{ + if (scissor != mScissor) + { + mScissor = scissor; + mFunctions->scissor(mScissor.x, mScissor.y, mScissor.width, mScissor.height); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR); + } +} + +void StateManagerGL::setViewport(const gl::Rectangle &viewport) +{ + if (viewport != mViewport) + { + mViewport = viewport; + mFunctions->viewport(mViewport.x, mViewport.y, mViewport.width, mViewport.height); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_VIEWPORT); + } +} + +void StateManagerGL::setDepthRange(float near, float far) +{ + if (mNear != near || mFar != far) + { + mNear = near; + mFar = far; + + // The glDepthRangef function isn't available until OpenGL 4.1. Prefer it when it is + // available because OpenGL ES only works in floats. + if (mFunctions->depthRangef) + { + mFunctions->depthRangef(mNear, mFar); + } + else + { + ASSERT(mFunctions->depthRange); + mFunctions->depthRange(mNear, mFar); + } + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_RANGE); + } +} + +void StateManagerGL::setBlendEnabled(bool enabled) +{ + if (mBlendEnabled != enabled) + { + mBlendEnabled = enabled; + if (mBlendEnabled) + { + mFunctions->enable(GL_BLEND); + } + else + { + mFunctions->disable(GL_BLEND); + } + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED); + } +} + +void StateManagerGL::setBlendColor(const gl::ColorF &blendColor) +{ + if (mBlendColor != blendColor) + { + mBlendColor = blendColor; + mFunctions->blendColor(mBlendColor.red, mBlendColor.green, mBlendColor.blue, mBlendColor.alpha); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_COLOR); + } +} + +void StateManagerGL::setBlendFuncs(GLenum sourceBlendRGB, + GLenum destBlendRGB, + GLenum sourceBlendAlpha, + GLenum destBlendAlpha) +{ + if (mSourceBlendRGB != sourceBlendRGB || mDestBlendRGB != destBlendRGB || + mSourceBlendAlpha != sourceBlendAlpha || mDestBlendAlpha != destBlendAlpha) + { + mSourceBlendRGB = sourceBlendRGB; + mDestBlendRGB = destBlendRGB; + mSourceBlendAlpha = sourceBlendAlpha; + mDestBlendAlpha = destBlendAlpha; + + mFunctions->blendFuncSeparate(mSourceBlendRGB, mDestBlendRGB, mSourceBlendAlpha, mDestBlendAlpha); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_FUNCS); + } +} + +void StateManagerGL::setBlendEquations(GLenum blendEquationRGB, GLenum blendEquationAlpha) +{ + if (mBlendEquationRGB != blendEquationRGB || mBlendEquationAlpha != blendEquationAlpha) + { + mBlendEquationRGB = blendEquationRGB; + mBlendEquationAlpha = blendEquationAlpha; + + mFunctions->blendEquationSeparate(mBlendEquationRGB, mBlendEquationAlpha); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_EQUATIONS); + } +} + +void StateManagerGL::setColorMask(bool red, bool green, bool blue, bool alpha) +{ + if (mColorMaskRed != red || mColorMaskGreen != green || mColorMaskBlue != blue || mColorMaskAlpha != alpha) + { + mColorMaskRed = red; + mColorMaskGreen = green; + mColorMaskBlue = blue; + mColorMaskAlpha = alpha; + mFunctions->colorMask(mColorMaskRed, mColorMaskGreen, mColorMaskBlue, mColorMaskAlpha); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK); + } +} + +void StateManagerGL::setSampleAlphaToCoverageEnabled(bool enabled) +{ + if (mSampleAlphaToCoverageEnabled != enabled) + { + mSampleAlphaToCoverageEnabled = enabled; + if (mSampleAlphaToCoverageEnabled) + { + mFunctions->enable(GL_SAMPLE_ALPHA_TO_COVERAGE); + } + else + { + mFunctions->disable(GL_SAMPLE_ALPHA_TO_COVERAGE); + } + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED); + } +} + +void StateManagerGL::setSampleCoverageEnabled(bool enabled) +{ + if (mSampleCoverageEnabled != enabled) + { + mSampleCoverageEnabled = enabled; + if (mSampleCoverageEnabled) + { + mFunctions->enable(GL_SAMPLE_COVERAGE); + } + else + { + mFunctions->disable(GL_SAMPLE_COVERAGE); + } + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED); + } +} + +void StateManagerGL::setSampleCoverage(float value, bool invert) +{ + if (mSampleCoverageValue != value || mSampleCoverageInvert != invert) + { + mSampleCoverageValue = value; + mSampleCoverageInvert = invert; + mFunctions->sampleCoverage(mSampleCoverageValue, mSampleCoverageInvert); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE); + } +} + +void StateManagerGL::setDepthTestEnabled(bool enabled) +{ + if (mDepthTestEnabled != enabled) + { + mDepthTestEnabled = enabled; + if (mDepthTestEnabled) + { + mFunctions->enable(GL_DEPTH_TEST); + } + else + { + mFunctions->disable(GL_DEPTH_TEST); + } + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED); + } +} + +void StateManagerGL::setDepthFunc(GLenum depthFunc) +{ + if (mDepthFunc != depthFunc) + { + mDepthFunc = depthFunc; + mFunctions->depthFunc(mDepthFunc); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_FUNC); + } +} + +void StateManagerGL::setDepthMask(bool mask) +{ + if (mDepthMask != mask) + { + mDepthMask = mask; + mFunctions->depthMask(mDepthMask); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_MASK); + } +} + +void StateManagerGL::setStencilTestEnabled(bool enabled) +{ + if (mStencilTestEnabled != enabled) + { + mStencilTestEnabled = enabled; + if (mStencilTestEnabled) + { + mFunctions->enable(GL_STENCIL_TEST); + } + else + { + mFunctions->disable(GL_STENCIL_TEST); + } + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED); + } +} + +void StateManagerGL::setStencilFrontWritemask(GLuint mask) +{ + if (mStencilFrontWritemask != mask) + { + mStencilFrontWritemask = mask; + mFunctions->stencilMaskSeparate(GL_FRONT, mStencilFrontWritemask); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT); + } +} + +void StateManagerGL::setStencilBackWritemask(GLuint mask) +{ + if (mStencilBackWritemask != mask) + { + mStencilBackWritemask = mask; + mFunctions->stencilMaskSeparate(GL_BACK, mStencilBackWritemask); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK); + } +} + +void StateManagerGL::setStencilFrontFuncs(GLenum func, GLint ref, GLuint mask) +{ + if (mStencilFrontFunc != func || mStencilFrontRef != ref || mStencilFrontValueMask != mask) + { + mStencilFrontFunc = func; + mStencilFrontRef = ref; + mStencilFrontValueMask = mask; + mFunctions->stencilFuncSeparate(GL_FRONT, mStencilFrontFunc, mStencilFrontRef, mStencilFrontValueMask); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT); + } +} + +void StateManagerGL::setStencilBackFuncs(GLenum func, GLint ref, GLuint mask) +{ + if (mStencilBackFunc != func || mStencilBackRef != ref || mStencilBackValueMask != mask) + { + mStencilBackFunc = func; + mStencilBackRef = ref; + mStencilBackValueMask = mask; + mFunctions->stencilFuncSeparate(GL_BACK, mStencilBackFunc, mStencilBackRef, mStencilBackValueMask); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK); + } +} + +void StateManagerGL::setStencilFrontOps(GLenum sfail, GLenum dpfail, GLenum dppass) +{ + if (mStencilFrontStencilFailOp != sfail || mStencilFrontStencilPassDepthFailOp != dpfail || mStencilFrontStencilPassDepthPassOp != dppass) + { + mStencilFrontStencilFailOp = sfail; + mStencilFrontStencilPassDepthFailOp = dpfail; + mStencilFrontStencilPassDepthPassOp = dppass; + mFunctions->stencilOpSeparate(GL_FRONT, mStencilFrontStencilFailOp, mStencilFrontStencilPassDepthFailOp, mStencilFrontStencilPassDepthPassOp); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_FRONT); + } +} + +void StateManagerGL::setStencilBackOps(GLenum sfail, GLenum dpfail, GLenum dppass) +{ + if (mStencilBackStencilFailOp != sfail || mStencilBackStencilPassDepthFailOp != dpfail || mStencilBackStencilPassDepthPassOp != dppass) + { + mStencilBackStencilFailOp = sfail; + mStencilBackStencilPassDepthFailOp = dpfail; + mStencilBackStencilPassDepthPassOp = dppass; + mFunctions->stencilOpSeparate(GL_BACK, mStencilBackStencilFailOp, mStencilBackStencilPassDepthFailOp, mStencilBackStencilPassDepthPassOp); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_BACK); + } +} + +void StateManagerGL::setCullFaceEnabled(bool enabled) +{ + if (mCullFaceEnabled != enabled) + { + mCullFaceEnabled = enabled; + if (mCullFaceEnabled) + { + mFunctions->enable(GL_CULL_FACE); + } + else + { + mFunctions->disable(GL_CULL_FACE); + } + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE_ENABLED); + } +} + +void StateManagerGL::setCullFace(GLenum cullFace) +{ + if (mCullFace != cullFace) + { + mCullFace = cullFace; + mFunctions->cullFace(mCullFace); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE); + } +} + +void StateManagerGL::setFrontFace(GLenum frontFace) +{ + if (mFrontFace != frontFace) + { + mFrontFace = frontFace; + mFunctions->frontFace(mFrontFace); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRONT_FACE); + } +} + +void StateManagerGL::setPolygonOffsetFillEnabled(bool enabled) +{ + if (mPolygonOffsetFillEnabled != enabled) + { + mPolygonOffsetFillEnabled = enabled; + if (mPolygonOffsetFillEnabled) + { + mFunctions->enable(GL_POLYGON_OFFSET_FILL); + } + else + { + mFunctions->disable(GL_POLYGON_OFFSET_FILL); + } + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED); + } +} + +void StateManagerGL::setPolygonOffset(float factor, float units) +{ + if (mPolygonOffsetFactor != factor || mPolygonOffsetUnits != units) + { + mPolygonOffsetFactor = factor; + mPolygonOffsetUnits = units; + mFunctions->polygonOffset(mPolygonOffsetFactor, mPolygonOffsetUnits); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET); + } +} + +void StateManagerGL::setRasterizerDiscardEnabled(bool enabled) +{ + if (mRasterizerDiscardEnabled != enabled) + { + mRasterizerDiscardEnabled = enabled; + if (mRasterizerDiscardEnabled) + { + mFunctions->enable(GL_RASTERIZER_DISCARD); + } + else + { + mFunctions->disable(GL_RASTERIZER_DISCARD); + } + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED); + } +} + +void StateManagerGL::setLineWidth(float width) +{ + if (mLineWidth != width) + { + mLineWidth = width; + mFunctions->lineWidth(mLineWidth); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_LINE_WIDTH); + } +} + +void StateManagerGL::setPrimitiveRestartEnabled(bool enabled) +{ + if (mPrimitiveRestartEnabled != enabled) + { + mPrimitiveRestartEnabled = enabled; + + if (mPrimitiveRestartEnabled) + { + mFunctions->enable(GL_PRIMITIVE_RESTART_FIXED_INDEX); + } + else + { + mFunctions->disable(GL_PRIMITIVE_RESTART_FIXED_INDEX); + } + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED); + } +} + +void StateManagerGL::setClearDepth(float clearDepth) +{ + if (mClearDepth != clearDepth) + { + mClearDepth = clearDepth; + + // The glClearDepthf function isn't available until OpenGL 4.1. Prefer it when it is + // available because OpenGL ES only works in floats. + if (mFunctions->clearDepthf) + { + mFunctions->clearDepthf(mClearDepth); + } + else + { + ASSERT(mFunctions->clearDepth); + mFunctions->clearDepth(mClearDepth); + } + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_DEPTH); + } +} + +void StateManagerGL::setClearColor(const gl::ColorF &clearColor) +{ + if (mClearColor != clearColor) + { + mClearColor = clearColor; + mFunctions->clearColor(mClearColor.red, mClearColor.green, mClearColor.blue, mClearColor.alpha); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_COLOR); + } +} + +void StateManagerGL::setClearStencil(GLint clearStencil) +{ + if (mClearStencil != clearStencil) + { + mClearStencil = clearStencil; + mFunctions->clearStencil(mClearStencil); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_STENCIL); + } +} + +void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBits &glDirtyBits) +{ + // The the current framebuffer binding sometimes requires resetting the srgb blending + if (glDirtyBits[gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING] && + mFunctions->standard == STANDARD_GL_DESKTOP) + { + mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB); + } + + const auto &glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits); + + if (!glAndLocalDirtyBits.any()) + { + return; + } + + // TODO(jmadill): Investigate only syncing vertex state for active attributes + for (auto dirtyBit : angle::IterateBitSet(glAndLocalDirtyBits)) + { + switch (dirtyBit) + { + case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED: + setScissorTestEnabled(state.isScissorTestEnabled()); + break; + case gl::State::DIRTY_BIT_SCISSOR: + setScissor(state.getScissor()); + break; + case gl::State::DIRTY_BIT_VIEWPORT: + setViewport(state.getViewport()); + break; + case gl::State::DIRTY_BIT_DEPTH_RANGE: + setDepthRange(state.getNearPlane(), state.getFarPlane()); + break; + case gl::State::DIRTY_BIT_BLEND_ENABLED: + setBlendEnabled(state.isBlendEnabled()); + break; + case gl::State::DIRTY_BIT_BLEND_COLOR: + setBlendColor(state.getBlendColor()); + break; + case gl::State::DIRTY_BIT_BLEND_FUNCS: + { + const auto &blendState = state.getBlendState(); + setBlendFuncs(blendState.sourceBlendRGB, blendState.destBlendRGB, + blendState.sourceBlendAlpha, blendState.destBlendAlpha); + break; + } + case gl::State::DIRTY_BIT_BLEND_EQUATIONS: + { + const auto &blendState = state.getBlendState(); + setBlendEquations(blendState.blendEquationRGB, blendState.blendEquationAlpha); + break; + } + case gl::State::DIRTY_BIT_COLOR_MASK: + { + const auto &blendState = state.getBlendState(); + setColorMask(blendState.colorMaskRed, blendState.colorMaskGreen, + blendState.colorMaskBlue, blendState.colorMaskAlpha); + break; + } + case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: + setSampleAlphaToCoverageEnabled(state.isSampleAlphaToCoverageEnabled()); + break; + case gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED: + setSampleCoverageEnabled(state.isSampleCoverageEnabled()); + break; + case gl::State::DIRTY_BIT_SAMPLE_COVERAGE: + setSampleCoverage(state.getSampleCoverageValue(), state.getSampleCoverageInvert()); + break; + case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED: + setDepthTestEnabled(state.isDepthTestEnabled()); + break; + case gl::State::DIRTY_BIT_DEPTH_FUNC: + setDepthFunc(state.getDepthStencilState().depthFunc); + break; + case gl::State::DIRTY_BIT_DEPTH_MASK: + setDepthMask(state.getDepthStencilState().depthMask); + break; + case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: + setStencilTestEnabled(state.isStencilTestEnabled()); + break; + case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: + { + const auto &depthStencilState = state.getDepthStencilState(); + setStencilFrontFuncs(depthStencilState.stencilFunc, state.getStencilRef(), + depthStencilState.stencilMask); + break; + } + case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK: + { + const auto &depthStencilState = state.getDepthStencilState(); + setStencilBackFuncs(depthStencilState.stencilBackFunc, state.getStencilBackRef(), + depthStencilState.stencilBackMask); + break; + } + case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT: + { + const auto &depthStencilState = state.getDepthStencilState(); + setStencilFrontOps(depthStencilState.stencilFail, + depthStencilState.stencilPassDepthFail, + depthStencilState.stencilPassDepthPass); + break; + } + case gl::State::DIRTY_BIT_STENCIL_OPS_BACK: + { + const auto &depthStencilState = state.getDepthStencilState(); + setStencilBackOps(depthStencilState.stencilBackFail, + depthStencilState.stencilBackPassDepthFail, + depthStencilState.stencilBackPassDepthPass); + break; + } + case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT: + setStencilFrontWritemask(state.getDepthStencilState().stencilWritemask); + break; + case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK: + setStencilBackWritemask(state.getDepthStencilState().stencilBackWritemask); + break; + case gl::State::DIRTY_BIT_CULL_FACE_ENABLED: + setCullFaceEnabled(state.isCullFaceEnabled()); + break; + case gl::State::DIRTY_BIT_CULL_FACE: + setCullFace(state.getRasterizerState().cullMode); + break; + case gl::State::DIRTY_BIT_FRONT_FACE: + setFrontFace(state.getRasterizerState().frontFace); + break; + case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: + setPolygonOffsetFillEnabled(state.isPolygonOffsetFillEnabled()); + break; + case gl::State::DIRTY_BIT_POLYGON_OFFSET: + { + const auto &rasterizerState = state.getRasterizerState(); + setPolygonOffset(rasterizerState.polygonOffsetFactor, + rasterizerState.polygonOffsetUnits); + break; + } + case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED: + setRasterizerDiscardEnabled(state.isRasterizerDiscardEnabled()); + break; + case gl::State::DIRTY_BIT_LINE_WIDTH: + setLineWidth(state.getLineWidth()); + break; + case gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED: + setPrimitiveRestartEnabled(state.isPrimitiveRestartEnabled()); + break; + case gl::State::DIRTY_BIT_CLEAR_COLOR: + setClearColor(state.getColorClearValue()); + break; + case gl::State::DIRTY_BIT_CLEAR_DEPTH: + setClearDepth(state.getDepthClearValue()); + break; + case gl::State::DIRTY_BIT_CLEAR_STENCIL: + setClearStencil(state.getStencilClearValue()); + break; + case gl::State::DIRTY_BIT_UNPACK_ALIGNMENT: + // TODO(jmadill): split this + setPixelUnpackState(state.getUnpackState()); + break; + case gl::State::DIRTY_BIT_UNPACK_ROW_LENGTH: + // TODO(jmadill): split this + setPixelUnpackState(state.getUnpackState()); + break; + case gl::State::DIRTY_BIT_UNPACK_IMAGE_HEIGHT: + // TODO(jmadill): split this + setPixelUnpackState(state.getUnpackState()); + break; + case gl::State::DIRTY_BIT_UNPACK_SKIP_IMAGES: + // TODO(jmadill): split this + setPixelUnpackState(state.getUnpackState()); + break; + case gl::State::DIRTY_BIT_UNPACK_SKIP_ROWS: + // TODO(jmadill): split this + setPixelUnpackState(state.getUnpackState()); + break; + case gl::State::DIRTY_BIT_UNPACK_SKIP_PIXELS: + // TODO(jmadill): split this + setPixelUnpackState(state.getUnpackState()); + break; + case gl::State::DIRTY_BIT_UNPACK_BUFFER_BINDING: + // TODO(jmadill): split this + setPixelUnpackState(state.getUnpackState()); + break; + case gl::State::DIRTY_BIT_PACK_ALIGNMENT: + // TODO(jmadill): split this + setPixelPackState(state.getPackState()); + break; + case gl::State::DIRTY_BIT_PACK_REVERSE_ROW_ORDER: + // TODO(jmadill): split this + setPixelPackState(state.getPackState()); + break; + case gl::State::DIRTY_BIT_PACK_ROW_LENGTH: + // TODO(jmadill): split this + setPixelPackState(state.getPackState()); + break; + case gl::State::DIRTY_BIT_PACK_SKIP_ROWS: + // TODO(jmadill): split this + setPixelPackState(state.getPackState()); + break; + case gl::State::DIRTY_BIT_PACK_SKIP_PIXELS: + // TODO(jmadill): split this + setPixelPackState(state.getPackState()); + break; + case gl::State::DIRTY_BIT_PACK_BUFFER_BINDING: + // TODO(jmadill): split this + setPixelPackState(state.getPackState()); + break; + case gl::State::DIRTY_BIT_DITHER_ENABLED: + setDitherEnabled(state.isDitherEnabled()); + break; + case gl::State::DIRTY_BIT_GENERATE_MIPMAP_HINT: + // TODO(jmadill): implement this + break; + case gl::State::DIRTY_BIT_SHADER_DERIVATIVE_HINT: + // TODO(jmadill): implement this + break; + case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING: + // TODO(jmadill): implement this + break; + case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING: + // TODO(jmadill): implement this + break; + case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING: + // TODO(jmadill): implement this + break; + case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING: + // TODO(jmadill): implement this + break; + case gl::State::DIRTY_BIT_PROGRAM_BINDING: + // TODO(jmadill): implement this + break; + case gl::State::DIRTY_BIT_MULTISAMPLING: + setMultisamplingStateEnabled(state.isMultisamplingEnabled()); + break; + case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE: + setSampleAlphaToOneStateEnabled(state.isSampleAlphaToOneEnabled()); + case gl::State::DIRTY_BIT_COVERAGE_MODULATION: + setCoverageModulation(state.getCoverageModulation()); + break; + case gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_MV: + setPathRenderingModelViewMatrix( + state.getPathRenderingMatrix(GL_PATH_MODELVIEW_MATRIX_CHROMIUM)); + break; + case gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ: + setPathRenderingProjectionMatrix( + state.getPathRenderingMatrix(GL_PATH_PROJECTION_MATRIX_CHROMIUM)); + break; + case gl::State::DIRTY_BIT_PATH_RENDERING_STENCIL_STATE: + setPathRenderingStencilState(state.getPathStencilFunc(), state.getPathStencilRef(), + state.getPathStencilMask()); + break; + case gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB: + setFramebufferSRGBEnabledForFramebuffer( + state.getFramebufferSRGB(), + GetImplAs<FramebufferGL>(state.getDrawFramebuffer())); + break; + default: + { + ASSERT(dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 && + dirtyBit < gl::State::DIRTY_BIT_CURRENT_VALUE_MAX); + size_t attribIndex = + static_cast<size_t>(dirtyBit) - gl::State::DIRTY_BIT_CURRENT_VALUE_0; + setAttributeCurrentData(attribIndex, state.getVertexAttribCurrentValue( + static_cast<unsigned int>(attribIndex))); + break; + } + } + + mLocalDirtyBits.reset(); + } +} + +void StateManagerGL::setFramebufferSRGBEnabled(bool enabled) +{ + if (mFramebufferSRGBEnabled != enabled) + { + mFramebufferSRGBEnabled = enabled; + if (mFramebufferSRGBEnabled) + { + mFunctions->enable(GL_FRAMEBUFFER_SRGB); + } + else + { + mFunctions->disable(GL_FRAMEBUFFER_SRGB); + } + mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB); + } +} + +void StateManagerGL::setFramebufferSRGBEnabledForFramebuffer(bool enabled, + const FramebufferGL *framebuffer) +{ + if (mFunctions->standard == STANDARD_GL_DESKTOP && framebuffer->isDefault()) + { + // Obey the framebuffer sRGB state for blending on all framebuffers except the default + // framebuffer on Desktop OpenGL. + // When SRGB blending is enabled, only SRGB capable formats will use it but the default + // framebuffer will always use it if it is enabled. + // TODO(geofflang): Update this when the framebuffer binding dirty changes, when it exists. + setFramebufferSRGBEnabled(false); + } + else + { + setFramebufferSRGBEnabled(enabled); + } +} + +void StateManagerGL::setDitherEnabled(bool enabled) +{ + if (mDitherEnabled != enabled) + { + mDitherEnabled = enabled; + if (mDitherEnabled) + { + mFunctions->enable(GL_DITHER); + } + else + { + mFunctions->disable(GL_DITHER); + } + } +} + +void StateManagerGL::setMultisamplingStateEnabled(bool enabled) +{ + if (mMultisamplingEnabled != enabled) + { + mMultisamplingEnabled = enabled; + if (mMultisamplingEnabled) + { + mFunctions->enable(GL_MULTISAMPLE_EXT); + } + else + { + mFunctions->disable(GL_MULTISAMPLE_EXT); + } + mLocalDirtyBits.set(gl::State::DIRTY_BIT_MULTISAMPLING); + } +} + +void StateManagerGL::setSampleAlphaToOneStateEnabled(bool enabled) +{ + if (mSampleAlphaToOneEnabled != enabled) + { + mSampleAlphaToOneEnabled = enabled; + if (mSampleAlphaToOneEnabled) + { + mFunctions->enable(GL_SAMPLE_ALPHA_TO_ONE); + } + else + { + mFunctions->disable(GL_SAMPLE_ALPHA_TO_ONE); + } + mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE); + } +} + +void StateManagerGL::setCoverageModulation(GLenum components) +{ + if (mCoverageModulation != components) + { + mCoverageModulation = components; + mFunctions->coverageModulationNV(components); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_COVERAGE_MODULATION); + } +} + +void StateManagerGL::setPathRenderingModelViewMatrix(const GLfloat *m) +{ + if (memcmp(mPathMatrixMV, m, sizeof(mPathMatrixMV)) != 0) + { + memcpy(mPathMatrixMV, m, sizeof(mPathMatrixMV)); + mFunctions->matrixLoadEXT(GL_PATH_MODELVIEW_CHROMIUM, m); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_MV); + } +} + +void StateManagerGL::setPathRenderingProjectionMatrix(const GLfloat *m) +{ + if (memcmp(mPathMatrixProj, m, sizeof(mPathMatrixProj)) != 0) + { + memcpy(mPathMatrixProj, m, sizeof(mPathMatrixProj)); + mFunctions->matrixLoadEXT(GL_PATH_PROJECTION_CHROMIUM, m); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ); + } +} + +void StateManagerGL::setPathRenderingStencilState(GLenum func, GLint ref, GLuint mask) +{ + if (func != mPathStencilFunc || ref != mPathStencilRef || mask != mPathStencilMask) + { + mPathStencilFunc = func; + mPathStencilRef = ref; + mPathStencilMask = mask; + mFunctions->pathStencilFuncNV(func, ref, mask); + + mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING_STENCIL_STATE); + } +} + +void StateManagerGL::setTextureCubemapSeamlessEnabled(bool enabled) +{ + if (mTextureCubemapSeamlessEnabled != enabled) + { + mTextureCubemapSeamlessEnabled = enabled; + if (mTextureCubemapSeamlessEnabled) + { + mFunctions->enable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + } + else + { + mFunctions->disable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + } + } +} + +GLuint StateManagerGL::getBoundBuffer(GLenum type) +{ + ASSERT(mBuffers.find(type) != mBuffers.end()); + return mBuffers[type]; +} +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/StateManagerGL.h b/gfx/angle/src/libANGLE/renderer/gl/StateManagerGL.h new file mode 100755 index 000000000..3c8c5389f --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/StateManagerGL.h @@ -0,0 +1,290 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// StateManagerGL.h: Defines a class for caching applied OpenGL state + +#ifndef LIBANGLE_RENDERER_GL_STATEMANAGERGL_H_ +#define LIBANGLE_RENDERER_GL_STATEMANAGERGL_H_ + +#include "common/debug.h" +#include "libANGLE/Error.h" +#include "libANGLE/State.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/gl/functionsgl_typedefs.h" + +#include <map> + +namespace gl +{ +struct Caps; +class ContextState; +class State; +} + +namespace rx +{ + +class FramebufferGL; +class FunctionsGL; +class TransformFeedbackGL; +class QueryGL; + +class StateManagerGL final : angle::NonCopyable +{ + public: + StateManagerGL(const FunctionsGL *functions, const gl::Caps &rendererCaps); + + void deleteProgram(GLuint program); + void deleteVertexArray(GLuint vao); + void deleteTexture(GLuint texture); + void deleteSampler(GLuint sampler); + void deleteBuffer(GLuint buffer); + void deleteFramebuffer(GLuint fbo); + void deleteRenderbuffer(GLuint rbo); + void deleteTransformFeedback(GLuint transformFeedback); + void deleteQuery(GLuint query); + + void useProgram(GLuint program); + void forceUseProgram(GLuint program); + void bindVertexArray(GLuint vao, GLuint elementArrayBuffer); + void bindBuffer(GLenum type, GLuint buffer); + void bindBufferBase(GLenum type, size_t index, GLuint buffer); + void bindBufferRange(GLenum type, size_t index, GLuint buffer, size_t offset, size_t size); + void activeTexture(size_t unit); + void bindTexture(GLenum type, GLuint texture); + void bindSampler(size_t unit, GLuint sampler); + void bindFramebuffer(GLenum type, GLuint framebuffer); + void bindRenderbuffer(GLenum type, GLuint renderbuffer); + void bindTransformFeedback(GLenum type, GLuint transformFeedback); + void beginQuery(GLenum type, GLuint query); + void endQuery(GLenum type, GLuint query); + void onBeginQuery(QueryGL *query); + + void setAttributeCurrentData(size_t index, const gl::VertexAttribCurrentValueData &data); + + void setScissorTestEnabled(bool enabled); + void setScissor(const gl::Rectangle &scissor); + + void setViewport(const gl::Rectangle &viewport); + void setDepthRange(float near, float far); + + void setBlendEnabled(bool enabled); + void setBlendColor(const gl::ColorF &blendColor); + void setBlendFuncs(GLenum sourceBlendRGB, + GLenum destBlendRGB, + GLenum sourceBlendAlpha, + GLenum destBlendAlpha); + void setBlendEquations(GLenum blendEquationRGB, GLenum blendEquationAlpha); + void setColorMask(bool red, bool green, bool blue, bool alpha); + void setSampleAlphaToCoverageEnabled(bool enabled); + void setSampleCoverageEnabled(bool enabled); + void setSampleCoverage(float value, bool invert); + + void setDepthTestEnabled(bool enabled); + void setDepthFunc(GLenum depthFunc); + void setDepthMask(bool mask); + void setStencilTestEnabled(bool enabled); + void setStencilFrontWritemask(GLuint mask); + void setStencilBackWritemask(GLuint mask); + void setStencilFrontFuncs(GLenum func, GLint ref, GLuint mask); + void setStencilBackFuncs(GLenum func, GLint ref, GLuint mask); + void setStencilFrontOps(GLenum sfail, GLenum dpfail, GLenum dppass); + void setStencilBackOps(GLenum sfail, GLenum dpfail, GLenum dppass); + + void setCullFaceEnabled(bool enabled); + void setCullFace(GLenum cullFace); + void setFrontFace(GLenum frontFace); + void setPolygonOffsetFillEnabled(bool enabled); + void setPolygonOffset(float factor, float units); + void setRasterizerDiscardEnabled(bool enabled); + void setLineWidth(float width); + + void setPrimitiveRestartEnabled(bool enabled); + + void setClearColor(const gl::ColorF &clearColor); + void setClearDepth(float clearDepth); + void setClearStencil(GLint clearStencil); + + void setPixelUnpackState(const gl::PixelUnpackState &unpack); + void setPixelUnpackState(GLint alignment, + GLint rowLength, + GLint skipRows, + GLint skipPixels, + GLint imageHeight, + GLint skipImages, + GLuint unpackBuffer); + void setPixelPackState(const gl::PixelPackState &pack); + void setPixelPackState(GLint alignment, + GLint rowLength, + GLint skipRows, + GLint skipPixels, + GLuint packBuffer); + + void setFramebufferSRGBEnabled(bool enabled); + void setFramebufferSRGBEnabledForFramebuffer(bool enabled, const FramebufferGL *framebuffer); + + void setDitherEnabled(bool enabled); + + void setMultisamplingStateEnabled(bool enabled); + void setSampleAlphaToOneStateEnabled(bool enabled); + + void setCoverageModulation(GLenum components); + + void setPathRenderingModelViewMatrix(const GLfloat *m); + void setPathRenderingProjectionMatrix(const GLfloat *m); + void setPathRenderingStencilState(GLenum func, GLint ref, GLuint mask); + + void onDeleteQueryObject(QueryGL *query); + + gl::Error setDrawArraysState(const gl::ContextState &data, + GLint first, + GLsizei count, + GLsizei instanceCount); + gl::Error setDrawElementsState(const gl::ContextState &data, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instanceCount, + const GLvoid **outIndices); + + gl::Error pauseTransformFeedback(const gl::ContextState &data); + gl::Error onMakeCurrent(const gl::ContextState &data); + + void syncState(const gl::State &state, const gl::State::DirtyBits &glDirtyBits); + + GLuint getBoundBuffer(GLenum type); + + private: + gl::Error setGenericDrawState(const gl::ContextState &data); + + void setTextureCubemapSeamlessEnabled(bool enabled); + + const FunctionsGL *mFunctions; + + GLuint mProgram; + + GLuint mVAO; + std::vector<gl::VertexAttribCurrentValueData> mVertexAttribCurrentValues; + + std::map<GLenum, GLuint> mBuffers; + + struct IndexedBufferBinding + { + IndexedBufferBinding(); + + size_t offset; + size_t size; + GLuint buffer; + }; + std::map<GLenum, std::vector<IndexedBufferBinding>> mIndexedBuffers; + + size_t mTextureUnitIndex; + std::map<GLenum, std::vector<GLuint>> mTextures; + std::vector<GLuint> mSamplers; + + GLuint mTransformFeedback; + + std::map<GLenum, GLuint> mQueries; + + TransformFeedbackGL *mPrevDrawTransformFeedback; + std::set<QueryGL *> mCurrentQueries; + uintptr_t mPrevDrawContext; + + GLint mUnpackAlignment; + GLint mUnpackRowLength; + GLint mUnpackSkipRows; + GLint mUnpackSkipPixels; + GLint mUnpackImageHeight; + GLint mUnpackSkipImages; + + GLint mPackAlignment; + GLint mPackRowLength; + GLint mPackSkipRows; + GLint mPackSkipPixels; + + // TODO(jmadill): Convert to std::array when available + std::vector<GLenum> mFramebuffers; + GLuint mRenderbuffer; + + bool mScissorTestEnabled; + gl::Rectangle mScissor; + + gl::Rectangle mViewport; + float mNear; + float mFar; + + bool mBlendEnabled; + gl::ColorF mBlendColor; + GLenum mSourceBlendRGB; + GLenum mDestBlendRGB; + GLenum mSourceBlendAlpha; + GLenum mDestBlendAlpha; + GLenum mBlendEquationRGB; + GLenum mBlendEquationAlpha; + bool mColorMaskRed; + bool mColorMaskGreen; + bool mColorMaskBlue; + bool mColorMaskAlpha; + bool mSampleAlphaToCoverageEnabled; + bool mSampleCoverageEnabled; + float mSampleCoverageValue; + bool mSampleCoverageInvert; + + bool mDepthTestEnabled; + GLenum mDepthFunc; + bool mDepthMask; + bool mStencilTestEnabled; + GLenum mStencilFrontFunc; + GLint mStencilFrontRef; + GLuint mStencilFrontValueMask; + GLenum mStencilFrontStencilFailOp; + GLenum mStencilFrontStencilPassDepthFailOp; + GLenum mStencilFrontStencilPassDepthPassOp; + GLuint mStencilFrontWritemask; + GLenum mStencilBackFunc; + GLint mStencilBackRef; + GLuint mStencilBackValueMask; + GLenum mStencilBackStencilFailOp; + GLenum mStencilBackStencilPassDepthFailOp; + GLenum mStencilBackStencilPassDepthPassOp; + GLuint mStencilBackWritemask; + + bool mCullFaceEnabled; + GLenum mCullFace; + GLenum mFrontFace; + bool mPolygonOffsetFillEnabled; + GLfloat mPolygonOffsetFactor; + GLfloat mPolygonOffsetUnits; + bool mRasterizerDiscardEnabled; + float mLineWidth; + + bool mPrimitiveRestartEnabled; + + gl::ColorF mClearColor; + float mClearDepth; + GLint mClearStencil; + + bool mFramebufferSRGBEnabled; + bool mDitherEnabled; + bool mTextureCubemapSeamlessEnabled; + + bool mMultisamplingEnabled; + bool mSampleAlphaToOneEnabled; + + GLenum mCoverageModulation; + + GLfloat mPathMatrixMV[16]; + GLfloat mPathMatrixProj[16]; + GLenum mPathStencilFunc; + GLint mPathStencilRef; + GLuint mPathStencilMask; + + gl::State::DirtyBits mLocalDirtyBits; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_STATEMANAGERGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/SurfaceGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/SurfaceGL.cpp new file mode 100755 index 000000000..a1f0abba7 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/SurfaceGL.cpp @@ -0,0 +1,36 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SurfaceGL.cpp: OpenGL implementation of egl::Surface + +#include "libANGLE/renderer/gl/SurfaceGL.h" + +#include "libANGLE/renderer/gl/FramebufferGL.h" +#include "libANGLE/renderer/gl/RendererGL.h" + +namespace rx +{ + +SurfaceGL::SurfaceGL(const egl::SurfaceState &state, RendererGL *renderer) + : SurfaceImpl(state), mRenderer(renderer) +{ +} + +SurfaceGL::~SurfaceGL() +{ +} + +FramebufferImpl *SurfaceGL::createDefaultFramebuffer(const gl::FramebufferState &data) +{ + return new FramebufferGL(data, mRenderer->getFunctions(), mRenderer->getStateManager(), + mRenderer->getWorkarounds(), mRenderer->getBlitter(), true); +} + +egl::Error SurfaceGL::unMakeCurrent() +{ + return egl::Error(EGL_SUCCESS); +} +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/SurfaceGL.h b/gfx/angle/src/libANGLE/renderer/gl/SurfaceGL.h new file mode 100755 index 000000000..681c365d2 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/SurfaceGL.h @@ -0,0 +1,36 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SurfaceGL.h: Defines the class interface for SurfaceGL. + +#ifndef LIBANGLE_RENDERER_GL_SURFACEGL_H_ +#define LIBANGLE_RENDERER_GL_SURFACEGL_H_ + +#include "libANGLE/renderer/SurfaceImpl.h" + +namespace rx +{ + +class RendererGL; + +class SurfaceGL : public SurfaceImpl +{ + public: + SurfaceGL(const egl::SurfaceState &state, RendererGL *renderer); + ~SurfaceGL() override; + + FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override; + + virtual egl::Error makeCurrent() = 0; + virtual egl::Error unMakeCurrent(); + + private: + RendererGL *mRenderer; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_SURFACEGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/TextureGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/TextureGL.cpp new file mode 100755 index 000000000..589580505 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/TextureGL.cpp @@ -0,0 +1,1039 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureGL.cpp: Implements the class methods for TextureGL. + +#include "libANGLE/renderer/gl/TextureGL.h" + +#include "common/BitSetIterator.h" +#include "common/debug.h" +#include "common/utilities.h" +#include "libANGLE/State.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/gl/BlitGL.h" +#include "libANGLE/renderer/gl/BufferGL.h" +#include "libANGLE/renderer/gl/FramebufferGL.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" +#include "libANGLE/renderer/gl/WorkaroundsGL.h" +#include "libANGLE/renderer/gl/formatutilsgl.h" +#include "libANGLE/renderer/gl/renderergl_utils.h" + +using angle::CheckedNumeric; + +namespace rx +{ + +namespace +{ + +bool UseTexImage2D(GLenum textureType) +{ + return textureType == GL_TEXTURE_2D || textureType == GL_TEXTURE_CUBE_MAP; +} + +bool UseTexImage3D(GLenum textureType) +{ + return textureType == GL_TEXTURE_2D_ARRAY || textureType == GL_TEXTURE_3D; +} + +bool CompatibleTextureTarget(GLenum textureType, GLenum textureTarget) +{ + if (textureType != GL_TEXTURE_CUBE_MAP) + { + return textureType == textureTarget; + } + else + { + return gl::IsCubeMapTextureTarget(textureTarget); + } +} + +bool IsLUMAFormat(GLenum format) +{ + return format == GL_LUMINANCE || format == GL_ALPHA || format == GL_LUMINANCE_ALPHA; +} + +LUMAWorkaroundGL GetLUMAWorkaroundInfo(const gl::InternalFormat &originalFormatInfo, + GLenum destinationFormat) +{ + if (IsLUMAFormat(originalFormatInfo.format)) + { + const gl::InternalFormat &destinationFormatInfo = + gl::GetInternalFormatInfo(destinationFormat); + return LUMAWorkaroundGL(!IsLUMAFormat(destinationFormatInfo.format), + destinationFormatInfo.format); + } + else + { + return LUMAWorkaroundGL(false, GL_NONE); + } +} + +bool IsDepthStencilFormat(GLenum format) +{ + return format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL; +} + +bool GetDepthStencilWorkaround(const gl::InternalFormat &originalFormatInfo) +{ + return IsDepthStencilFormat(originalFormatInfo.format); +} + +LevelInfoGL GetLevelInfo(GLenum originalFormat, GLenum destinationFormat) +{ + const gl::InternalFormat &originalFormatInfo = gl::GetInternalFormatInfo(originalFormat); + return LevelInfoGL(originalFormat, GetDepthStencilWorkaround(originalFormatInfo), + GetLUMAWorkaroundInfo(originalFormatInfo, destinationFormat)); +} + +gl::Texture::DirtyBits GetLevelWorkaroundDirtyBits() +{ + gl::Texture::DirtyBits bits; + bits.set(gl::Texture::DIRTY_BIT_SWIZZLE_RED); + bits.set(gl::Texture::DIRTY_BIT_SWIZZLE_GREEN); + bits.set(gl::Texture::DIRTY_BIT_SWIZZLE_BLUE); + bits.set(gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA); + return bits; +} + +} // anonymous namespace + +LUMAWorkaroundGL::LUMAWorkaroundGL() : LUMAWorkaroundGL(false, GL_NONE) +{ +} + +LUMAWorkaroundGL::LUMAWorkaroundGL(bool enabled_, GLenum workaroundFormat_) + : enabled(enabled_), workaroundFormat(workaroundFormat_) +{ +} + +LevelInfoGL::LevelInfoGL() : LevelInfoGL(GL_NONE, false, LUMAWorkaroundGL()) +{ +} + +LevelInfoGL::LevelInfoGL(GLenum sourceFormat_, + bool depthStencilWorkaround_, + const LUMAWorkaroundGL &lumaWorkaround_) + : sourceFormat(sourceFormat_), + depthStencilWorkaround(depthStencilWorkaround_), + lumaWorkaround(lumaWorkaround_) +{ +} + +TextureGL::TextureGL(const gl::TextureState &state, + const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + StateManagerGL *stateManager, + BlitGL *blitter) + : TextureImpl(state), + mFunctions(functions), + mWorkarounds(workarounds), + mStateManager(stateManager), + mBlitter(blitter), + mLevelInfo(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1), + mAppliedTextureState(state.mTarget), + mTextureID(0) +{ + ASSERT(mFunctions); + ASSERT(mStateManager); + ASSERT(mBlitter); + + mFunctions->genTextures(1, &mTextureID); + mStateManager->bindTexture(mState.mTarget, mTextureID); +} + +TextureGL::~TextureGL() +{ + mStateManager->deleteTexture(mTextureID); + mTextureID = 0; +} + +gl::Error TextureGL::setImage(GLenum target, + size_t level, + GLenum internalFormat, + const gl::Extents &size, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) +{ + if (mWorkarounds.unpackOverlappingRowsSeparatelyUnpackBuffer && unpack.pixelBuffer.get() && + unpack.rowLength != 0 && unpack.rowLength < size.width) + { + // The rows overlap in unpack memory. Upload the texture row by row to work around + // driver bug. + reserveTexImageToBeFilled(target, level, internalFormat, size, format, type); + + if (size.width == 0 || size.height == 0 || size.depth == 0) + { + return gl::NoError(); + } + + gl::Box area(0, 0, 0, size.width, size.height, size.depth); + return setSubImageRowByRowWorkaround(target, level, area, format, type, unpack, pixels); + } + + if (mWorkarounds.unpackLastRowSeparatelyForPaddingInclusion) + { + bool apply; + ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, unpack, format, type, + UseTexImage3D(mState.mTarget), pixels), + apply); + + // The driver will think the pixel buffer doesn't have enough data, work around this bug + // by uploading the last row (and last level if 3D) separately. + if (apply) + { + reserveTexImageToBeFilled(target, level, internalFormat, size, format, type); + + if (size.width == 0 || size.height == 0 || size.depth == 0) + { + return gl::NoError(); + } + + gl::Box area(0, 0, 0, size.width, size.height, size.depth); + return setSubImagePaddingWorkaround(target, level, area, format, type, unpack, pixels); + } + } + + setImageHelper(target, level, internalFormat, size, format, type, pixels); + + return gl::NoError(); +} + +void TextureGL::setImageHelper(GLenum target, + size_t level, + GLenum internalFormat, + const gl::Extents &size, + GLenum format, + GLenum type, + const uint8_t *pixels) +{ + ASSERT(CompatibleTextureTarget(mState.mTarget, target)); + + nativegl::TexImageFormat texImageFormat = + nativegl::GetTexImageFormat(mFunctions, mWorkarounds, internalFormat, format, type); + + mStateManager->bindTexture(mState.mTarget, mTextureID); + + if (UseTexImage2D(mState.mTarget)) + { + ASSERT(size.depth == 1); + mFunctions->texImage2D(target, static_cast<GLint>(level), texImageFormat.internalFormat, + size.width, size.height, 0, texImageFormat.format, + texImageFormat.type, pixels); + } + else if (UseTexImage3D(mState.mTarget)) + { + mFunctions->texImage3D(target, static_cast<GLint>(level), texImageFormat.internalFormat, + size.width, size.height, size.depth, 0, texImageFormat.format, + texImageFormat.type, pixels); + } + else + { + UNREACHABLE(); + } + + setLevelInfo(level, 1, GetLevelInfo(internalFormat, texImageFormat.internalFormat)); +} + +void TextureGL::reserveTexImageToBeFilled(GLenum target, + size_t level, + GLenum internalFormat, + const gl::Extents &size, + GLenum format, + GLenum type) +{ + GLuint unpackBuffer = mStateManager->getBoundBuffer(GL_PIXEL_UNPACK_BUFFER); + mStateManager->bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + gl::PixelUnpackState unpack; + setImageHelper(target, level, internalFormat, size, format, type, nullptr); + mStateManager->bindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer); +} + +gl::Error TextureGL::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(CompatibleTextureTarget(mState.mTarget, target)); + + nativegl::TexSubImageFormat texSubImageFormat = + nativegl::GetTexSubImageFormat(mFunctions, mWorkarounds, format, type); + + ASSERT(mLevelInfo[level].lumaWorkaround.enabled == + GetLevelInfo(format, texSubImageFormat.format).lumaWorkaround.enabled); + + mStateManager->bindTexture(mState.mTarget, mTextureID); + if (mWorkarounds.unpackOverlappingRowsSeparatelyUnpackBuffer && unpack.pixelBuffer.get() && + unpack.rowLength != 0 && unpack.rowLength < area.width) + { + return setSubImageRowByRowWorkaround(target, level, area, format, type, unpack, pixels); + } + + if (mWorkarounds.unpackLastRowSeparatelyForPaddingInclusion) + { + gl::Extents size(area.width, area.height, area.depth); + + bool apply; + ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, unpack, format, type, + UseTexImage3D(mState.mTarget), pixels), + apply); + + // The driver will think the pixel buffer doesn't have enough data, work around this bug + // by uploading the last row (and last level if 3D) separately. + if (apply) + { + return setSubImagePaddingWorkaround(target, level, area, format, type, unpack, pixels); + } + } + + if (UseTexImage2D(mState.mTarget)) + { + ASSERT(area.z == 0 && area.depth == 1); + mFunctions->texSubImage2D(target, static_cast<GLint>(level), area.x, area.y, area.width, + area.height, texSubImageFormat.format, texSubImageFormat.type, + pixels); + } + else + { + ASSERT(UseTexImage3D(mState.mTarget)); + mFunctions->texSubImage3D(target, static_cast<GLint>(level), area.x, area.y, area.z, + area.width, area.height, area.depth, texSubImageFormat.format, + texSubImageFormat.type, pixels); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureGL::setSubImageRowByRowWorkaround(GLenum target, + size_t level, + const gl::Box &area, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) +{ + gl::PixelUnpackState directUnpack; + directUnpack.pixelBuffer = unpack.pixelBuffer; + directUnpack.alignment = 1; + mStateManager->setPixelUnpackState(directUnpack); + directUnpack.pixelBuffer.set(nullptr); + + const gl::InternalFormat &glFormat = + gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type)); + GLuint rowBytes = 0; + ANGLE_TRY_RESULT(glFormat.computeRowPitch(area.width, unpack.alignment, unpack.rowLength), + rowBytes); + GLuint imageBytes = 0; + ANGLE_TRY_RESULT(gl::InternalFormat::computeDepthPitch(area.height, unpack.imageHeight, rowBytes), + imageBytes); + bool useTexImage3D = UseTexImage3D(mState.mTarget); + GLuint skipBytes = 0; + ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack, useTexImage3D), + skipBytes); + + const uint8_t *pixelsWithSkip = pixels + skipBytes; + if (useTexImage3D) + { + for (GLint image = 0; image < area.depth; ++image) + { + GLint imageByteOffset = image * imageBytes; + for (GLint row = 0; row < area.height; ++row) + { + GLint byteOffset = imageByteOffset + row * rowBytes; + const GLubyte *rowPixels = pixelsWithSkip + byteOffset; + mFunctions->texSubImage3D(target, static_cast<GLint>(level), area.x, row + area.y, + image + area.z, area.width, 1, 1, format, type, + rowPixels); + } + } + } + else + { + ASSERT(UseTexImage2D(mState.mTarget)); + for (GLint row = 0; row < area.height; ++row) + { + GLint byteOffset = row * rowBytes; + const GLubyte *rowPixels = pixelsWithSkip + byteOffset; + mFunctions->texSubImage2D(target, static_cast<GLint>(level), area.x, row + area.y, + area.width, 1, format, type, rowPixels); + } + } + return gl::NoError(); +} + +gl::Error TextureGL::setSubImagePaddingWorkaround(GLenum target, + size_t level, + const gl::Box &area, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) +{ + const gl::InternalFormat &glFormat = + gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type)); + GLuint rowBytes = 0; + ANGLE_TRY_RESULT(glFormat.computeRowPitch(area.width, unpack.alignment, unpack.rowLength), + rowBytes); + GLuint imageBytes = 0; + ANGLE_TRY_RESULT(gl::InternalFormat::computeDepthPitch(area.height, unpack.imageHeight, rowBytes), + imageBytes); + bool useTexImage3D = UseTexImage3D(mState.mTarget); + GLuint skipBytes = 0; + ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack, useTexImage3D), + skipBytes); + + gl::PixelUnpackState directUnpack; + directUnpack.pixelBuffer = unpack.pixelBuffer; + directUnpack.alignment = 1; + + if (useTexImage3D) + { + // Upload all but the last slice + if (area.depth > 1) + { + mFunctions->texSubImage3D(target, static_cast<GLint>(level), area.x, area.y, area.z, + area.width, area.height, area.depth - 1, format, type, + pixels); + } + + // Upload the last slice but its last row + if (area.height > 1) + { + // Do not include skipBytes in the last image pixel start offset as it will be done by + // the driver + GLint lastImageOffset = (area.depth - 1) * imageBytes; + const GLubyte *lastImagePixels = pixels + lastImageOffset; + mFunctions->texSubImage3D(target, static_cast<GLint>(level), area.x, area.y, + area.z + area.depth - 1, area.width, area.height - 1, 1, + format, type, lastImagePixels); + } + + // Upload the last row of the last slice "manually" + mStateManager->setPixelUnpackState(directUnpack); + + GLint lastRowOffset = + skipBytes + (area.depth - 1) * imageBytes + (area.height - 1) * rowBytes; + const GLubyte *lastRowPixels = pixels + lastRowOffset; + mFunctions->texSubImage3D(target, static_cast<GLint>(level), area.x, + area.y + area.height - 1, area.z + area.depth - 1, area.width, 1, + 1, format, type, lastRowPixels); + } + else + { + ASSERT(UseTexImage2D(mState.mTarget)); + + // Upload all but the last row + if (area.height > 1) + { + mFunctions->texSubImage2D(target, static_cast<GLint>(level), area.x, area.y, area.width, + area.height - 1, format, type, pixels); + } + + // Upload the last row "manually" + mStateManager->setPixelUnpackState(directUnpack); + + GLint lastRowOffset = skipBytes + (area.height - 1) * rowBytes; + const GLubyte *lastRowPixels = pixels + lastRowOffset; + mFunctions->texSubImage2D(target, static_cast<GLint>(level), area.x, + area.y + area.height - 1, area.width, 1, format, type, + lastRowPixels); + } + + directUnpack.pixelBuffer.set(nullptr); + + return gl::NoError(); +} + +gl::Error TextureGL::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) +{ + ASSERT(CompatibleTextureTarget(mState.mTarget, target)); + + nativegl::CompressedTexImageFormat compressedTexImageFormat = + nativegl::GetCompressedTexImageFormat(mFunctions, mWorkarounds, internalFormat); + + mStateManager->bindTexture(mState.mTarget, mTextureID); + if (UseTexImage2D(mState.mTarget)) + { + ASSERT(size.depth == 1); + mFunctions->compressedTexImage2D(target, static_cast<GLint>(level), + compressedTexImageFormat.internalFormat, size.width, + size.height, 0, static_cast<GLsizei>(imageSize), pixels); + } + else if (UseTexImage3D(mState.mTarget)) + { + mFunctions->compressedTexImage3D( + target, static_cast<GLint>(level), compressedTexImageFormat.internalFormat, size.width, + size.height, size.depth, 0, static_cast<GLsizei>(imageSize), pixels); + } + else + { + UNREACHABLE(); + } + + setLevelInfo(level, 1, GetLevelInfo(internalFormat, compressedTexImageFormat.internalFormat)); + ASSERT(!mLevelInfo[level].lumaWorkaround.enabled); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureGL::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) +{ + ASSERT(CompatibleTextureTarget(mState.mTarget, target)); + + nativegl::CompressedTexSubImageFormat compressedTexSubImageFormat = + nativegl::GetCompressedSubTexImageFormat(mFunctions, mWorkarounds, format); + + mStateManager->bindTexture(mState.mTarget, mTextureID); + if (UseTexImage2D(mState.mTarget)) + { + ASSERT(area.z == 0 && area.depth == 1); + mFunctions->compressedTexSubImage2D( + target, static_cast<GLint>(level), area.x, area.y, area.width, area.height, + compressedTexSubImageFormat.format, static_cast<GLsizei>(imageSize), pixels); + } + else if (UseTexImage3D(mState.mTarget)) + { + mFunctions->compressedTexSubImage3D(target, static_cast<GLint>(level), area.x, area.y, + area.z, area.width, area.height, area.depth, + compressedTexSubImageFormat.format, + static_cast<GLsizei>(imageSize), pixels); + } + else + { + UNREACHABLE(); + } + + ASSERT(!mLevelInfo[level].lumaWorkaround.enabled && + !GetLevelInfo(format, compressedTexSubImageFormat.format).lumaWorkaround.enabled); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureGL::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) +{ + nativegl::CopyTexImageImageFormat copyTexImageFormat = nativegl::GetCopyTexImageImageFormat( + mFunctions, mWorkarounds, internalFormat, source->getImplementationColorReadType()); + + LevelInfoGL levelInfo = GetLevelInfo(internalFormat, copyTexImageFormat.internalFormat); + if (levelInfo.lumaWorkaround.enabled) + { + gl::Error error = mBlitter->copyImageToLUMAWorkaroundTexture( + mTextureID, mState.mTarget, target, levelInfo.sourceFormat, level, sourceArea, + copyTexImageFormat.internalFormat, source); + if (error.isError()) + { + return error; + } + } + else + { + const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source); + + mStateManager->bindTexture(mState.mTarget, mTextureID); + mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, + sourceFramebufferGL->getFramebufferID()); + + if (UseTexImage2D(mState.mTarget)) + { + mFunctions->copyTexImage2D(target, static_cast<GLint>(level), + copyTexImageFormat.internalFormat, sourceArea.x, + sourceArea.y, sourceArea.width, sourceArea.height, 0); + } + else + { + UNREACHABLE(); + } + } + + setLevelInfo(level, 1, levelInfo); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureGL::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) +{ + const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source); + + mStateManager->bindTexture(mState.mTarget, mTextureID); + mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID()); + + const LevelInfoGL &levelInfo = mLevelInfo[level]; + if (levelInfo.lumaWorkaround.enabled) + { + gl::Error error = mBlitter->copySubImageToLUMAWorkaroundTexture( + mTextureID, mState.mTarget, target, levelInfo.sourceFormat, level, destOffset, + sourceArea, source); + if (error.isError()) + { + return error; + } + } + else + { + if (UseTexImage2D(mState.mTarget)) + { + ASSERT(destOffset.z == 0); + mFunctions->copyTexSubImage2D(target, static_cast<GLint>(level), destOffset.x, + destOffset.y, sourceArea.x, sourceArea.y, + sourceArea.width, sourceArea.height); + } + else if (UseTexImage3D(mState.mTarget)) + { + mFunctions->copyTexSubImage3D(target, static_cast<GLint>(level), destOffset.x, + destOffset.y, destOffset.z, sourceArea.x, sourceArea.y, + sourceArea.width, sourceArea.height); + } + else + { + UNREACHABLE(); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureGL::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) +{ + // TODO: emulate texture storage with TexImage calls if on GL version <4.2 or the + // ARB_texture_storage extension is not available. + + nativegl::TexStorageFormat texStorageFormat = + nativegl::GetTexStorageFormat(mFunctions, mWorkarounds, internalFormat); + + mStateManager->bindTexture(mState.mTarget, mTextureID); + if (UseTexImage2D(mState.mTarget)) + { + ASSERT(size.depth == 1); + if (mFunctions->texStorage2D) + { + mFunctions->texStorage2D(target, static_cast<GLsizei>(levels), + texStorageFormat.internalFormat, size.width, size.height); + } + else + { + // Make sure no pixel unpack buffer is bound + mStateManager->bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); + + // Internal format must be sized + ASSERT(internalFormatInfo.pixelBytes != 0); + + for (size_t level = 0; level < levels; level++) + { + gl::Extents levelSize(std::max(size.width >> level, 1), + std::max(size.height >> level, 1), + 1); + + if (mState.mTarget == GL_TEXTURE_2D) + { + if (internalFormatInfo.compressed) + { + GLuint dataSize = 0; + ANGLE_TRY_RESULT(internalFormatInfo.computeCompressedImageSize(levelSize), + dataSize); + mFunctions->compressedTexImage2D(target, static_cast<GLint>(level), + texStorageFormat.internalFormat, + levelSize.width, levelSize.height, 0, + static_cast<GLsizei>(dataSize), nullptr); + } + else + { + mFunctions->texImage2D(target, static_cast<GLint>(level), + texStorageFormat.internalFormat, levelSize.width, + levelSize.height, 0, internalFormatInfo.format, + internalFormatInfo.type, nullptr); + } + } + else if (mState.mTarget == GL_TEXTURE_CUBE_MAP) + { + for (GLenum face = gl::FirstCubeMapTextureTarget; face <= gl::LastCubeMapTextureTarget; face++) + { + if (internalFormatInfo.compressed) + { + GLuint dataSize = 0; + ANGLE_TRY_RESULT(internalFormatInfo.computeCompressedImageSize( + levelSize), + dataSize); + mFunctions->compressedTexImage2D( + face, static_cast<GLint>(level), texStorageFormat.internalFormat, + levelSize.width, levelSize.height, 0, + static_cast<GLsizei>(dataSize), nullptr); + } + else + { + mFunctions->texImage2D(face, static_cast<GLint>(level), + texStorageFormat.internalFormat, levelSize.width, + levelSize.height, 0, internalFormatInfo.format, + internalFormatInfo.type, nullptr); + } + } + } + else + { + UNREACHABLE(); + } + } + } + } + else if (UseTexImage3D(mState.mTarget)) + { + if (mFunctions->texStorage3D) + { + mFunctions->texStorage3D(target, static_cast<GLsizei>(levels), + texStorageFormat.internalFormat, size.width, size.height, + size.depth); + } + else + { + // Make sure no pixel unpack buffer is bound + mStateManager->bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); + + // Internal format must be sized + ASSERT(internalFormatInfo.pixelBytes != 0); + + for (GLsizei i = 0; i < static_cast<GLsizei>(levels); i++) + { + gl::Extents levelSize( + std::max(size.width >> i, 1), std::max(size.height >> i, 1), + mState.mTarget == GL_TEXTURE_3D ? std::max(size.depth >> i, 1) : size.depth); + + if (internalFormatInfo.compressed) + { + GLuint dataSize = 0; + ANGLE_TRY_RESULT( + internalFormatInfo.computeCompressedImageSize(levelSize), + dataSize); + mFunctions->compressedTexImage3D(target, i, texStorageFormat.internalFormat, + levelSize.width, levelSize.height, + levelSize.depth, 0, + static_cast<GLsizei>(dataSize), nullptr); + } + else + { + mFunctions->texImage3D(target, i, texStorageFormat.internalFormat, + levelSize.width, levelSize.height, levelSize.depth, 0, + internalFormatInfo.format, internalFormatInfo.type, + nullptr); + } + } + } + } + else + { + UNREACHABLE(); + } + + setLevelInfo(0, levels, GetLevelInfo(internalFormat, texStorageFormat.internalFormat)); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureGL::setImageExternal(GLenum target, + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) +{ + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureGL::generateMipmap() +{ + mStateManager->bindTexture(mState.mTarget, mTextureID); + mFunctions->generateMipmap(mState.mTarget); + + const GLuint effectiveBaseLevel = mState.getEffectiveBaseLevel(); + const GLuint maxLevel = mState.getMipmapMaxLevel(); + + ASSERT(maxLevel < mLevelInfo.size()); + + setLevelInfo(effectiveBaseLevel, maxLevel - effectiveBaseLevel, mLevelInfo[effectiveBaseLevel]); + + return gl::Error(GL_NO_ERROR); +} + +void TextureGL::bindTexImage(egl::Surface *surface) +{ + ASSERT(mState.mTarget == GL_TEXTURE_2D); + + // Make sure this texture is bound + mStateManager->bindTexture(mState.mTarget, mTextureID); + + setLevelInfo(0, 1, LevelInfoGL()); +} + +void TextureGL::releaseTexImage() +{ + // Not all Surface implementations reset the size of mip 0 when releasing, do it manually + ASSERT(mState.mTarget == GL_TEXTURE_2D); + + mStateManager->bindTexture(mState.mTarget, mTextureID); + if (UseTexImage2D(mState.mTarget)) + { + mFunctions->texImage2D(mState.mTarget, 0, GL_RGBA, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, + nullptr); + } + else + { + UNREACHABLE(); + } +} + +gl::Error TextureGL::setEGLImageTarget(GLenum target, egl::Image *image) +{ + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION); +} + +void TextureGL::syncState(const gl::Texture::DirtyBits &dirtyBits) +{ + if (dirtyBits.none() && mLocalDirtyBits.none()) + { + return; + } + + mStateManager->bindTexture(mState.mTarget, mTextureID); + + if (dirtyBits[gl::Texture::DIRTY_BIT_BASE_LEVEL] || dirtyBits[gl::Texture::DIRTY_BIT_MAX_LEVEL]) + { + // Don't know if the previous base level was using any workarounds, always re-sync the + // workaround dirty bits + mLocalDirtyBits |= GetLevelWorkaroundDirtyBits(); + } + + for (auto dirtyBit : angle::IterateBitSet(dirtyBits | mLocalDirtyBits)) + { + switch (dirtyBit) + { + case gl::Texture::DIRTY_BIT_MIN_FILTER: + mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_MIN_FILTER, + mState.getSamplerState().minFilter); + break; + case gl::Texture::DIRTY_BIT_MAG_FILTER: + mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_MAG_FILTER, + mState.getSamplerState().magFilter); + break; + case gl::Texture::DIRTY_BIT_WRAP_S: + mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_WRAP_S, + mState.getSamplerState().wrapS); + break; + case gl::Texture::DIRTY_BIT_WRAP_T: + mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_WRAP_T, + mState.getSamplerState().wrapT); + break; + case gl::Texture::DIRTY_BIT_WRAP_R: + mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_WRAP_R, + mState.getSamplerState().wrapR); + break; + case gl::Texture::DIRTY_BIT_MAX_ANISOTROPY: + mFunctions->texParameterf(mState.mTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, + mState.getSamplerState().maxAnisotropy); + break; + case gl::Texture::DIRTY_BIT_MIN_LOD: + mFunctions->texParameterf(mState.mTarget, GL_TEXTURE_MIN_LOD, + mState.getSamplerState().minLod); + break; + case gl::Texture::DIRTY_BIT_MAX_LOD: + mFunctions->texParameterf(mState.mTarget, GL_TEXTURE_MAX_LOD, + mState.getSamplerState().maxLod); + break; + case gl::Texture::DIRTY_BIT_COMPARE_MODE: + mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_COMPARE_MODE, + mState.getSamplerState().compareMode); + break; + case gl::Texture::DIRTY_BIT_COMPARE_FUNC: + mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_COMPARE_FUNC, + mState.getSamplerState().compareFunc); + break; + case gl::Texture::DIRTY_BIT_SRGB_DECODE: + mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_SRGB_DECODE_EXT, + mState.getSamplerState().sRGBDecode); + break; + + // Texture state + case gl::Texture::DIRTY_BIT_SWIZZLE_RED: + syncTextureStateSwizzle(mFunctions, GL_TEXTURE_SWIZZLE_R, + mState.getSwizzleState().swizzleRed); + break; + case gl::Texture::DIRTY_BIT_SWIZZLE_GREEN: + syncTextureStateSwizzle(mFunctions, GL_TEXTURE_SWIZZLE_G, + mState.getSwizzleState().swizzleGreen); + break; + case gl::Texture::DIRTY_BIT_SWIZZLE_BLUE: + syncTextureStateSwizzle(mFunctions, GL_TEXTURE_SWIZZLE_B, + mState.getSwizzleState().swizzleBlue); + break; + case gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA: + syncTextureStateSwizzle(mFunctions, GL_TEXTURE_SWIZZLE_A, + mState.getSwizzleState().swizzleAlpha); + break; + case gl::Texture::DIRTY_BIT_BASE_LEVEL: + mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_BASE_LEVEL, + mState.getEffectiveBaseLevel()); + break; + case gl::Texture::DIRTY_BIT_MAX_LEVEL: + mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_MAX_LEVEL, + mState.getEffectiveMaxLevel()); + break; + case gl::Texture::DIRTY_BIT_USAGE: + break; + + default: + UNREACHABLE(); + } + } + + mLocalDirtyBits.reset(); +} + +bool TextureGL::hasAnyDirtyBit() const +{ + return mLocalDirtyBits.any(); +} + +void TextureGL::syncTextureStateSwizzle(const FunctionsGL *functions, GLenum name, GLenum value) +{ + const LevelInfoGL &levelInfo = mLevelInfo[mState.getEffectiveBaseLevel()]; + GLenum resultSwizzle = value; + if (levelInfo.lumaWorkaround.enabled || levelInfo.depthStencilWorkaround) + { + if (levelInfo.lumaWorkaround.enabled) + { + switch (value) + { + case GL_RED: + case GL_GREEN: + case GL_BLUE: + if (levelInfo.sourceFormat == GL_LUMINANCE || + levelInfo.sourceFormat == GL_LUMINANCE_ALPHA) + { + // Texture is backed by a RED or RG texture, point all color channels at the red + // channel. + ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RED || + levelInfo.lumaWorkaround.workaroundFormat == GL_RG); + resultSwizzle = GL_RED; + } + else if (levelInfo.sourceFormat == GL_ALPHA) + { + // Color channels are not supposed to exist, make them always sample 0. + resultSwizzle = GL_ZERO; + } + else + { + UNREACHABLE(); + } + break; + + case GL_ALPHA: + if (levelInfo.sourceFormat == GL_LUMINANCE) + { + // Alpha channel is not supposed to exist, make it always sample 1. + resultSwizzle = GL_ONE; + } + else if (levelInfo.sourceFormat == GL_ALPHA) + { + // Texture is backed by a RED texture, point the alpha channel at the red + // channel. + ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RED); + resultSwizzle = GL_RED; + } + else if (levelInfo.sourceFormat == GL_LUMINANCE_ALPHA) + { + // Texture is backed by an RG texture, point the alpha channel at the green + // channel. + ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RG); + resultSwizzle = GL_GREEN; + } + else + { + UNREACHABLE(); + } + break; + + case GL_ZERO: + case GL_ONE: + // Don't modify the swizzle state when requesting ZERO or ONE. + resultSwizzle = value; + break; + + default: + UNREACHABLE(); + break; + } + } + else if (levelInfo.depthStencilWorkaround) + { + switch (value) + { + case GL_RED: + // Don't modify the swizzle state when requesting the red channel. + resultSwizzle = value; + break; + + case GL_GREEN: + case GL_BLUE: + // Depth textures should sample 0 from the green and blue channels. + resultSwizzle = GL_ZERO; + break; + + case GL_ALPHA: + // Depth textures should sample 1 from the alpha channel. + resultSwizzle = GL_ONE; + break; + + case GL_ZERO: + case GL_ONE: + // Don't modify the swizzle state when requesting ZERO or ONE. + resultSwizzle = value; + break; + + default: + UNREACHABLE(); + break; + } + } + else + { + UNREACHABLE(); + } + + } + + functions->texParameteri(mState.mTarget, name, resultSwizzle); +} + +void TextureGL::setLevelInfo(size_t level, size_t levelCount, const LevelInfoGL &levelInfo) +{ + ASSERT(levelCount > 0 && level + levelCount < mLevelInfo.size()); + + GLuint baseLevel = mState.getEffectiveBaseLevel(); + bool needsResync = level <= baseLevel && level + levelCount >= baseLevel && + (levelInfo.depthStencilWorkaround || levelInfo.lumaWorkaround.enabled); + if (needsResync) + { + mLocalDirtyBits |= GetLevelWorkaroundDirtyBits(); + } + + for (size_t i = level; i < level + levelCount; i++) + { + mLevelInfo[i] = levelInfo; + } +} + +GLuint TextureGL::getTextureID() const +{ + return mTextureID; +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/TextureGL.h b/gfx/angle/src/libANGLE/renderer/gl/TextureGL.h new file mode 100755 index 000000000..068284c5b --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/TextureGL.h @@ -0,0 +1,145 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureGL.h: Defines the class interface for TextureGL. + +#ifndef LIBANGLE_RENDERER_GL_TEXTUREGL_H_ +#define LIBANGLE_RENDERER_GL_TEXTUREGL_H_ + +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/TextureImpl.h" +#include "libANGLE/Texture.h" + +namespace rx +{ + +class BlitGL; +class FunctionsGL; +class StateManagerGL; +struct WorkaroundsGL; + +struct LUMAWorkaroundGL +{ + bool enabled; + GLenum workaroundFormat; + + LUMAWorkaroundGL(); + LUMAWorkaroundGL(bool enabled, GLenum workaroundFormat); +}; + +// Structure containing information about format and workarounds for each mip level of the +// TextureGL. +struct LevelInfoGL +{ + // Format of the data used in this mip level. + GLenum sourceFormat; + + // If this mip level requires sampler-state re-writing so that only a red channel is exposed. + bool depthStencilWorkaround; + + // Information about luminance alpha texture workarounds in the core profile. + LUMAWorkaroundGL lumaWorkaround; + + LevelInfoGL(); + LevelInfoGL(GLenum sourceFormat, + bool depthStencilWorkaround, + const LUMAWorkaroundGL &lumaWorkaround); +}; + +class TextureGL : public TextureImpl +{ + public: + TextureGL(const gl::TextureState &state, + const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + StateManagerGL *stateManager, + BlitGL *blitter); + ~TextureGL() override; + + gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; + gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; + + gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) override; + gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override; + + gl::Error setImageExternal(GLenum target, + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) override; + + gl::Error generateMipmap() override; + + void bindTexImage(egl::Surface *surface) override; + void releaseTexImage() override; + + gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override; + + GLuint getTextureID() const; + + void setBaseLevel(GLuint) override {} + + void syncState(const gl::Texture::DirtyBits &dirtyBits) override; + bool hasAnyDirtyBit() const; + + private: + void setImageHelper(GLenum target, + size_t level, + GLenum internalFormat, + const gl::Extents &size, + GLenum format, + GLenum type, + const uint8_t *pixels); + void reserveTexImageToBeFilled(GLenum target, + size_t level, + GLenum internalFormat, + const gl::Extents &size, + GLenum format, + GLenum type); + gl::Error setSubImageRowByRowWorkaround(GLenum target, + size_t level, + const gl::Box &area, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels); + + gl::Error setSubImagePaddingWorkaround(GLenum target, + size_t level, + const gl::Box &area, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels); + + void syncTextureStateSwizzle(const FunctionsGL *functions, GLenum name, GLenum value); + + void setLevelInfo(size_t level, size_t levelCount, const LevelInfoGL &levelInfo); + + const FunctionsGL *mFunctions; + const WorkaroundsGL &mWorkarounds; + StateManagerGL *mStateManager; + BlitGL *mBlitter; + + std::vector<LevelInfoGL> mLevelInfo; + gl::Texture::DirtyBits mLocalDirtyBits; + + mutable gl::TextureState mAppliedTextureState; + GLuint mTextureID; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_TEXTUREGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp new file mode 100755 index 000000000..ae75a0f47 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp @@ -0,0 +1,131 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TransformFeedbackGL.cpp: Implements the class methods for TransformFeedbackGL. + +#include "libANGLE/renderer/gl/TransformFeedbackGL.h" + +#include "common/debug.h" +#include "libANGLE/ContextState.h" +#include "libANGLE/renderer/gl/BufferGL.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" + +namespace rx +{ + +TransformFeedbackGL::TransformFeedbackGL(const gl::TransformFeedbackState &state, + const FunctionsGL *functions, + StateManagerGL *stateManager) + : TransformFeedbackImpl(state), + mFunctions(functions), + mStateManager(stateManager), + mTransformFeedbackID(0), + mIsActive(false), + mIsPaused(false) +{ + mFunctions->genTransformFeedbacks(1, &mTransformFeedbackID); +} + +TransformFeedbackGL::~TransformFeedbackGL() +{ + mStateManager->deleteTransformFeedback(mTransformFeedbackID); + mTransformFeedbackID = 0; +} + +void TransformFeedbackGL::begin(GLenum primitiveMode) +{ + // Do not begin directly, StateManagerGL will handle beginning and resuming transform feedback. +} + +void TransformFeedbackGL::end() +{ + syncActiveState(false, GL_NONE); +} + +void TransformFeedbackGL::pause() +{ + syncPausedState(true); +} + +void TransformFeedbackGL::resume() +{ + // Do not resume directly, StateManagerGL will handle beginning and resuming transform feedback. +} + +void TransformFeedbackGL::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) +{ +} + +void TransformFeedbackGL::bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) +{ + // Directly bind buffer (not through the StateManager methods) because the buffer bindings are + // tracked per transform feedback object + mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID); + if (binding.get() != nullptr) + { + const BufferGL *bufferGL = GetImplAs<BufferGL>(binding.get()); + if (binding.getSize() != 0) + { + mFunctions->bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index), + bufferGL->getBufferID(), binding.getOffset(), + binding.getSize()); + } + else + { + mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index), + bufferGL->getBufferID()); + } + } + else + { + mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index), 0); + } +} + +GLuint TransformFeedbackGL::getTransformFeedbackID() const +{ + return mTransformFeedbackID; +} + +void TransformFeedbackGL::syncActiveState(bool active, GLenum primitiveMode) const +{ + if (mIsActive != active) + { + mIsActive = active; + mIsPaused = false; + + mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID); + if (mIsActive) + { + mFunctions->beginTransformFeedback(primitiveMode); + } + else + { + mFunctions->endTransformFeedback(); + } + } +} + +void TransformFeedbackGL::syncPausedState(bool paused) const +{ + if (mIsActive && mIsPaused != paused) + { + mIsPaused = paused; + + mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID); + if (mIsPaused) + { + mFunctions->pauseTransformFeedback(); + } + else + { + mFunctions->resumeTransformFeedback(); + } + } +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h b/gfx/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h new file mode 100755 index 000000000..f84edc0b7 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h @@ -0,0 +1,53 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TransformFeedbackGL.h: Defines the class interface for TransformFeedbackGL. + +#ifndef LIBANGLE_RENDERER_GL_TRANSFORMFEEDBACKGL_H_ +#define LIBANGLE_RENDERER_GL_TRANSFORMFEEDBACKGL_H_ + +#include "libANGLE/renderer/TransformFeedbackImpl.h" + +namespace rx +{ + +class FunctionsGL; +class StateManagerGL; + +class TransformFeedbackGL : public TransformFeedbackImpl +{ + public: + TransformFeedbackGL(const gl::TransformFeedbackState &state, + const FunctionsGL *functions, + StateManagerGL *stateManager); + ~TransformFeedbackGL() override; + + void begin(GLenum primitiveMode) override; + void end() override; + void pause() override; + void resume() override; + + void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override; + void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override; + + GLuint getTransformFeedbackID() const; + + void syncActiveState(bool active, GLenum primitiveMode) const; + void syncPausedState(bool paused) const; + + private: + const FunctionsGL *mFunctions; + StateManagerGL *mStateManager; + + GLuint mTransformFeedbackID; + + mutable bool mIsActive; + mutable bool mIsPaused; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_TRANSFORMFEEDBACKGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp new file mode 100755 index 000000000..1e7fa030f --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp @@ -0,0 +1,499 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexArrayGL.cpp: Implements the class methods for VertexArrayGL. + +#include "libANGLE/renderer/gl/VertexArrayGL.h" + +#include "common/BitSetIterator.h" +#include "common/debug.h" +#include "common/mathutil.h" +#include "common/utilities.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/gl/BufferGL.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/renderergl_utils.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" + +using namespace gl; + +namespace rx +{ +namespace +{ +bool AttributeNeedsStreaming(const VertexAttribute &attribute) +{ + return (attribute.enabled && attribute.buffer.get() == nullptr); +} + +} // anonymous namespace + +VertexArrayGL::VertexArrayGL(const VertexArrayState &state, + const FunctionsGL *functions, + StateManagerGL *stateManager) + : VertexArrayImpl(state), + mFunctions(functions), + mStateManager(stateManager), + mVertexArrayID(0), + mAppliedElementArrayBuffer(), + mStreamingElementArrayBufferSize(0), + mStreamingElementArrayBuffer(0), + mStreamingArrayBufferSize(0), + mStreamingArrayBuffer(0) +{ + ASSERT(mFunctions); + ASSERT(mStateManager); + mFunctions->genVertexArrays(1, &mVertexArrayID); + + // Set the cached vertex attribute array size + GLint maxVertexAttribs = 0; + mFunctions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs); + mAppliedAttributes.resize(maxVertexAttribs); +} + +VertexArrayGL::~VertexArrayGL() +{ + mStateManager->deleteVertexArray(mVertexArrayID); + mVertexArrayID = 0; + + mStateManager->deleteBuffer(mStreamingElementArrayBuffer); + mStreamingElementArrayBufferSize = 0; + mStreamingElementArrayBuffer = 0; + + mStateManager->deleteBuffer(mStreamingArrayBuffer); + mStreamingArrayBufferSize = 0; + mStreamingArrayBuffer = 0; + + mAppliedElementArrayBuffer.set(nullptr); + for (size_t idx = 0; idx < mAppliedAttributes.size(); idx++) + { + mAppliedAttributes[idx].buffer.set(nullptr); + } +} + +gl::Error VertexArrayGL::syncDrawArraysState(const gl::AttributesMask &activeAttributesMask, + GLint first, + GLsizei count, + GLsizei instanceCount) const +{ + return syncDrawState(activeAttributesMask, first, count, GL_NONE, nullptr, instanceCount, false, + nullptr); +} + +gl::Error VertexArrayGL::syncDrawElementsState(const gl::AttributesMask &activeAttributesMask, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instanceCount, + bool primitiveRestartEnabled, + const GLvoid **outIndices) const +{ + return syncDrawState(activeAttributesMask, 0, count, type, indices, instanceCount, + primitiveRestartEnabled, outIndices); +} + +gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttributesMask, + GLint first, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instanceCount, + bool primitiveRestartEnabled, + const GLvoid **outIndices) const +{ + mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID()); + + // Check if any attributes need to be streamed, determines if the index range needs to be computed + bool attributesNeedStreaming = mAttributesNeedStreaming.any(); + + // Determine if an index buffer needs to be streamed and the range of vertices that need to be copied + IndexRange indexRange; + if (type != GL_NONE) + { + Error error = syncIndexData(count, type, indices, primitiveRestartEnabled, + attributesNeedStreaming, &indexRange, outIndices); + if (error.isError()) + { + return error; + } + } + else + { + // Not an indexed call, set the range to [first, first + count - 1] + indexRange.start = first; + indexRange.end = first + count - 1; + } + + if (attributesNeedStreaming) + { + Error error = streamAttributes(activeAttributesMask, instanceCount, indexRange); + if (error.isError()) + { + return error; + } + } + + return Error(GL_NO_ERROR); +} + +Error VertexArrayGL::syncIndexData(GLsizei count, + GLenum type, + const GLvoid *indices, + bool primitiveRestartEnabled, + bool attributesNeedStreaming, + IndexRange *outIndexRange, + const GLvoid **outIndices) const +{ + ASSERT(outIndices); + + gl::Buffer *elementArrayBuffer = mData.getElementArrayBuffer().get(); + + // Need to check the range of indices if attributes need to be streamed + if (elementArrayBuffer != nullptr) + { + if (elementArrayBuffer != mAppliedElementArrayBuffer.get()) + { + const BufferGL *bufferGL = GetImplAs<BufferGL>(elementArrayBuffer); + mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferGL->getBufferID()); + mAppliedElementArrayBuffer.set(elementArrayBuffer); + } + + // Only compute the index range if the attributes also need to be streamed + if (attributesNeedStreaming) + { + ptrdiff_t elementArrayBufferOffset = reinterpret_cast<ptrdiff_t>(indices); + Error error = mData.getElementArrayBuffer()->getIndexRange( + type, elementArrayBufferOffset, count, primitiveRestartEnabled, outIndexRange); + if (error.isError()) + { + return error; + } + } + + // Indices serves as an offset into the index buffer in this case, use the same value for the draw call + *outIndices = indices; + } + else + { + // Need to stream the index buffer + // TODO: if GLES, nothing needs to be streamed + + // Only compute the index range if the attributes also need to be streamed + if (attributesNeedStreaming) + { + *outIndexRange = ComputeIndexRange(type, indices, count, primitiveRestartEnabled); + } + + // Allocate the streaming element array buffer + if (mStreamingElementArrayBuffer == 0) + { + mFunctions->genBuffers(1, &mStreamingElementArrayBuffer); + mStreamingElementArrayBufferSize = 0; + } + + mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mStreamingElementArrayBuffer); + mAppliedElementArrayBuffer.set(nullptr); + + // Make sure the element array buffer is large enough + const Type &indexTypeInfo = GetTypeInfo(type); + size_t requiredStreamingBufferSize = indexTypeInfo.bytes * count; + if (requiredStreamingBufferSize > mStreamingElementArrayBufferSize) + { + // Copy the indices in while resizing the buffer + mFunctions->bufferData(GL_ELEMENT_ARRAY_BUFFER, requiredStreamingBufferSize, indices, GL_DYNAMIC_DRAW); + mStreamingElementArrayBufferSize = requiredStreamingBufferSize; + } + else + { + // Put the indices at the beginning of the buffer + mFunctions->bufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, requiredStreamingBufferSize, indices); + } + + // Set the index offset for the draw call to zero since the supplied index pointer is to client data + *outIndices = nullptr; + } + + return Error(GL_NO_ERROR); +} + +void VertexArrayGL::computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask, + GLsizei instanceCount, + const gl::IndexRange &indexRange, + size_t *outStreamingDataSize, + size_t *outMaxAttributeDataSize) const +{ + *outStreamingDataSize = 0; + *outMaxAttributeDataSize = 0; + + ASSERT(mAttributesNeedStreaming.any()); + + const auto &attribs = mData.getVertexAttributes(); + for (auto idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask)) + { + const auto &attrib = attribs[idx]; + ASSERT(AttributeNeedsStreaming(attrib)); + + // If streaming is going to be required, compute the size of the required buffer + // and how much slack space at the beginning of the buffer will be required by determining + // the attribute with the largest data size. + size_t typeSize = ComputeVertexAttributeTypeSize(attrib); + *outStreamingDataSize += typeSize * ComputeVertexAttributeElementCount( + attrib, indexRange.vertexCount(), instanceCount); + *outMaxAttributeDataSize = std::max(*outMaxAttributeDataSize, typeSize); + } +} + +gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttributesMask, + GLsizei instanceCount, + const gl::IndexRange &indexRange) const +{ + // Sync the vertex attribute state and track what data needs to be streamed + size_t streamingDataSize = 0; + size_t maxAttributeDataSize = 0; + + computeStreamingAttributeSizes(activeAttributesMask, instanceCount, indexRange, + &streamingDataSize, &maxAttributeDataSize); + + if (streamingDataSize == 0) + { + return gl::Error(GL_NO_ERROR); + } + + if (mStreamingArrayBuffer == 0) + { + mFunctions->genBuffers(1, &mStreamingArrayBuffer); + mStreamingArrayBufferSize = 0; + } + + // If first is greater than zero, a slack space needs to be left at the beginning of the buffer so that + // the same 'first' argument can be passed into the draw call. + const size_t bufferEmptySpace = maxAttributeDataSize * indexRange.start; + const size_t requiredBufferSize = streamingDataSize + bufferEmptySpace; + + mStateManager->bindBuffer(GL_ARRAY_BUFFER, mStreamingArrayBuffer); + if (requiredBufferSize > mStreamingArrayBufferSize) + { + mFunctions->bufferData(GL_ARRAY_BUFFER, requiredBufferSize, nullptr, GL_DYNAMIC_DRAW); + mStreamingArrayBufferSize = requiredBufferSize; + } + + // Unmapping a buffer can return GL_FALSE to indicate that the system has corrupted the data + // somehow (such as by a screen change), retry writing the data a few times and return OUT_OF_MEMORY + // if that fails. + GLboolean unmapResult = GL_FALSE; + size_t unmapRetryAttempts = 5; + while (unmapResult != GL_TRUE && --unmapRetryAttempts > 0) + { + uint8_t *bufferPointer = MapBufferRangeWithFallback(mFunctions, GL_ARRAY_BUFFER, 0, + requiredBufferSize, GL_MAP_WRITE_BIT); + size_t curBufferOffset = bufferEmptySpace; + + const auto &attribs = mData.getVertexAttributes(); + for (auto idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask)) + { + const auto &attrib = attribs[idx]; + ASSERT(AttributeNeedsStreaming(attrib)); + + const size_t streamedVertexCount = + ComputeVertexAttributeElementCount(attrib, indexRange.vertexCount(), instanceCount); + + const size_t sourceStride = ComputeVertexAttributeStride(attrib); + const size_t destStride = ComputeVertexAttributeTypeSize(attrib); + + const uint8_t *inputPointer = reinterpret_cast<const uint8_t *>(attrib.pointer); + + // Pack the data when copying it, user could have supplied a very large stride that + // would cause the buffer to be much larger than needed. + if (destStride == sourceStride) + { + // Can copy in one go, the data is packed + memcpy(bufferPointer + curBufferOffset, + inputPointer + (sourceStride * indexRange.start), + destStride * streamedVertexCount); + } + else + { + // Copy each vertex individually + for (size_t vertexIdx = 0; vertexIdx < streamedVertexCount; vertexIdx++) + { + uint8_t *out = bufferPointer + curBufferOffset + (destStride * vertexIdx); + const uint8_t *in = + inputPointer + sourceStride * (vertexIdx + indexRange.start); + memcpy(out, in, destStride); + } + } + + // Compute where the 0-index vertex would be. + const size_t vertexStartOffset = curBufferOffset - (indexRange.start * destStride); + + if (attrib.pureInteger) + { + ASSERT(!attrib.normalized); + mFunctions->vertexAttribIPointer( + static_cast<GLuint>(idx), attrib.size, attrib.type, + static_cast<GLsizei>(destStride), + reinterpret_cast<const GLvoid *>(vertexStartOffset)); + } + else + { + mFunctions->vertexAttribPointer( + static_cast<GLuint>(idx), attrib.size, attrib.type, attrib.normalized, + static_cast<GLsizei>(destStride), + reinterpret_cast<const GLvoid *>(vertexStartOffset)); + } + + curBufferOffset += destStride * streamedVertexCount; + + // Mark the applied attribute as dirty by setting an invalid size so that if it doesn't + // need to be streamed later, there is no chance that the caching will skip it. + mAppliedAttributes[idx].size = static_cast<GLuint>(-1); + } + + unmapResult = mFunctions->unmapBuffer(GL_ARRAY_BUFFER); + } + + if (unmapResult != GL_TRUE) + { + return Error(GL_OUT_OF_MEMORY, "Failed to unmap the client data streaming buffer."); + } + + return Error(GL_NO_ERROR); +} + +GLuint VertexArrayGL::getVertexArrayID() const +{ + return mVertexArrayID; +} + +GLuint VertexArrayGL::getAppliedElementArrayBufferID() const +{ + if (mAppliedElementArrayBuffer.get() == nullptr) + { + return mStreamingElementArrayBuffer; + } + + return GetImplAs<BufferGL>(mAppliedElementArrayBuffer.get())->getBufferID(); +} + +void VertexArrayGL::updateNeedsStreaming(size_t attribIndex) +{ + const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex); + mAttributesNeedStreaming.set(attribIndex, AttributeNeedsStreaming(attrib)); +} + +void VertexArrayGL::updateAttribEnabled(size_t attribIndex) +{ + const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex); + if (mAppliedAttributes[attribIndex].enabled == attrib.enabled) + { + return; + } + + updateNeedsStreaming(attribIndex); + + mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID()); + if (attrib.enabled) + { + mFunctions->enableVertexAttribArray(static_cast<GLuint>(attribIndex)); + } + else + { + mFunctions->disableVertexAttribArray(static_cast<GLuint>(attribIndex)); + } + mAppliedAttributes[attribIndex].enabled = attrib.enabled; +} + +void VertexArrayGL::updateAttribPointer(size_t attribIndex) +{ + const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex); + if (mAppliedAttributes[attribIndex] == attrib) + { + return; + } + + updateNeedsStreaming(attribIndex); + + // If we need to stream, defer the attribPointer to the draw call. + if (mAttributesNeedStreaming[attribIndex]) + { + return; + } + + mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID()); + const Buffer *arrayBuffer = attrib.buffer.get(); + if (arrayBuffer != nullptr) + { + const BufferGL *arrayBufferGL = GetImplAs<BufferGL>(arrayBuffer); + mStateManager->bindBuffer(GL_ARRAY_BUFFER, arrayBufferGL->getBufferID()); + } + else + { + mStateManager->bindBuffer(GL_ARRAY_BUFFER, 0); + } + mAppliedAttributes[attribIndex].buffer = attrib.buffer; + + if (attrib.pureInteger) + { + mFunctions->vertexAttribIPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type, + attrib.stride, attrib.pointer); + } + else + { + mFunctions->vertexAttribPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type, + attrib.normalized, attrib.stride, attrib.pointer); + } + mAppliedAttributes[attribIndex].size = attrib.size; + mAppliedAttributes[attribIndex].type = attrib.type; + mAppliedAttributes[attribIndex].normalized = attrib.normalized; + mAppliedAttributes[attribIndex].pureInteger = attrib.pureInteger; + mAppliedAttributes[attribIndex].stride = attrib.stride; + mAppliedAttributes[attribIndex].pointer = attrib.pointer; +} + +void VertexArrayGL::syncState(const VertexArray::DirtyBits &dirtyBits) +{ + for (unsigned long dirtyBit : angle::IterateBitSet(dirtyBits)) + { + if (dirtyBit == VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER) + { + // TODO(jmadill): Element array buffer bindings + } + else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED && + dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED) + { + size_t attribIndex = + static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED; + updateAttribEnabled(attribIndex); + } + else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_POINTER && + dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_POINTER) + { + size_t attribIndex = + static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_POINTER; + updateAttribPointer(attribIndex); + } + else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR && + dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_DIVISOR) + { + size_t attribIndex = + static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR; + const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex); + + if (mAppliedAttributes[attribIndex].divisor != attrib.divisor) + { + mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID()); + mFunctions->vertexAttribDivisor(static_cast<GLuint>(attribIndex), attrib.divisor); + mAppliedAttributes[attribIndex].divisor = attrib.divisor; + } + } + else + UNREACHABLE(); + } +} + +} // rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/VertexArrayGL.h b/gfx/angle/src/libANGLE/renderer/gl/VertexArrayGL.h new file mode 100755 index 000000000..261b63d91 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/VertexArrayGL.h @@ -0,0 +1,100 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexArrayGL.h: Defines the class interface for VertexArrayGL. + +#ifndef LIBANGLE_RENDERER_GL_VERTEXARRAYGL_H_ +#define LIBANGLE_RENDERER_GL_VERTEXARRAYGL_H_ + +#include "libANGLE/renderer/VertexArrayImpl.h" + +namespace rx +{ + +class FunctionsGL; +class StateManagerGL; + +class VertexArrayGL : public VertexArrayImpl +{ + public: + VertexArrayGL(const gl::VertexArrayState &data, + const FunctionsGL *functions, + StateManagerGL *stateManager); + ~VertexArrayGL() override; + + gl::Error syncDrawArraysState(const gl::AttributesMask &activeAttributesMask, + GLint first, + GLsizei count, + GLsizei instanceCount) const; + gl::Error syncDrawElementsState(const gl::AttributesMask &activeAttributesMask, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instanceCount, + bool primitiveRestartEnabled, + const GLvoid **outIndices) const; + + GLuint getVertexArrayID() const; + GLuint getAppliedElementArrayBufferID() const; + + void syncState(const gl::VertexArray::DirtyBits &dirtyBits) override; + + private: + gl::Error syncDrawState(const gl::AttributesMask &activeAttributesMask, + GLint first, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instanceCount, + bool primitiveRestartEnabled, + const GLvoid **outIndices) const; + + // Apply index data, only sets outIndexRange if attributesNeedStreaming is true + gl::Error syncIndexData(GLsizei count, + GLenum type, + const GLvoid *indices, + bool primitiveRestartEnabled, + bool attributesNeedStreaming, + gl::IndexRange *outIndexRange, + const GLvoid **outIndices) const; + + // Returns the amount of space needed to stream all attributes that need streaming + // and the data size of the largest attribute + void computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask, + GLsizei instanceCount, + const gl::IndexRange &indexRange, + size_t *outStreamingDataSize, + size_t *outMaxAttributeDataSize) const; + + // Stream attributes that have client data + gl::Error streamAttributes(const gl::AttributesMask &activeAttributesMask, + GLsizei instanceCount, + const gl::IndexRange &indexRange) const; + + void updateNeedsStreaming(size_t attribIndex); + void updateAttribEnabled(size_t attribIndex); + void updateAttribPointer(size_t attribIndex); + + const FunctionsGL *mFunctions; + StateManagerGL *mStateManager; + + GLuint mVertexArrayID; + + mutable BindingPointer<gl::Buffer> mAppliedElementArrayBuffer; + mutable std::vector<gl::VertexAttribute> mAppliedAttributes; + + mutable size_t mStreamingElementArrayBufferSize; + mutable GLuint mStreamingElementArrayBuffer; + + mutable size_t mStreamingArrayBufferSize; + mutable GLuint mStreamingArrayBuffer; + + gl::AttributesMask mAttributesNeedStreaming; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_VERTEXARRAYGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h b/gfx/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h new file mode 100755 index 000000000..105f94089 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h @@ -0,0 +1,126 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// WorkaroundsGL.h: Workarounds for GL driver bugs and other issues. + +#ifndef LIBANGLE_RENDERER_GL_WORKAROUNDSGL_H_ +#define LIBANGLE_RENDERER_GL_WORKAROUNDSGL_H_ + +namespace rx +{ + +struct WorkaroundsGL +{ + WorkaroundsGL() + : avoid1BitAlphaTextureFormats(false), + rgba4IsNotSupportedForColorRendering(false), + doesSRGBClearsOnLinearFramebufferAttachments(false), + doWhileGLSLCausesGPUHang(false), + finishDoesNotCauseQueriesToBeAvailable(false), + alwaysCallUseProgramAfterLink(false), + unpackOverlappingRowsSeparatelyUnpackBuffer(false), + emulateAbsIntFunction(false), + addAndTrueToLoopCondition(false), + emulateIsnanFloat(false), + useUnusedBlocksWithStandardOrSharedLayout(false), + dontRemoveInvariantForFragmentInput(false), + removeInvariantAndCentroidForESSL3(false) + { + } + + // When writing a float to a normalized integer framebuffer, desktop OpenGL is allowed to write + // one of the two closest normalized integer representations (although round to nearest is + // preferred) (see section 2.3.5.2 of the GL 4.5 core specification). OpenGL ES requires that + // round-to-nearest is used (see "Conversion from Floating-Point to Framebuffer Fixed-Point" in + // section 2.1.2 of the OpenGL ES 2.0.25 spec). This issue only shows up on Intel and AMD + // drivers on framebuffer formats that have 1-bit alpha, work around this by using higher + // precision formats instead. + bool avoid1BitAlphaTextureFormats; + + // On some older Intel drivers, GL_RGBA4 is not color renderable, glCheckFramebufferStatus + // returns GL_FRAMEBUFFER_UNSUPPORTED. Work around this by using a known color-renderable + // format. + bool rgba4IsNotSupportedForColorRendering; + + // When clearing a framebuffer on Intel or AMD drivers, when GL_FRAMEBUFFER_SRGB is enabled, the + // driver clears to the linearized clear color despite the framebuffer not supporting SRGB + // blending. It only seems to do this when the framebuffer has only linear attachments, mixed + // attachments appear to get the correct clear color. + bool doesSRGBClearsOnLinearFramebufferAttachments; + + // On Mac some GLSL constructs involving do-while loops cause GPU hangs, such as the following: + // int i = 1; + // do { + // i --; + // continue; + // } while (i > 0) + // Work around this by rewriting the do-while to use another GLSL construct (block + while) + bool doWhileGLSLCausesGPUHang; + + // Calling glFinish doesn't cause all queries to report that the result is available on some + // (NVIDIA) drivers. It was found that enabling GL_DEBUG_OUTPUT_SYNCHRONOUS before the finish + // causes it to fully finish. + bool finishDoesNotCauseQueriesToBeAvailable; + + // Always call useProgram after a successful link to avoid a driver bug. + // This workaround is meant to reproduce the use_current_program_after_successful_link + // workaround in Chromium (http://crbug.com/110263). It has been shown that this workaround is + // not necessary for MacOSX 10.9 and higher (http://crrev.com/39eb535b). + bool alwaysCallUseProgramAfterLink; + + // In the case of unpacking from a pixel unpack buffer, unpack overlapping rows row by row. + bool unpackOverlappingRowsSeparatelyUnpackBuffer; + // In the case of packing to a pixel pack buffer, pack overlapping rows row by row. + bool packOverlappingRowsSeparatelyPackBuffer; + + // During initialization, assign the current vertex attributes to the spec-mandated defaults. + bool initializeCurrentVertexAttributes; + + // abs(i) where i is an integer returns unexpected result on Intel Mac. + // Emulate abs(i) with i * sign(i). + bool emulateAbsIntFunction; + + // On Intel Mac, calculation of loop conditions in for and while loop has bug. + // Add "&& true" to the end of the condition expression to work around the bug. + bool addAndTrueToLoopCondition; + + // When uploading textures from an unpack buffer, some drivers count an extra row padding when + // checking if the pixel unpack buffer is big enough. Tracking bug: http://anglebug.com/1512 + // For example considering the pixel buffer below where in memory, each row data (D) of the + // texture is followed by some unused data (the dots): + // +-------+--+ + // |DDDDDDD|..| + // |DDDDDDD|..| + // |DDDDDDD|..| + // |DDDDDDD|..| + // +-------A--B + // The last pixel read will be A, but the driver will think it is B, causing it to generate an + // error when the pixel buffer is just big enough. + bool unpackLastRowSeparatelyForPaddingInclusion; + + // Equivalent workaround when uploading data from a pixel pack buffer. + bool packLastRowSeparatelyForPaddingInclusion; + + // On some Intel drivers, using isnan() on highp float will get wrong answer. To work around + // this bug, we use an expression to emulate function isnan(). + // Tracking bug: http://crbug.com/650547 + bool emulateIsnanFloat; + + // On Mac with OpenGL version 4.1, unused std140 or shared uniform blocks will be + // treated as inactive which is not consistent with WebGL2.0 spec. Reference all members in a + // unused std140 or shared uniform block at the beginning of main to work around it. + bool useUnusedBlocksWithStandardOrSharedLayout; + + // This flag will keep invariant declaration for input in fragment shader for GLSL >=4.20 + // on AMD. + bool dontRemoveInvariantForFragmentInput; + + // This flag is used to fix spec difference between GLSL 4.1 or lower and ESSL3. + bool removeInvariantAndCentroidForESSL3; +}; +} + +#endif // LIBANGLE_RENDERER_GL_WORKAROUNDSGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.h b/gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.h new file mode 100755 index 000000000..cc1b17bb7 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.h @@ -0,0 +1,77 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayCGL.h: CGL implementation of egl::Display + +#ifndef LIBANGLE_RENDERER_GL_CGL_DISPLAYCGL_H_ +#define LIBANGLE_RENDERER_GL_CGL_DISPLAYCGL_H_ + +#include "libANGLE/renderer/gl/DisplayGL.h" + +struct _CGLContextObject; +typedef _CGLContextObject *CGLContextObj; + +namespace rx +{ + +class DisplayCGL : public DisplayGL +{ + public: + DisplayCGL(); + ~DisplayCGL() override; + + egl::Error initialize(egl::Display *display) override; + void terminate() override; + + SurfaceImpl *createWindowSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) override; + + egl::ConfigSet generateConfigs() override; + + bool testDeviceLost() override; + egl::Error restoreLostDevice() override; + + bool isValidNativeWindow(EGLNativeWindowType window) const override; + + egl::Error getDevice(DeviceImpl **device) override; + + std::string getVendorString() const override; + + egl::Error waitClient() const override; + egl::Error waitNative(EGLint engine, + egl::Surface *drawSurface, + egl::Surface *readSurface) const override; + + egl::Error getDriverVersion(std::string *version) const override; + + private: + const FunctionsGL *getFunctionsGL() const override; + + void generateExtensions(egl::DisplayExtensions *outExtensions) const override; + void generateCaps(egl::Caps *outCaps) const override; + + egl::Display *mEGLDisplay; + FunctionsGL *mFunctions; + CGLContextObj mContext; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_CGL_DISPLAYCGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm b/gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm new file mode 100755 index 000000000..f87134c82 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm @@ -0,0 +1,275 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayCGL.mm: CGL implementation of egl::Display + +#include "libANGLE/renderer/gl/cgl/DisplayCGL.h" + +#import <Cocoa/Cocoa.h> +#include <dlfcn.h> +#include <EGL/eglext.h> + +#include "common/debug.h" +#include "libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h" +#include "libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h" + +namespace +{ + +const char *kDefaultOpenGLDylibName = + "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"; +const char *kFallbackOpenGLDylibName = "GL"; + +} + +namespace rx +{ + +class FunctionsGLCGL : public FunctionsGL +{ + public: + FunctionsGLCGL(void *dylibHandle) : mDylibHandle(dylibHandle) {} + + ~FunctionsGLCGL() override { dlclose(mDylibHandle); } + + private: + void *loadProcAddress(const std::string &function) override + { + return dlsym(mDylibHandle, function.c_str()); + } + + void *mDylibHandle; +}; + +DisplayCGL::DisplayCGL() : DisplayGL(), mEGLDisplay(nullptr), mFunctions(nullptr), mContext(nullptr) +{ +} + +DisplayCGL::~DisplayCGL() +{ +} + +egl::Error DisplayCGL::initialize(egl::Display *display) +{ + mEGLDisplay = display; + + CGLPixelFormatObj pixelFormat; + { + // TODO(cwallez) investigate which pixel format we want + CGLPixelFormatAttribute attribs[] = { + kCGLPFAOpenGLProfile, static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_3_2_Core), + static_cast<CGLPixelFormatAttribute>(0)}; + GLint nVirtualScreens = 0; + CGLChoosePixelFormat(attribs, &pixelFormat, &nVirtualScreens); + + if (pixelFormat == nullptr) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not create the context's pixel format."); + } + } + + CGLCreateContext(pixelFormat, nullptr, &mContext); + if (mContext == nullptr) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not create the CGL context."); + } + CGLSetCurrentContext(mContext); + + // There is no equivalent getProcAddress in CGL so we open the dylib directly + void *handle = dlopen(kDefaultOpenGLDylibName, RTLD_NOW); + if (!handle) + { + handle = dlopen(kFallbackOpenGLDylibName, RTLD_NOW); + } + if (!handle) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not open the OpenGL Framework."); + } + + mFunctions = new FunctionsGLCGL(handle); + mFunctions->initialize(); + + return DisplayGL::initialize(display); +} + +void DisplayCGL::terminate() +{ + DisplayGL::terminate(); + + if (mContext != nullptr) + { + CGLSetCurrentContext(nullptr); + CGLReleaseContext(mContext); + mContext = nullptr; + } + + SafeDelete(mFunctions); +} + +SurfaceImpl *DisplayCGL::createWindowSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) +{ + return new WindowSurfaceCGL(state, this->getRenderer(), window, mFunctions, mContext); +} + +SurfaceImpl *DisplayCGL::createPbufferSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + const egl::AttributeMap &attribs) +{ + EGLint width = static_cast<EGLint>(attribs.get(EGL_WIDTH, 0)); + EGLint height = static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0)); + return new PbufferSurfaceCGL(state, this->getRenderer(), width, height, mFunctions); +} + +SurfaceImpl *DisplayCGL::createPbufferFromClientBuffer(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) +{ + UNIMPLEMENTED(); + return nullptr; +} + +SurfaceImpl *DisplayCGL::createPixmapSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) +{ + UNIMPLEMENTED(); + return nullptr; +} + +egl::Error DisplayCGL::getDevice(DeviceImpl **device) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_BAD_DISPLAY); +} + +egl::ConfigSet DisplayCGL::generateConfigs() +{ + // TODO(cwallez): generate more config permutations + egl::ConfigSet configs; + + const gl::Version &maxVersion = getMaxSupportedESVersion(); + ASSERT(maxVersion >= gl::Version(2, 0)); + bool supportsES3 = maxVersion >= gl::Version(3, 0); + + egl::Config config; + + // Native stuff + config.nativeVisualID = 0; + config.nativeVisualType = 0; + config.nativeRenderable = EGL_TRUE; + + // Buffer sizes + config.redSize = 8; + config.greenSize = 8; + config.blueSize = 8; + config.alphaSize = 8; + config.depthSize = 24; + config.stencilSize = 8; + + config.colorBufferType = EGL_RGB_BUFFER; + config.luminanceSize = 0; + config.alphaMaskSize = 0; + + config.bufferSize = config.redSize + config.greenSize + config.blueSize + config.alphaSize; + + config.transparentType = EGL_NONE; + + // Pbuffer + config.maxPBufferWidth = 4096; + config.maxPBufferHeight = 4096; + config.maxPBufferPixels = 4096 * 4096; + + // Caveat + config.configCaveat = EGL_NONE; + + // Misc + config.sampleBuffers = 0; + config.samples = 0; + config.level = 0; + config.bindToTextureRGB = EGL_FALSE; + config.bindToTextureRGBA = EGL_FALSE; + + config.surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; + + config.minSwapInterval = 1; + config.maxSwapInterval = 1; + + config.renderTargetFormat = GL_RGBA8; + config.depthStencilFormat = GL_DEPTH24_STENCIL8; + + config.conformant = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0); + config.renderableType = config.conformant; + + config.matchNativePixmap = EGL_NONE; + + configs.add(config); + return configs; +} + +bool DisplayCGL::testDeviceLost() +{ + // TODO(cwallez) investigate implementing this + return false; +} + +egl::Error DisplayCGL::restoreLostDevice() +{ + UNIMPLEMENTED(); + return egl::Error(EGL_BAD_DISPLAY); +} + +bool DisplayCGL::isValidNativeWindow(EGLNativeWindowType window) const +{ + // TODO(cwallez) investigate implementing this + return true; +} + +std::string DisplayCGL::getVendorString() const +{ + // TODO(cwallez) find a useful vendor string + return ""; +} + +const FunctionsGL *DisplayCGL::getFunctionsGL() const +{ + return mFunctions; +} + +void DisplayCGL::generateExtensions(egl::DisplayExtensions *outExtensions) const +{ +} + +void DisplayCGL::generateCaps(egl::Caps *outCaps) const +{ + outCaps->textureNPOT = true; +} + +egl::Error DisplayCGL::waitClient() const +{ + // TODO(cwallez) UNIMPLEMENTED() + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayCGL::waitNative(EGLint engine, + egl::Surface *drawSurface, + egl::Surface *readSurface) const +{ + // TODO(cwallez) UNIMPLEMENTED() + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayCGL::getDriverVersion(std::string *version) const +{ + *version = ""; + return egl::Error(EGL_SUCCESS); +} +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h b/gfx/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h new file mode 100755 index 000000000..7cbb74da4 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h @@ -0,0 +1,65 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// PBufferSurfaceCGL.h: an implementation of egl::Surface for PBuffers for the CLG backend, +// currently implemented using renderbuffers + +#ifndef LIBANGLE_RENDERER_GL_CGL_PBUFFERSURFACECGL_H_ +#define LIBANGLE_RENDERER_GL_CGL_PBUFFERSURFACECGL_H_ + +#include "libANGLE/renderer/gl/SurfaceGL.h" + +namespace rx +{ + +class FunctionsGL; +class StateManagerGL; +struct WorkaroundsGL; + +class PbufferSurfaceCGL : public SurfaceGL +{ + public: + PbufferSurfaceCGL(const egl::SurfaceState &state, + RendererGL *renderer, + EGLint width, + EGLint height, + const FunctionsGL *functions); + ~PbufferSurfaceCGL() override; + + egl::Error initialize() override; + egl::Error makeCurrent() override; + + egl::Error swap() override; + egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; + egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; + egl::Error releaseTexImage(EGLint buffer) override; + void setSwapInterval(EGLint interval) override; + + EGLint getWidth() const override; + EGLint getHeight() const override; + + EGLint isPostSubBufferSupported() const override; + EGLint getSwapBehavior() const override; + + FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override; + + private: + unsigned mWidth; + unsigned mHeight; + + const FunctionsGL *mFunctions; + StateManagerGL *mStateManager; + RendererGL *mRenderer; + + GLuint mFramebuffer; + GLuint mColorRenderbuffer; + GLuint mDSRenderbuffer; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_CGL_PBUFFERSURFACECGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm b/gfx/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm new file mode 100755 index 000000000..c03d3836f --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm @@ -0,0 +1,143 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// PBufferSurfaceCGL.cpp: an implementation of egl::Surface for PBuffers for the CLG backend, +// currently implemented using renderbuffers + +#include "libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h" + +#include "common/debug.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/FramebufferGL.h" +#include "libANGLE/renderer/gl/RendererGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" + +namespace rx +{ + +PbufferSurfaceCGL::PbufferSurfaceCGL(const egl::SurfaceState &state, + RendererGL *renderer, + EGLint width, + EGLint height, + const FunctionsGL *functions) + : SurfaceGL(state, renderer), + mWidth(width), + mHeight(height), + mFunctions(functions), + mStateManager(renderer->getStateManager()), + mRenderer(renderer), + mFramebuffer(0), + mColorRenderbuffer(0), + mDSRenderbuffer(0) +{ +} + +PbufferSurfaceCGL::~PbufferSurfaceCGL() +{ + if (mFramebuffer != 0) + { + mFunctions->deleteFramebuffers(1, &mFramebuffer); + mFramebuffer = 0; + } + + if (mColorRenderbuffer != 0) + { + mFunctions->deleteRenderbuffers(1, &mColorRenderbuffer); + mColorRenderbuffer = 0; + } + if (mDSRenderbuffer != 0) + { + mFunctions->deleteRenderbuffers(1, &mDSRenderbuffer); + mDSRenderbuffer = 0; + } +} + +egl::Error PbufferSurfaceCGL::initialize() +{ + mFunctions->genRenderbuffers(1, &mColorRenderbuffer); + mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mColorRenderbuffer); + mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, mWidth, mHeight); + + mFunctions->genRenderbuffers(1, &mDSRenderbuffer); + mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer); + mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mWidth, mHeight); + + mFunctions->genFramebuffers(1, &mFramebuffer); + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); + mFunctions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, + mColorRenderbuffer); + mFunctions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, mDSRenderbuffer); + + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceCGL::makeCurrent() +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceCGL::swap() +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceCGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceCGL::querySurfacePointerANGLE(EGLint attribute, void **value) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceCGL::bindTexImage(gl::Texture *texture, EGLint buffer) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceCGL::releaseTexImage(EGLint buffer) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +void PbufferSurfaceCGL::setSwapInterval(EGLint interval) +{ +} + +EGLint PbufferSurfaceCGL::getWidth() const +{ + return mWidth; +} + +EGLint PbufferSurfaceCGL::getHeight() const +{ + return mHeight; +} + +EGLint PbufferSurfaceCGL::isPostSubBufferSupported() const +{ + UNIMPLEMENTED(); + return EGL_FALSE; +} + +EGLint PbufferSurfaceCGL::getSwapBehavior() const +{ + return EGL_BUFFER_PRESERVED; +} + +FramebufferImpl *PbufferSurfaceCGL::createDefaultFramebuffer(const gl::FramebufferState &state) +{ + // TODO(cwallez) assert it happens only once? + return new FramebufferGL(mFramebuffer, state, mFunctions, mRenderer->getWorkarounds(), + mRenderer->getBlitter(), mStateManager); +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h b/gfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h new file mode 100755 index 000000000..165ab0486 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h @@ -0,0 +1,100 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// WindowSurfaceCGL.h: CGL implementation of egl::Surface for windows + +#ifndef LIBANGLE_RENDERER_GL_CGL_WINDOWSURFACECGL_H_ +#define LIBANGLE_RENDERER_GL_CGL_WINDOWSURFACECGL_H_ + +#include "libANGLE/renderer/gl/SurfaceGL.h" + +struct _CGLContextObject; +typedef _CGLContextObject *CGLContextObj; +@class CALayer; +struct __IOSurface; +typedef __IOSurface *IOSurfaceRef; + +@class SwapLayer; + +namespace rx +{ + +class DisplayCGL; +class FramebufferGL; +class FunctionsGL; +class StateManagerGL; +struct WorkaroundsGL; + +struct SharedSwapState +{ + struct SwapTexture + { + GLuint texture; + unsigned int width; + unsigned int height; + uint64_t swapId; + }; + + SwapTexture textures[3]; + + // This code path is not going to be used by Chrome so we take the liberty + // to use pthreads directly instead of using mutexes and condition variables + // via the Platform API. + pthread_mutex_t mutex; + // The following members should be accessed only when holding the mutex + // (or doing construction / destruction) + SwapTexture *beingRendered; + SwapTexture *lastRendered; + SwapTexture *beingPresented; +}; + +class WindowSurfaceCGL : public SurfaceGL +{ + public: + WindowSurfaceCGL(const egl::SurfaceState &state, + RendererGL *renderer, + CALayer *layer, + const FunctionsGL *functions, + CGLContextObj context); + ~WindowSurfaceCGL() override; + + egl::Error initialize() override; + egl::Error makeCurrent() override; + + egl::Error swap() override; + egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; + egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; + egl::Error releaseTexImage(EGLint buffer) override; + void setSwapInterval(EGLint interval) override; + + EGLint getWidth() const override; + EGLint getHeight() const override; + + EGLint isPostSubBufferSupported() const override; + EGLint getSwapBehavior() const override; + + FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override; + + private: + SwapLayer *mSwapLayer; + SharedSwapState mSwapState; + uint64_t mCurrentSwapId; + + CALayer *mLayer; + CGLContextObj mContext; + const FunctionsGL *mFunctions; + StateManagerGL *mStateManager; + RendererGL *mRenderer; + const WorkaroundsGL &mWorkarounds; + + GLuint mFramebuffer; + GLuint mDSRenderbuffer; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_CGL_WINDOWSURFACECGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm b/gfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm new file mode 100755 index 000000000..c2ac4dca4 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm @@ -0,0 +1,332 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// WindowSurfaceCGL.cpp: CGL implementation of egl::Surface for windows + +#include "libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h" + +#import <Cocoa/Cocoa.h> +#include <OpenGL/OpenGL.h> +#import <QuartzCore/QuartzCore.h> + +#include "common/debug.h" +#include "libANGLE/renderer/gl/cgl/DisplayCGL.h" +#include "libANGLE/renderer/gl/FramebufferGL.h" +#include "libANGLE/renderer/gl/RendererGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" + +@interface SwapLayer : CAOpenGLLayer +{ + CGLContextObj mDisplayContext; + + bool initialized; + rx::SharedSwapState *mSwapState; + const rx::FunctionsGL *mFunctions; + + GLuint mReadFramebuffer; +} +- (id)initWithSharedState:(rx::SharedSwapState *)swapState + withContext:(CGLContextObj)displayContext + withFunctions:(const rx::FunctionsGL *)functions; +@end + +@implementation SwapLayer +- (id)initWithSharedState:(rx::SharedSwapState *)swapState + withContext:(CGLContextObj)displayContext + withFunctions:(const rx::FunctionsGL *)functions + { + self = [super init]; + if (self != nil) + { + self.asynchronous = YES; + mDisplayContext = displayContext; + + initialized = false; + mSwapState = swapState; + mFunctions = functions; + + [self setFrame:CGRectMake(0, 0, mSwapState->textures[0].width, + mSwapState->textures[0].height)]; + } + return self; + } + + - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask + { + CGLPixelFormatAttribute attribs[] = { + kCGLPFADisplayMask, static_cast<CGLPixelFormatAttribute>(mask), kCGLPFAOpenGLProfile, + static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_3_2_Core), + static_cast<CGLPixelFormatAttribute>(0)}; + + CGLPixelFormatObj pixelFormat = nullptr; + GLint numFormats = 0; + CGLChoosePixelFormat(attribs, &pixelFormat, &numFormats); + + return pixelFormat; + } + + - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat + { + CGLContextObj context = nullptr; + CGLCreateContext(pixelFormat, mDisplayContext, &context); + return context; + } + + - (BOOL)canDrawInCGLContext:(CGLContextObj)glContext + pixelFormat:(CGLPixelFormatObj)pixelFormat + forLayerTime:(CFTimeInterval)timeInterval + displayTime:(const CVTimeStamp *)timeStamp + { + BOOL result = NO; + + pthread_mutex_lock(&mSwapState->mutex); + { + if (mSwapState->lastRendered->swapId > mSwapState->beingPresented->swapId) + { + std::swap(mSwapState->lastRendered, mSwapState->beingPresented); + result = YES; + } + } + pthread_mutex_unlock(&mSwapState->mutex); + + return result; + } + + - (void)drawInCGLContext:(CGLContextObj)glContext + pixelFormat:(CGLPixelFormatObj)pixelFormat + forLayerTime:(CFTimeInterval)timeInterval + displayTime:(const CVTimeStamp *)timeStamp + { + CGLSetCurrentContext(glContext); + if (!initialized) + { + initialized = true; + + mFunctions->genFramebuffers(1, &mReadFramebuffer); + } + + const auto &texture = *mSwapState->beingPresented; + if ([self frame].size.width != texture.width || [self frame].size.height != texture.height) + { + [self setFrame:CGRectMake(0, 0, texture.width, texture.height)]; + + // Without this, the OSX compositor / window system doesn't see the resize. + [self setNeedsDisplay]; + } + + // TODO(cwallez) support 2.1 contexts too that don't have blitFramebuffer nor the + // GL_DRAW_FRAMEBUFFER_BINDING query + GLint drawFBO; + mFunctions->getIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFBO); + + mFunctions->bindFramebuffer(GL_FRAMEBUFFER, mReadFramebuffer); + mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + texture.texture, 0); + + mFunctions->bindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer); + mFunctions->bindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO); + mFunctions->blitFramebuffer(0, 0, texture.width, texture.height, 0, 0, texture.width, + texture.height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + // Call the super method to flush the context + [super drawInCGLContext:glContext + pixelFormat:pixelFormat + forLayerTime:timeInterval + displayTime:timeStamp]; + } + @end + + namespace rx + { + + WindowSurfaceCGL::WindowSurfaceCGL(const egl::SurfaceState &state, + RendererGL *renderer, + CALayer *layer, + const FunctionsGL *functions, + CGLContextObj context) + : SurfaceGL(state, renderer), + mSwapLayer(nil), + mCurrentSwapId(0), + mLayer(layer), + mContext(context), + mFunctions(functions), + mStateManager(renderer->getStateManager()), + mRenderer(renderer), + mWorkarounds(renderer->getWorkarounds()), + mFramebuffer(0), + mDSRenderbuffer(0) + { + pthread_mutex_init(&mSwapState.mutex, nullptr); +} + +WindowSurfaceCGL::~WindowSurfaceCGL() +{ + pthread_mutex_destroy(&mSwapState.mutex); + if (mFramebuffer != 0) + { + mFunctions->deleteFramebuffers(1, &mFramebuffer); + mFramebuffer = 0; + } + + if (mDSRenderbuffer != 0) + { + mFunctions->deleteRenderbuffers(1, &mDSRenderbuffer); + mDSRenderbuffer = 0; + } + + if (mSwapLayer != nil) + { + [mSwapLayer removeFromSuperlayer]; + [mSwapLayer release]; + mSwapLayer = nil; + } + + for (size_t i = 0; i < ArraySize(mSwapState.textures); ++i) + { + if (mSwapState.textures[i].texture != 0) + { + mFunctions->deleteTextures(1, &mSwapState.textures[i].texture); + mSwapState.textures[i].texture = 0; + } + } +} + +egl::Error WindowSurfaceCGL::initialize() +{ + unsigned width = getWidth(); + unsigned height = getHeight(); + + for (size_t i = 0; i < ArraySize(mSwapState.textures); ++i) + { + mFunctions->genTextures(1, &mSwapState.textures[i].texture); + mStateManager->bindTexture(GL_TEXTURE_2D, mSwapState.textures[i].texture); + mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + mSwapState.textures[i].width = width; + mSwapState.textures[i].height = height; + mSwapState.textures[i].swapId = 0; + } + mSwapState.beingRendered = &mSwapState.textures[0]; + mSwapState.lastRendered = &mSwapState.textures[1]; + mSwapState.beingPresented = &mSwapState.textures[2]; + + mSwapLayer = [[SwapLayer alloc] initWithSharedState:&mSwapState + withContext:mContext + withFunctions:mFunctions]; + [mLayer addSublayer:mSwapLayer]; + + mFunctions->genRenderbuffers(1, &mDSRenderbuffer); + mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer); + mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); + + mFunctions->genFramebuffers(1, &mFramebuffer); + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); + mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + mSwapState.beingRendered->texture, 0); + mFunctions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, + mDSRenderbuffer); + + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceCGL::makeCurrent() +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceCGL::swap() +{ + mFunctions->flush(); + mSwapState.beingRendered->swapId = ++mCurrentSwapId; + + pthread_mutex_lock(&mSwapState.mutex); + { + std::swap(mSwapState.beingRendered, mSwapState.lastRendered); + } + pthread_mutex_unlock(&mSwapState.mutex); + + unsigned width = getWidth(); + unsigned height = getHeight(); + auto &texture = *mSwapState.beingRendered; + + if (texture.width != width || texture.height != height) + { + mStateManager->bindTexture(GL_TEXTURE_2D, texture.texture); + mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + + mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer); + mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); + + texture.width = width; + texture.height = height; + } + + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); + mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + mSwapState.beingRendered->texture, 0); + + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceCGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceCGL::querySurfacePointerANGLE(EGLint attribute, void **value) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceCGL::bindTexImage(gl::Texture *texture, EGLint buffer) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceCGL::releaseTexImage(EGLint buffer) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +void WindowSurfaceCGL::setSwapInterval(EGLint interval) +{ + // TODO(cwallez) investigate implementing swap intervals other than 0 +} + +EGLint WindowSurfaceCGL::getWidth() const +{ + return CGRectGetWidth([mLayer frame]); +} + +EGLint WindowSurfaceCGL::getHeight() const +{ + return CGRectGetHeight([mLayer frame]); +} + +EGLint WindowSurfaceCGL::isPostSubBufferSupported() const +{ + UNIMPLEMENTED(); + return EGL_FALSE; +} + +EGLint WindowSurfaceCGL::getSwapBehavior() const +{ + return EGL_BUFFER_DESTROYED; +} + +FramebufferImpl *WindowSurfaceCGL::createDefaultFramebuffer(const gl::FramebufferState &state) +{ + // TODO(cwallez) assert it happens only once? + return new FramebufferGL(mFramebuffer, state, mFunctions, mWorkarounds, mRenderer->getBlitter(), + mStateManager); +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp new file mode 100755 index 000000000..988b233b4 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp @@ -0,0 +1,116 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayEGL.cpp: Common across EGL parts of platform specific egl::Display implementations + +#include "libANGLE/renderer/gl/egl/DisplayEGL.h" + +namespace rx +{ + +#define EGL_NO_CONFIG ((EGLConfig)0) + +DisplayEGL::DisplayEGL() + : DisplayGL(), + mEGL(nullptr), + mConfig(EGL_NO_CONFIG), + mContext(EGL_NO_CONTEXT), + mFunctionsGL(nullptr) +{ +} + +DisplayEGL::~DisplayEGL() +{ +} + +std::string DisplayEGL::getVendorString() const +{ + const char *vendor = mEGL->queryString(EGL_VENDOR); + ASSERT(vendor); + return vendor; +} + +egl::Error DisplayEGL::initializeContext(const egl::AttributeMap &eglAttributes) +{ + gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion); + + EGLint requestedMajor = + eglAttributes.getAsInt(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE); + EGLint requestedMinor = + eglAttributes.getAsInt(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE); + bool initializeRequested = requestedMajor != EGL_DONT_CARE && requestedMinor != EGL_DONT_CARE; + + static_assert(EGL_CONTEXT_MAJOR_VERSION == EGL_CONTEXT_MAJOR_VERSION_KHR, + "Major Version define should match"); + static_assert(EGL_CONTEXT_MINOR_VERSION == EGL_CONTEXT_MINOR_VERSION_KHR, + "Minor Version define should match"); + + std::vector<std::vector<EGLint>> contextAttribLists; + if (eglVersion >= gl::Version(1, 5) || mEGL->hasExtension("EGL_KHR_create_context")) + { + if (initializeRequested) + { + contextAttribLists.push_back({EGL_CONTEXT_MAJOR_VERSION, requestedMajor, + EGL_CONTEXT_MINOR_VERSION, requestedMinor, EGL_NONE}); + } + else + { + // clang-format off + const gl::Version esVersionsFrom2_0[] = { + gl::Version(3, 2), + gl::Version(3, 1), + gl::Version(3, 0), + gl::Version(2, 0), + }; + // clang-format on + + for (const auto &version : esVersionsFrom2_0) + { + contextAttribLists.push_back( + {EGL_CONTEXT_MAJOR_VERSION, static_cast<EGLint>(version.major), + EGL_CONTEXT_MINOR_VERSION, static_cast<EGLint>(version.minor), EGL_NONE}); + } + } + } + else + { + if (initializeRequested && (requestedMajor != 2 || requestedMinor != 0)) + { + return egl::Error(EGL_BAD_ATTRIBUTE, "Unsupported requested context version"); + } + contextAttribLists.push_back({EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}); + } + + for (auto &attribList : contextAttribLists) + { + mContext = mEGL->createContext(mConfig, EGL_NO_CONTEXT, attribList.data()); + if (mContext != EGL_NO_CONTEXT) + { + return egl::Error(EGL_SUCCESS); + } + } + + return egl::Error(mEGL->getError(), "eglCreateContext failed"); +} + +void DisplayEGL::generateExtensions(egl::DisplayExtensions *outExtensions) const +{ + outExtensions->createContextRobustness = + mEGL->hasExtension("EGL_EXT_create_context_robustness"); + + outExtensions->postSubBuffer = false; // Since SurfaceEGL::postSubBuffer is not implemented +} + +void DisplayEGL::generateCaps(egl::Caps *outCaps) const +{ + outCaps->textureNPOT = true; // Since we request GLES >= 2 +} + +const FunctionsGL *DisplayEGL::getFunctionsGL() const +{ + return mFunctionsGL; +} +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.h new file mode 100755 index 000000000..e498cd79a --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.h @@ -0,0 +1,43 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayEGL.h: Common across EGL parts of platform specific egl::Display implementations + +#ifndef LIBANGLE_RENDERER_GL_EGL_DISPLAYEGL_H_ +#define LIBANGLE_RENDERER_GL_EGL_DISPLAYEGL_H_ + +#include "libANGLE/renderer/gl/DisplayGL.h" +#include "libANGLE/renderer/gl/egl/FunctionsEGL.h" + +namespace rx +{ + +class DisplayEGL : public DisplayGL +{ + public: + DisplayEGL(); + ~DisplayEGL() override; + + std::string getVendorString() const override; + + protected: + egl::Error initializeContext(const egl::AttributeMap &eglAttributes); + + FunctionsEGL *mEGL; + EGLConfig mConfig; + EGLContext mContext; + FunctionsGL *mFunctionsGL; + + private: + void generateExtensions(egl::DisplayExtensions *outExtensions) const override; + void generateCaps(egl::Caps *outCaps) const override; + + const FunctionsGL *getFunctionsGL() const override; +}; + +} // namespace rx + +#endif /* LIBANGLE_RENDERER_GL_EGL_DISPLAYEGL_H_ */ diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp new file mode 100755 index 000000000..c0b0f846f --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp @@ -0,0 +1,340 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FunctionsEGL.cpp: Implements the FunctionsEGL class. + +#include "libANGLE/renderer/gl/egl/FunctionsEGL.h" + +#include <algorithm> + +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/egl/functionsegl_typedefs.h" +#include "common/string_utils.h" + +namespace +{ + +template <typename T> +bool SetPtr(T *dst, void *src) +{ + if (src) + { + *dst = reinterpret_cast<T>(src); + return true; + } + return false; +} +} // namespace + +namespace rx +{ + +struct FunctionsEGL::EGLDispatchTable +{ + EGLDispatchTable() + : bindAPIPtr(nullptr), + chooseConfigPtr(nullptr), + createContextPtr(nullptr), + createPbufferSurfacePtr(nullptr), + createWindowSurfacePtr(nullptr), + destroyContextPtr(nullptr), + destroySurfacePtr(nullptr), + getConfigAttribPtr(nullptr), + getDisplayPtr(nullptr), + getErrorPtr(nullptr), + initializePtr(nullptr), + makeCurrentPtr(nullptr), + queryStringPtr(nullptr), + querySurfacePtr(nullptr), + swapBuffersPtr(nullptr), + terminatePtr(nullptr), + + bindTexImagePtr(nullptr), + releaseTexImagePtr(nullptr), + swapIntervalPtr(nullptr), + + createImageKHRPtr(nullptr), + destroyImageKHRPtr(nullptr), + + clientWaitSyncKHRPtr(nullptr), + createSyncKHRPtr(nullptr), + destroySyncKHRPtr(nullptr), + getSyncAttribKHRPtr(nullptr) + { + } + + // 1.0 + PFNEGLBINDAPIPROC bindAPIPtr; + PFNEGLCHOOSECONFIGPROC chooseConfigPtr; + PFNEGLCREATECONTEXTPROC createContextPtr; + PFNEGLCREATEPBUFFERSURFACEPROC createPbufferSurfacePtr; + PFNEGLCREATEWINDOWSURFACEPROC createWindowSurfacePtr; + PFNEGLDESTROYCONTEXTPROC destroyContextPtr; + PFNEGLDESTROYSURFACEPROC destroySurfacePtr; + PFNEGLGETCONFIGATTRIBPROC getConfigAttribPtr; + PFNEGLGETDISPLAYPROC getDisplayPtr; + PFNEGLGETERRORPROC getErrorPtr; + PFNEGLINITIALIZEPROC initializePtr; + PFNEGLMAKECURRENTPROC makeCurrentPtr; + PFNEGLQUERYSTRINGPROC queryStringPtr; + PFNEGLQUERYSURFACEPROC querySurfacePtr; + PFNEGLSWAPBUFFERSPROC swapBuffersPtr; + PFNEGLTERMINATEPROC terminatePtr; + + // 1.1 + PFNEGLBINDTEXIMAGEPROC bindTexImagePtr; + PFNEGLRELEASETEXIMAGEPROC releaseTexImagePtr; + PFNEGLSWAPINTERVALPROC swapIntervalPtr; + + // EGL_KHR_image + PFNEGLCREATEIMAGEKHRPROC createImageKHRPtr; + PFNEGLDESTROYIMAGEKHRPROC destroyImageKHRPtr; + + // EGL_KHR_fence_sync + PFNEGLCLIENTWAITSYNCKHRPROC clientWaitSyncKHRPtr; + PFNEGLCREATESYNCKHRPROC createSyncKHRPtr; + PFNEGLDESTROYSYNCKHRPROC destroySyncKHRPtr; + PFNEGLGETSYNCATTRIBKHRPROC getSyncAttribKHRPtr; +}; + +FunctionsEGL::FunctionsEGL() + : majorVersion(0), minorVersion(0), mFnPtrs(new EGLDispatchTable()), mEGLDisplay(EGL_NO_DISPLAY) +{ +} + +FunctionsEGL::~FunctionsEGL() +{ + SafeDelete(mFnPtrs); +} + +egl::Error FunctionsEGL::initialize(EGLNativeDisplayType nativeDisplay) +{ +#define ANGLE_GET_PROC_OR_ERROR(MEMBER, NAME) \ + if (!SetPtr(MEMBER, getProcAddress(#NAME))) \ + { \ + return egl::Error(EGL_NOT_INITIALIZED, "Could not load EGL entry point " #NAME); \ + } + + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->bindAPIPtr, eglBindAPI); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->chooseConfigPtr, eglChooseConfig); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createContextPtr, eglCreateContext); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createPbufferSurfacePtr, eglCreatePbufferSurface); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createWindowSurfacePtr, eglCreateWindowSurface); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroyContextPtr, eglDestroyContext); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroySurfacePtr, eglDestroySurface); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getConfigAttribPtr, eglGetConfigAttrib); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getDisplayPtr, eglGetDisplay); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getErrorPtr, eglGetError); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->initializePtr, eglInitialize); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->makeCurrentPtr, eglMakeCurrent); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->queryStringPtr, eglQueryString); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->querySurfacePtr, eglQuerySurface); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->swapBuffersPtr, eglSwapBuffers); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->terminatePtr, eglTerminate); + + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->bindTexImagePtr, eglBindTexImage); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->releaseTexImagePtr, eglReleaseTexImage); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalPtr, eglSwapInterval); + + mEGLDisplay = mFnPtrs->getDisplayPtr(nativeDisplay); + if (mEGLDisplay == EGL_NO_DISPLAY) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to get system egl display"); + } + if (mFnPtrs->initializePtr(mEGLDisplay, &majorVersion, &minorVersion) != EGL_TRUE) + { + return egl::Error(mFnPtrs->getErrorPtr(), "Failed to initialize system egl"); + } + if (majorVersion < 1 || (majorVersion == 1 && minorVersion < 4)) + { + return egl::Error(EGL_NOT_INITIALIZED, "Unsupported EGL version (require at least 1.4)."); + } + if (mFnPtrs->bindAPIPtr(EGL_OPENGL_ES_API) != EGL_TRUE) + { + return egl::Error(mFnPtrs->getErrorPtr(), "Failed to bind API in system egl"); + } + + const char *extensions = queryString(EGL_EXTENSIONS); + if (!extensions) + { + return egl::Error(mFnPtrs->getErrorPtr(), "Faild to query extensions in system egl"); + } + angle::SplitStringAlongWhitespace(extensions, &mExtensions); + + if (hasExtension("EGL_KHR_image_base")) + { + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createImageKHRPtr, eglCreateImageKHR); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroyImageKHRPtr, eglDestroyImageKHR); + } + if (hasExtension("EGL_KHR_fence_sync")) + { + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->clientWaitSyncKHRPtr, eglClientWaitSyncKHR); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createSyncKHRPtr, eglCreateSyncKHR); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroySyncKHRPtr, eglDestroySyncKHR); + ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getSyncAttribKHRPtr, eglGetSyncAttribKHR); + } + +#undef ANGLE_GET_PROC_OR_ERROR + + return egl::Error(EGL_SUCCESS); +} + +egl::Error FunctionsEGL::terminate() +{ + if (mFnPtrs->terminatePtr(mEGLDisplay) == EGL_TRUE) + { + mEGLDisplay = nullptr; + return egl::Error(EGL_SUCCESS); + } + return egl::Error(mFnPtrs->getErrorPtr()); +} + +class FunctionsGLEGL : public FunctionsGL +{ + public: + FunctionsGLEGL(const FunctionsEGL &egl) : mEGL(egl) {} + + ~FunctionsGLEGL() override {} + + private: + void *loadProcAddress(const std::string &function) override + { + return mEGL.getProcAddress(function.c_str()); + } + + const FunctionsEGL &mEGL; +}; + +FunctionsGL *FunctionsEGL::makeFunctionsGL(void) const +{ + return new FunctionsGLEGL(*this); +} + +bool FunctionsEGL::hasExtension(const char *extension) const +{ + return std::find(mExtensions.begin(), mExtensions.end(), extension) != mExtensions.end(); +} + +EGLDisplay FunctionsEGL::getDisplay() const +{ + return mEGLDisplay; +} + +EGLint FunctionsEGL::getError() const +{ + return mFnPtrs->getErrorPtr(); +} + +EGLBoolean FunctionsEGL::chooseConfig(EGLint const *attribList, + EGLConfig *configs, + EGLint configSize, + EGLint *numConfig) const +{ + return mFnPtrs->chooseConfigPtr(mEGLDisplay, attribList, configs, configSize, numConfig); +} + +EGLBoolean FunctionsEGL::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) const +{ + return mFnPtrs->getConfigAttribPtr(mEGLDisplay, config, attribute, value); +} + +EGLContext FunctionsEGL::createContext(EGLConfig config, + EGLContext share_context, + EGLint const *attrib_list) const +{ + return mFnPtrs->createContextPtr(mEGLDisplay, config, share_context, attrib_list); +} + +EGLSurface FunctionsEGL::createPbufferSurface(EGLConfig config, const EGLint *attrib_list) const +{ + return mFnPtrs->createPbufferSurfacePtr(mEGLDisplay, config, attrib_list); +} + +EGLSurface FunctionsEGL::createWindowSurface(EGLConfig config, + EGLNativeWindowType win, + const EGLint *attrib_list) const +{ + return mFnPtrs->createWindowSurfacePtr(mEGLDisplay, config, win, attrib_list); +} + +EGLBoolean FunctionsEGL::destroyContext(EGLContext context) const +{ + return mFnPtrs->destroyContextPtr(mEGLDisplay, context); +} + +EGLBoolean FunctionsEGL::destroySurface(EGLSurface surface) const +{ + return mFnPtrs->destroySurfacePtr(mEGLDisplay, surface); +} + +EGLBoolean FunctionsEGL::makeCurrent(EGLSurface surface, EGLContext context) const +{ + return mFnPtrs->makeCurrentPtr(mEGLDisplay, surface, surface, context); +} + +char const *FunctionsEGL::queryString(EGLint name) const +{ + return mFnPtrs->queryStringPtr(mEGLDisplay, name); +} + +EGLBoolean FunctionsEGL::querySurface(EGLSurface surface, EGLint attribute, EGLint *value) const +{ + return mFnPtrs->querySurfacePtr(mEGLDisplay, surface, attribute, value); +} + +EGLBoolean FunctionsEGL::swapBuffers(EGLSurface surface) const +{ + return mFnPtrs->swapBuffersPtr(mEGLDisplay, surface); +} + +EGLBoolean FunctionsEGL::bindTexImage(EGLSurface surface, EGLint buffer) const +{ + return mFnPtrs->bindTexImagePtr(mEGLDisplay, surface, buffer); +} + +EGLBoolean FunctionsEGL::releaseTexImage(EGLSurface surface, EGLint buffer) const +{ + return mFnPtrs->releaseTexImagePtr(mEGLDisplay, surface, buffer); +} + +EGLBoolean FunctionsEGL::swapInterval(EGLint interval) const +{ + return mFnPtrs->swapIntervalPtr(mEGLDisplay, interval); +} + +EGLImageKHR FunctionsEGL::createImageKHR(EGLContext context, + EGLenum target, + EGLClientBuffer buffer, + const EGLint *attrib_list) const +{ + return mFnPtrs->createImageKHRPtr(mEGLDisplay, context, target, buffer, attrib_list); +} + +EGLBoolean FunctionsEGL::destroyImageKHR(EGLImageKHR image) const +{ + return mFnPtrs->destroyImageKHRPtr(mEGLDisplay, image); +} + +EGLSyncKHR FunctionsEGL::createSyncKHR(EGLenum type, const EGLint *attrib_list) +{ + return mFnPtrs->createSyncKHRPtr(mEGLDisplay, type, attrib_list); +} + +EGLBoolean FunctionsEGL::destroySyncKHR(EGLSyncKHR sync) +{ + return mFnPtrs->destroySyncKHRPtr(mEGLDisplay, sync); +} + +EGLint FunctionsEGL::clientWaitSyncKHR(EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) +{ + return mFnPtrs->clientWaitSyncKHRPtr(mEGLDisplay, sync, flags, timeout); +} + +EGLBoolean FunctionsEGL::getSyncAttribKHR(EGLSyncKHR sync, EGLint attribute, EGLint *value) +{ + return mFnPtrs->getSyncAttribKHRPtr(mEGLDisplay, sync, attribute, value); +} +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.h new file mode 100755 index 000000000..43d5622e6 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.h @@ -0,0 +1,91 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FunctionsEGL.h: Defines the FunctionsEGL class to load functions and data from EGL + +#ifndef LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGL_H_ +#define LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGL_H_ + +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#include <string> +#include <vector> + +#include "libANGLE/Error.h" + +namespace rx +{ + +class FunctionsGL; + +class FunctionsEGL +{ + public: + FunctionsEGL(); + virtual ~FunctionsEGL(); + + int majorVersion; + int minorVersion; + + egl::Error initialize(EGLNativeDisplayType nativeDisplay); + egl::Error terminate(); + + virtual void *getProcAddress(const char *name) const = 0; + + FunctionsGL *makeFunctionsGL() const; + bool hasExtension(const char *extension) const; + EGLDisplay getDisplay() const; + EGLint getError() const; + + EGLBoolean chooseConfig(EGLint const *attrib_list, + EGLConfig *configs, + EGLint config_size, + EGLint *num_config) const; + EGLBoolean getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) const; + EGLContext createContext(EGLConfig config, + EGLContext share_context, + EGLint const *attrib_list) const; + EGLSurface createPbufferSurface(EGLConfig config, const EGLint *attrib_list) const; + EGLSurface createWindowSurface(EGLConfig config, + EGLNativeWindowType win, + const EGLint *attrib_list) const; + EGLBoolean destroyContext(EGLContext context) const; + EGLBoolean destroySurface(EGLSurface surface) const; + EGLBoolean makeCurrent(EGLSurface surface, EGLContext context) const; + const char *queryString(EGLint name) const; + EGLBoolean querySurface(EGLSurface surface, EGLint attribute, EGLint *value) const; + EGLBoolean swapBuffers(EGLSurface surface) const; + + EGLBoolean bindTexImage(EGLSurface surface, EGLint buffer) const; + EGLBoolean releaseTexImage(EGLSurface surface, EGLint buffer) const; + EGLBoolean swapInterval(EGLint interval) const; + + EGLImageKHR createImageKHR(EGLContext context, + EGLenum target, + EGLClientBuffer buffer, + const EGLint *attrib_list) const; + EGLBoolean destroyImageKHR(EGLImageKHR image) const; + + EGLSyncKHR createSyncKHR(EGLenum type, const EGLint *attrib_list); + EGLBoolean destroySyncKHR(EGLSyncKHR sync); + EGLint clientWaitSyncKHR(EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout); + EGLBoolean getSyncAttribKHR(EGLSyncKHR sync, EGLint attribute, EGLint *value); + + private: + // So as to isolate from angle we do not include angleutils.h and cannot + // use angle::NonCopyable so we replicated it here instead. + FunctionsEGL(const FunctionsEGL &) = delete; + void operator=(const FunctionsEGL &) = delete; + + struct EGLDispatchTable; + EGLDispatchTable *mFnPtrs; + EGLDisplay mEGLDisplay; + std::vector<std::string> mExtensions; +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.cpp new file mode 100755 index 000000000..e6ef45d8d --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.cpp @@ -0,0 +1,74 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FunctionsEGLDL.cpp: Implements the FunctionsEGLDL class. + +#include "libANGLE/renderer/gl/egl/FunctionsEGLDL.h" + +#include <dlfcn.h> + +namespace rx +{ + +DynamicLib::DynamicLib() : handle(nullptr) +{ +} + +DynamicLib::~DynamicLib() +{ + if (handle) + { + dlclose(handle); + handle = nullptr; + } +} + +// Due to a bug in Mesa (or maybe libdl) it's not possible to close and re-open libEGL.so +// an arbitrary number of times. End2end tests would die after a couple hundred tests. +// So we use a static object with a destructor to close the library when the program exits. +// TODO(fjhenigman) File a bug and put a link here. +DynamicLib FunctionsEGLDL::sNativeLib; + +FunctionsEGLDL::FunctionsEGLDL() : mGetProcAddressPtr(nullptr) +{ +} + +FunctionsEGLDL::~FunctionsEGLDL() +{ +} + +egl::Error FunctionsEGLDL::initialize(EGLNativeDisplayType nativeDisplay, const char *libName) +{ + if (!sNativeLib.handle) + { + sNativeLib.handle = dlopen(libName, RTLD_NOW); + if (!sNativeLib.handle) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not dlopen native EGL: %s", dlerror()); + } + } + + mGetProcAddressPtr = + reinterpret_cast<PFNEGLGETPROCADDRESSPROC>(dlsym(sNativeLib.handle, "eglGetProcAddress")); + if (!mGetProcAddressPtr) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not find eglGetProcAddress"); + } + + return FunctionsEGL::initialize(nativeDisplay); +} + +void *FunctionsEGLDL::getProcAddress(const char *name) const +{ + void *f = reinterpret_cast<void *>(mGetProcAddressPtr(name)); + if (f) + { + return f; + } + return dlsym(sNativeLib.handle, name); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.h new file mode 100755 index 000000000..d69df77ab --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.h @@ -0,0 +1,42 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FunctionsEGL.h: Implements FunctionsEGL with dlopen/dlsym/dlclose + +#ifndef LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGLDL_H_ +#define LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGLDL_H_ + +#include "libANGLE/renderer/gl/egl/FunctionsEGL.h" +#include "libANGLE/renderer/gl/egl/functionsegl_typedefs.h" + +namespace rx +{ + +class DynamicLib final +{ + public: + void *handle; + + DynamicLib(); + ~DynamicLib(); +}; + +class FunctionsEGLDL : public FunctionsEGL +{ + public: + FunctionsEGLDL(); + ~FunctionsEGLDL() override; + + egl::Error initialize(EGLNativeDisplayType nativeDisplay, const char *libName); + void *getProcAddress(const char *name) const override; + + private: + PFNEGLGETPROCADDRESSPROC mGetProcAddressPtr; + static DynamicLib sNativeLib; +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGLDL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.cpp new file mode 100755 index 000000000..68da9f2b8 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.cpp @@ -0,0 +1,39 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// PbufferSurfaceEGL.h: EGL implementation of egl::Surface for pbuffers + +#include "libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h" + +namespace rx +{ + +PbufferSurfaceEGL::PbufferSurfaceEGL(const egl::SurfaceState &state, + const FunctionsEGL *egl, + EGLConfig config, + const std::vector<EGLint> &attribList, + EGLContext context, + RendererGL *renderer) + : SurfaceEGL(state, egl, config, attribList, context, renderer) +{ +} + +PbufferSurfaceEGL::~PbufferSurfaceEGL() +{ +} + +egl::Error PbufferSurfaceEGL::initialize() +{ + mSurface = mEGL->createPbufferSurface(mConfig, mAttribList.data()); + if (mSurface == EGL_NO_SURFACE) + { + return egl::Error(mEGL->getError(), "eglCreatePbufferSurface failed"); + } + + return egl::Error(EGL_SUCCESS); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h new file mode 100755 index 000000000..ff557f2ca --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h @@ -0,0 +1,36 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// PbufferSurfaceEGL.h: EGL implementation of egl::Surface for pbuffers + +#ifndef LIBANGLE_RENDERER_GL_EGL_PBUFFERSURFACEEGL_H_ +#define LIBANGLE_RENDERER_GL_EGL_PBUFFERSURFACEEGL_H_ + +#include <vector> +#include <EGL/egl.h> + +#include "libANGLE/renderer/gl/egl/SurfaceEGL.h" + +namespace rx +{ + +class PbufferSurfaceEGL : public SurfaceEGL +{ + public: + PbufferSurfaceEGL(const egl::SurfaceState &state, + const FunctionsEGL *egl, + EGLConfig config, + const std::vector<EGLint> &attribList, + EGLContext context, + RendererGL *renderer); + ~PbufferSurfaceEGL() override; + + egl::Error initialize() override; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_GL_EGL_PBUFFERSURFACEEGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp new file mode 100755 index 000000000..693b61c9c --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp @@ -0,0 +1,132 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SurfaceEGL.cpp: EGL implementation of egl::Surface + +#include "libANGLE/renderer/gl/egl/SurfaceEGL.h" + +#include "common/debug.h" + +namespace rx +{ + +SurfaceEGL::SurfaceEGL(const egl::SurfaceState &state, + const FunctionsEGL *egl, + EGLConfig config, + const std::vector<EGLint> &attribList, + EGLContext context, + RendererGL *renderer) + : SurfaceGL(state, renderer), + mEGL(egl), + mConfig(config), + mAttribList(attribList), + mSurface(EGL_NO_SURFACE), + mContext(context) +{ +} + +SurfaceEGL::~SurfaceEGL() +{ + if (mSurface != EGL_NO_SURFACE) + { + EGLBoolean success = mEGL->destroySurface(mSurface); + ASSERT(success == EGL_TRUE); + } +} + +egl::Error SurfaceEGL::makeCurrent() +{ + EGLBoolean success = mEGL->makeCurrent(mSurface, mContext); + if (success == EGL_FALSE) + { + return egl::Error(mEGL->getError(), "eglMakeCurrent failed"); + } + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceEGL::swap() +{ + EGLBoolean success = mEGL->swapBuffers(mSurface); + if (success == EGL_FALSE) + { + return egl::Error(mEGL->getError(), "eglSwapBuffers failed"); + } + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceEGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_BAD_SURFACE); +} + +egl::Error SurfaceEGL::querySurfacePointerANGLE(EGLint attribute, void **value) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_BAD_SURFACE); +} + +egl::Error SurfaceEGL::bindTexImage(gl::Texture *texture, EGLint buffer) +{ + EGLBoolean success = mEGL->bindTexImage(mSurface, buffer); + if (success == EGL_FALSE) + { + return egl::Error(mEGL->getError(), "eglBindTexImage failed"); + } + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceEGL::releaseTexImage(EGLint buffer) +{ + EGLBoolean success = mEGL->releaseTexImage(mSurface, buffer); + if (success == EGL_FALSE) + { + return egl::Error(mEGL->getError(), "eglReleaseTexImage failed"); + } + return egl::Error(EGL_SUCCESS); +} + +void SurfaceEGL::setSwapInterval(EGLint interval) +{ + EGLBoolean success = mEGL->swapInterval(interval); + if (success == EGL_FALSE) + { + ERR("eglSwapInterval error 0x%04x", mEGL->getError()); + ASSERT(false); + } +} + +EGLint SurfaceEGL::getWidth() const +{ + EGLint value; + EGLBoolean success = mEGL->querySurface(mSurface, EGL_WIDTH, &value); + ASSERT(success == EGL_TRUE); + return value; +} + +EGLint SurfaceEGL::getHeight() const +{ + EGLint value; + EGLBoolean success = mEGL->querySurface(mSurface, EGL_HEIGHT, &value); + ASSERT(success == EGL_TRUE); + return value; +} + +EGLint SurfaceEGL::isPostSubBufferSupported() const +{ + UNIMPLEMENTED(); + return 0; +} + +EGLint SurfaceEGL::getSwapBehavior() const +{ + EGLint value; + EGLBoolean success = mEGL->querySurface(mSurface, EGL_SWAP_BEHAVIOR, &value); + ASSERT(success == EGL_TRUE); + return value; +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.h new file mode 100755 index 000000000..ee1568c9e --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.h @@ -0,0 +1,55 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SurfaceEGL.h: common interface for EGL surfaces + +#ifndef LIBANGLE_RENDERER_GL_EGL_SURFACEEGL_H_ +#define LIBANGLE_RENDERER_GL_EGL_SURFACEEGL_H_ + +#include <EGL/egl.h> + +#include "libANGLE/renderer/gl/SurfaceGL.h" +#include "libANGLE/renderer/gl/egl/FunctionsEGL.h" + +namespace rx +{ + +class SurfaceEGL : public SurfaceGL +{ + public: + SurfaceEGL(const egl::SurfaceState &state, + const FunctionsEGL *egl, + EGLConfig config, + const std::vector<EGLint> &attribList, + EGLContext context, + RendererGL *renderer); + ~SurfaceEGL() override; + + egl::Error makeCurrent() override; + egl::Error swap() override; + egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; + egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; + egl::Error releaseTexImage(EGLint buffer) override; + void setSwapInterval(EGLint interval) override; + EGLint getWidth() const override; + EGLint getHeight() const override; + EGLint isPostSubBufferSupported() const override; + EGLint getSwapBehavior() const override; + + protected: + const FunctionsEGL *mEGL; + EGLConfig mConfig; + std::vector<EGLint> mAttribList; + EGLSurface mSurface; + + private: + EGLContext mContext; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_GL_EGL_SURFACEEGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.cpp new file mode 100755 index 000000000..db226ee18 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.cpp @@ -0,0 +1,40 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// WindowSurfaceEGL.h: EGL implementation of egl::Surface for windows + +#include "libANGLE/renderer/gl/egl/WindowSurfaceEGL.h" + +namespace rx +{ + +WindowSurfaceEGL::WindowSurfaceEGL(const egl::SurfaceState &state, + const FunctionsEGL *egl, + EGLConfig config, + EGLNativeWindowType window, + const std::vector<EGLint> &attribList, + EGLContext context, + RendererGL *renderer) + : SurfaceEGL(state, egl, config, attribList, context, renderer), mWindow(window) +{ +} + +WindowSurfaceEGL::~WindowSurfaceEGL() +{ +} + +egl::Error WindowSurfaceEGL::initialize() +{ + mSurface = mEGL->createWindowSurface(mConfig, mWindow, mAttribList.data()); + if (mSurface == EGL_NO_SURFACE) + { + return egl::Error(mEGL->getError(), "eglCreateWindowSurface failed"); + } + + return egl::Error(EGL_SUCCESS); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.h new file mode 100755 index 000000000..f9da4c27c --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.h @@ -0,0 +1,37 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// WindowSurfaceEGL.h: EGL implementation of egl::Surface for windows + +#ifndef LIBANGLE_RENDERER_GL_EGL_WINDOWSURFACEEGL_H_ +#define LIBANGLE_RENDERER_GL_EGL_WINDOWSURFACEEGL_H_ + +#include "libANGLE/renderer/gl/egl/SurfaceEGL.h" + +namespace rx +{ + +class WindowSurfaceEGL : public SurfaceEGL +{ + public: + WindowSurfaceEGL(const egl::SurfaceState &state, + const FunctionsEGL *egl, + EGLConfig config, + EGLNativeWindowType window, + const std::vector<EGLint> &attribList, + EGLContext context, + RendererGL *renderer); + ~WindowSurfaceEGL() override; + + egl::Error initialize() override; + + private: + EGLNativeWindowType mWindow; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_GL_EGL_WINDOWSURFACEEGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp new file mode 100755 index 000000000..b689578c9 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp @@ -0,0 +1,385 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayAndroid.cpp: Android implementation of egl::Display + +#include <android/native_window.h> + +#include "common/debug.h" +#include "libANGLE/Display.h" +#include "libANGLE/renderer/gl/renderergl_utils.h" +#include "libANGLE/renderer/gl/egl/android/DisplayAndroid.h" +#include "libANGLE/renderer/gl/egl/FunctionsEGLDL.h" +#include "libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h" +#include "libANGLE/renderer/gl/egl/WindowSurfaceEGL.h" + +namespace +{ +const char *GetEGLPath() +{ +#if defined(__LP64__) + return "/system/lib64/libEGL.so"; +#else + return "/system/lib/libEGL.so"; +#endif +} +} // namespace + +namespace rx +{ + +DisplayAndroid::DisplayAndroid() : DisplayEGL(), mDummyPbuffer(EGL_NO_SURFACE) +{ +} + +DisplayAndroid::~DisplayAndroid() +{ +} + +egl::Error DisplayAndroid::initialize(egl::Display *display) +{ + FunctionsEGLDL *egl = new FunctionsEGLDL(); + mEGL = egl; + ANGLE_TRY(egl->initialize(display->getNativeDisplayId(), GetEGLPath())); + + gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion); + ASSERT(eglVersion >= gl::Version(1, 4)); + + static_assert(EGL_OPENGL_ES3_BIT == EGL_OPENGL_ES3_BIT_KHR, "Extension define must match core"); + EGLint esBit = (eglVersion >= gl::Version(1, 5) || mEGL->hasExtension("EGL_KHR_create_context")) + ? EGL_OPENGL_ES3_BIT + : EGL_OPENGL_ES2_BIT; + + // clang-format off + mConfigAttribList = + { + // Choose RGBA8888 + EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + // EGL1.5 spec Section 2.2 says that depth, multisample and stencil buffer depths + // must match for contexts to be compatible. + EGL_DEPTH_SIZE, 24, + EGL_STENCIL_SIZE, 8, + EGL_SAMPLE_BUFFERS, 0, + // Android doesn't support pixmaps + EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, + EGL_CONFIG_CAVEAT, EGL_NONE, + EGL_CONFORMANT, esBit, + EGL_RENDERABLE_TYPE, esBit, + EGL_NONE + }; + // clang-format on + EGLint numConfig; + + EGLBoolean success = mEGL->chooseConfig(mConfigAttribList.data(), &mConfig, 1, &numConfig); + if (success == EGL_FALSE) + { + return egl::Error(mEGL->getError(), "eglChooseConfig failed"); + } + + ANGLE_TRY(initializeContext(display->getAttributeMap())); + + int dummyPbufferAttribs[] = { + EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, + }; + mDummyPbuffer = mEGL->createPbufferSurface(mConfig, dummyPbufferAttribs); + if (mDummyPbuffer == EGL_NO_SURFACE) + { + return egl::Error(mEGL->getError(), "eglCreatePbufferSurface failed"); + } + + success = mEGL->makeCurrent(mDummyPbuffer, mContext); + if (success == EGL_FALSE) + { + return egl::Error(mEGL->getError(), "eglMakeCurrent failed"); + } + + mFunctionsGL = mEGL->makeFunctionsGL(); + mFunctionsGL->initialize(); + + return DisplayGL::initialize(display); +} + +void DisplayAndroid::terminate() +{ + DisplayGL::terminate(); + + EGLBoolean success = mEGL->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (success == EGL_FALSE) + { + ERR("eglMakeCurrent error 0x%04x", mEGL->getError()); + } + + if (mDummyPbuffer != EGL_NO_SURFACE) + { + success = mEGL->destroySurface(mDummyPbuffer); + mDummyPbuffer = EGL_NO_SURFACE; + if (success == EGL_FALSE) + { + ERR("eglDestroySurface error 0x%04x", mEGL->getError()); + } + } + + if (mContext != EGL_NO_CONTEXT) + { + success = mEGL->destroyContext(mContext); + mContext = EGL_NO_CONTEXT; + if (success == EGL_FALSE) + { + ERR("eglDestroyContext error 0x%04x", mEGL->getError()); + } + } + + egl::Error result = mEGL->terminate(); + if (result.isError()) + { + ERR("eglTerminate error 0x%04x", result.getCode()); + } + + SafeDelete(mEGL); + SafeDelete(mFunctionsGL); +} + +SurfaceImpl *DisplayAndroid::createWindowSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) +{ + EGLConfig config; + EGLint numConfig; + EGLBoolean success; + + const EGLint configAttribList[] = {EGL_CONFIG_ID, mConfigIds[configuration->configID], + EGL_NONE}; + success = mEGL->chooseConfig(configAttribList, &config, 1, &numConfig); + ASSERT(success && numConfig == 1); + + return new WindowSurfaceEGL(state, mEGL, config, window, attribs.toIntVector(), mContext, + getRenderer()); +} + +SurfaceImpl *DisplayAndroid::createPbufferSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + const egl::AttributeMap &attribs) +{ + EGLConfig config; + EGLint numConfig; + EGLBoolean success; + + const EGLint configAttribList[] = {EGL_CONFIG_ID, mConfigIds[configuration->configID], + EGL_NONE}; + success = mEGL->chooseConfig(configAttribList, &config, 1, &numConfig); + ASSERT(success && numConfig == 1); + + return new PbufferSurfaceEGL(state, mEGL, config, attribs.toIntVector(), mContext, + getRenderer()); +} + +SurfaceImpl *DisplayAndroid::createPbufferFromClientBuffer(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) +{ + UNIMPLEMENTED(); + return nullptr; +} + +SurfaceImpl *DisplayAndroid::createPixmapSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) +{ + UNIMPLEMENTED(); + return nullptr; +} + +ImageImpl *DisplayAndroid::createImage(EGLenum target, + egl::ImageSibling *buffer, + const egl::AttributeMap &attribs) +{ + UNIMPLEMENTED(); + return DisplayGL::createImage(target, buffer, attribs); +} + +template <typename T> +void DisplayAndroid::getConfigAttrib(EGLConfig config, EGLint attribute, T *value) const +{ + EGLint tmp; + EGLBoolean success = mEGL->getConfigAttrib(config, attribute, &tmp); + ASSERT(success == EGL_TRUE); + *value = tmp; +} + +egl::ConfigSet DisplayAndroid::generateConfigs() +{ + egl::ConfigSet configSet; + mConfigIds.clear(); + + EGLint numConfigs; + EGLBoolean success = mEGL->chooseConfig(mConfigAttribList.data(), nullptr, 0, &numConfigs); + ASSERT(success == EGL_TRUE && numConfigs > 0); + + std::vector<EGLConfig> configs(numConfigs); + EGLint numConfigs2; + success = + mEGL->chooseConfig(mConfigAttribList.data(), configs.data(), numConfigs, &numConfigs2); + ASSERT(success == EGL_TRUE && numConfigs2 == numConfigs); + + for (int i = 0; i < numConfigs; i++) + { + egl::Config config; + + getConfigAttrib(configs[i], EGL_BUFFER_SIZE, &config.bufferSize); + getConfigAttrib(configs[i], EGL_RED_SIZE, &config.redSize); + getConfigAttrib(configs[i], EGL_GREEN_SIZE, &config.greenSize); + getConfigAttrib(configs[i], EGL_BLUE_SIZE, &config.blueSize); + getConfigAttrib(configs[i], EGL_LUMINANCE_SIZE, &config.luminanceSize); + getConfigAttrib(configs[i], EGL_ALPHA_SIZE, &config.alphaSize); + getConfigAttrib(configs[i], EGL_ALPHA_MASK_SIZE, &config.alphaMaskSize); + getConfigAttrib(configs[i], EGL_BIND_TO_TEXTURE_RGB, &config.bindToTextureRGB); + getConfigAttrib(configs[i], EGL_BIND_TO_TEXTURE_RGBA, &config.bindToTextureRGBA); + getConfigAttrib(configs[i], EGL_COLOR_BUFFER_TYPE, &config.colorBufferType); + getConfigAttrib(configs[i], EGL_CONFIG_CAVEAT, &config.configCaveat); + getConfigAttrib(configs[i], EGL_CONFIG_ID, &config.configID); + getConfigAttrib(configs[i], EGL_CONFORMANT, &config.conformant); + getConfigAttrib(configs[i], EGL_DEPTH_SIZE, &config.depthSize); + getConfigAttrib(configs[i], EGL_LEVEL, &config.level); + getConfigAttrib(configs[i], EGL_MAX_PBUFFER_WIDTH, &config.maxPBufferWidth); + getConfigAttrib(configs[i], EGL_MAX_PBUFFER_HEIGHT, &config.maxPBufferHeight); + getConfigAttrib(configs[i], EGL_MAX_PBUFFER_PIXELS, &config.maxPBufferPixels); + getConfigAttrib(configs[i], EGL_MAX_SWAP_INTERVAL, &config.maxSwapInterval); + getConfigAttrib(configs[i], EGL_MIN_SWAP_INTERVAL, &config.minSwapInterval); + getConfigAttrib(configs[i], EGL_NATIVE_RENDERABLE, &config.nativeRenderable); + getConfigAttrib(configs[i], EGL_NATIVE_VISUAL_ID, &config.nativeVisualID); + getConfigAttrib(configs[i], EGL_NATIVE_VISUAL_TYPE, &config.nativeVisualType); + getConfigAttrib(configs[i], EGL_RENDERABLE_TYPE, &config.renderableType); + getConfigAttrib(configs[i], EGL_SAMPLE_BUFFERS, &config.sampleBuffers); + getConfigAttrib(configs[i], EGL_SAMPLES, &config.samples); + getConfigAttrib(configs[i], EGL_STENCIL_SIZE, &config.stencilSize); + getConfigAttrib(configs[i], EGL_SURFACE_TYPE, &config.surfaceType); + getConfigAttrib(configs[i], EGL_TRANSPARENT_TYPE, &config.transparentType); + getConfigAttrib(configs[i], EGL_TRANSPARENT_RED_VALUE, &config.transparentRedValue); + getConfigAttrib(configs[i], EGL_TRANSPARENT_GREEN_VALUE, &config.transparentGreenValue); + getConfigAttrib(configs[i], EGL_TRANSPARENT_BLUE_VALUE, &config.transparentBlueValue); + + if (config.colorBufferType == EGL_RGB_BUFFER) + { + if (config.redSize == 8 && config.greenSize == 8 && config.blueSize == 8 && + config.alphaSize == 8) + { + config.renderTargetFormat = GL_RGBA8; + } + else if (config.redSize == 8 && config.greenSize == 8 && config.blueSize == 8 && + config.alphaSize == 0) + { + config.renderTargetFormat = GL_RGB8; + } + else if (config.redSize == 5 && config.greenSize == 6 && config.blueSize == 5 && + config.alphaSize == 0) + { + config.renderTargetFormat = GL_RGB565; + } + else + { + UNREACHABLE(); + } + } + else + { + UNREACHABLE(); + } + + if (config.depthSize == 0 && config.stencilSize == 0) + { + config.depthStencilFormat = GL_ZERO; + } + else if (config.depthSize == 16 && config.stencilSize == 0) + { + config.depthStencilFormat = GL_DEPTH_COMPONENT16; + } + else if (config.depthSize == 24 && config.stencilSize == 0) + { + config.depthStencilFormat = GL_DEPTH_COMPONENT24; + } + else if (config.depthSize == 24 && config.stencilSize == 8) + { + config.depthStencilFormat = GL_DEPTH24_STENCIL8; + } + else if (config.depthSize == 0 && config.stencilSize == 8) + { + config.depthStencilFormat = GL_STENCIL_INDEX8; + } + else + { + UNREACHABLE(); + } + + config.matchNativePixmap = EGL_NONE; + config.optimalOrientation = 0; + + int internalId = configSet.add(config); + mConfigIds[internalId] = config.configID; + } + + return configSet; +} + +bool DisplayAndroid::testDeviceLost() +{ + return false; +} + +egl::Error DisplayAndroid::restoreLostDevice() +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +bool DisplayAndroid::isValidNativeWindow(EGLNativeWindowType window) const +{ + return ANativeWindow_getFormat(window) >= 0; +} + +egl::Error DisplayAndroid::getDevice(DeviceImpl **device) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayAndroid::waitClient() const +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayAndroid::waitNative(EGLint engine, + egl::Surface *drawSurface, + egl::Surface *readSurface) const +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayAndroid::getDriverVersion(std::string *version) const +{ + VendorID vendor = GetVendorID(mFunctionsGL); + + switch (vendor) + { + case VENDOR_ID_QUALCOMM: + *version = reinterpret_cast<const char *>(mFunctionsGL->getString(GL_VERSION)); + return egl::Error(EGL_SUCCESS); + default: + *version = ""; + return egl::Error(EGL_SUCCESS); + } +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h b/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h new file mode 100755 index 000000000..0be9bb465 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h @@ -0,0 +1,78 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayAndroid.h: Android implementation of egl::Display + +#ifndef LIBANGLE_RENDERER_GL_EGL_ANDROID_DISPLAYANDROID_H_ +#define LIBANGLE_RENDERER_GL_EGL_ANDROID_DISPLAYANDROID_H_ + +#include <map> +#include <string> +#include <vector> + +#include "libANGLE/renderer/gl/egl/DisplayEGL.h" + +namespace rx +{ + +class DisplayAndroid : public DisplayEGL +{ + public: + DisplayAndroid(); + ~DisplayAndroid() override; + + egl::Error initialize(egl::Display *display) override; + void terminate() override; + + SurfaceImpl *createWindowSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) override; + + ImageImpl *createImage(EGLenum target, + egl::ImageSibling *buffer, + const egl::AttributeMap &attribs) override; + + egl::ConfigSet generateConfigs() override; + + bool testDeviceLost() override; + egl::Error restoreLostDevice() override; + + bool isValidNativeWindow(EGLNativeWindowType window) const override; + + egl::Error getDevice(DeviceImpl **device) override; + + egl::Error waitClient() const override; + egl::Error waitNative(EGLint engine, + egl::Surface *drawSurface, + egl::Surface *readSurface) const override; + + egl::Error getDriverVersion(std::string *version) const override; + + private: + template <typename T> + void getConfigAttrib(EGLConfig config, EGLint attribute, T *value) const; + + std::vector<EGLint> mConfigAttribList; + std::map<EGLint, EGLint> mConfigIds; + EGLSurface mDummyPbuffer; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_GL_EGL_ANDROID_DISPLAYANDROID_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/functionsegl_typedefs.h b/gfx/angle/src/libANGLE/renderer/gl/egl/functionsegl_typedefs.h new file mode 100755 index 000000000..78f9009bf --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/functionsegl_typedefs.h @@ -0,0 +1,131 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// functionsegl_typedefs.h: Typedefs of EGL functions. + +#ifndef LIBANGLE_RENDERER_GL_EGL_FUNCTIONSEGLTYPEDEFS_H_ +#define LIBANGLE_RENDERER_GL_EGL_FUNCTIONSEGLTYPEDEFS_H_ + +#include <EGL/egl.h> + +namespace rx +{ +// EGL 1.0 +typedef EGLBoolean (*PFNEGLCHOOSECONFIGPROC)(EGLDisplay dpy, + const EGLint *attrib_list, + EGLConfig *configs, + EGLint config_size, + EGLint *num_config); +typedef EGLBoolean (*PFNEGLCOPYBUFFERSPROC)(EGLDisplay dpy, + EGLSurface surface, + EGLNativePixmapType target); +typedef EGLContext (*PFNEGLCREATECONTEXTPROC)(EGLDisplay dpy, + EGLConfig config, + EGLContext share_context, + const EGLint *attrib_list); +typedef EGLSurface (*PFNEGLCREATEPBUFFERSURFACEPROC)(EGLDisplay dpy, + EGLConfig config, + const EGLint *attrib_list); +typedef EGLSurface (*PFNEGLCREATEPIXMAPSURFACEPROC)(EGLDisplay dpy, + EGLConfig config, + EGLNativePixmapType pixmap, + const EGLint *attrib_list); +typedef EGLSurface (*PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay dpy, + EGLConfig config, + EGLNativeWindowType win, + const EGLint *attrib_list); +typedef EGLBoolean (*PFNEGLDESTROYCONTEXTPROC)(EGLDisplay dpy, EGLContext ctx); +typedef EGLBoolean (*PFNEGLDESTROYSURFACEPROC)(EGLDisplay dpy, EGLSurface surface); +typedef EGLBoolean (*PFNEGLGETCONFIGATTRIBPROC)(EGLDisplay dpy, + EGLConfig config, + EGLint attribute, + EGLint *value); +typedef EGLBoolean (*PFNEGLGETCONFIGSPROC)(EGLDisplay dpy, + EGLConfig *configs, + EGLint config_size, + EGLint *num_config); +typedef EGLDisplay (*PFNEGLGETCURRENTDISPLAYPROC)(void); +typedef EGLSurface (*PFNEGLGETCURRENTSURFACEPROC)(EGLint readdraw); +typedef EGLDisplay (*PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType display_id); +typedef EGLint (*PFNEGLGETERRORPROC)(void); +typedef __eglMustCastToProperFunctionPointerType (*PFNEGLGETPROCADDRESSPROC)(const char *procname); +typedef EGLBoolean (*PFNEGLINITIALIZEPROC)(EGLDisplay dpy, EGLint *major, EGLint *minor); +typedef EGLBoolean (*PFNEGLMAKECURRENTPROC)(EGLDisplay dpy, + EGLSurface draw, + EGLSurface read, + EGLContext ctx); +typedef EGLBoolean (*PFNEGLQUERYCONTEXTPROC)(EGLDisplay dpy, + EGLContext ctx, + EGLint attribute, + EGLint *value); +typedef const char *(*PFNEGLQUERYSTRINGPROC)(EGLDisplay dpy, EGLint name); +typedef EGLBoolean (*PFNEGLQUERYSURFACEPROC)(EGLDisplay dpy, + EGLSurface surface, + EGLint attribute, + EGLint *value); +typedef EGLBoolean (*PFNEGLSWAPBUFFERSPROC)(EGLDisplay dpy, EGLSurface surface); +typedef EGLBoolean (*PFNEGLTERMINATEPROC)(EGLDisplay dpy); +typedef EGLBoolean (*PFNEGLWAITGLPROC)(void); +typedef EGLBoolean (*PFNEGLWAITNATIVEPROC)(EGLint engine); + +// EGL 1.1 +typedef EGLBoolean (*PFNEGLBINDTEXIMAGEPROC)(EGLDisplay dpy, EGLSurface surface, EGLint buffer); +typedef EGLBoolean (*PFNEGLRELEASETEXIMAGEPROC)(EGLDisplay dpy, EGLSurface surface, EGLint buffer); +typedef EGLBoolean (*PFNEGLSURFACEATTRIBPROC)(EGLDisplay dpy, + EGLSurface surface, + EGLint attribute, + EGLint value); +typedef EGLBoolean (*PFNEGLSWAPINTERVALPROC)(EGLDisplay dpy, EGLint interval); + +// EGL 1.2 +typedef EGLBoolean (*PFNEGLBINDAPIPROC)(EGLenum api); +typedef EGLenum (*PFNEGLQUERYAPIPROC)(void); +typedef EGLSurface (*PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC)(EGLDisplay dpy, + EGLenum buftype, + EGLClientBuffer buffer, + EGLConfig config, + const EGLint *attrib_list); +typedef EGLBoolean (*PFNEGLRELEASETHREADPROC)(void); +typedef EGLBoolean (*PFNEGLWAITCLIENTPROC)(void); + +// EGL 1.3 + +// EGL 1.4 +typedef EGLContext (*PFNEGLGETCURRENTCONTEXTPROC)(void); + +// EGL 1.5 +typedef EGLSync (*PFNEGLCREATESYNCPROC)(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list); +typedef EGLBoolean (*PFNEGLDESTROYSYNCPROC)(EGLDisplay dpy, EGLSync sync); +typedef EGLint (*PFNEGLCLIENTWAITSYNCPROC)(EGLDisplay dpy, + EGLSync sync, + EGLint flags, + EGLTime timeout); +typedef EGLBoolean (*PFNEGLGETSYNCATTRIBPROC)(EGLDisplay dpy, + EGLSync sync, + EGLint attribute, + EGLAttrib *value); +typedef EGLImage (*PFNEGLCREATEIMAGEPROC)(EGLDisplay dpy, + EGLContext ctx, + EGLenum target, + EGLClientBuffer buffer, + const EGLAttrib *attrib_list); +typedef EGLBoolean (*PFNEGLDESTROYIMAGEPROC)(EGLDisplay dpy, EGLImage image); +typedef EGLDisplay (*PFNEGLGETPLATFORMDISPLAYPROC)(EGLenum platform, + void *native_display, + const EGLAttrib *attrib_list); +typedef EGLSurface (*PFNEGLCREATEPLATFORMWINDOWSURFACEPROC)(EGLDisplay dpy, + EGLConfig config, + void *native_window, + const EGLAttrib *attrib_list); +typedef EGLSurface (*PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC)(EGLDisplay dpy, + EGLConfig config, + void *native_pixmap, + const EGLAttrib *attrib_list); +typedef EGLBoolean (*PFNEGLWAITSYNCPROC)(EGLDisplay dpy, EGLSync sync, EGLint flags); + +} // namespace rx + +#endif // LIBANGLE_RENDERER_GL_EGL_FUNCTIONSEGLTYPEDEFS_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp new file mode 100755 index 000000000..01549fcfa --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp @@ -0,0 +1,945 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayOzone.cpp: Ozone implementation of egl::Display + +#include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h" + +#include <fcntl.h> +#include <poll.h> +#include <iostream> +#include <unistd.h> +#include <sys/time.h> + +#include <EGL/eglext.h> + +#include <gbm.h> +#include <drm_fourcc.h> + +#include "common/debug.h" +#include "libANGLE/Config.h" +#include "libANGLE/Display.h" +#include "libANGLE/Surface.h" +#include "libANGLE/renderer/gl/FramebufferGL.h" +#include "libANGLE/renderer/gl/RendererGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" +#include "libANGLE/renderer/gl/egl/FunctionsEGLDL.h" +#include "libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h" +#include "platform/Platform.h" + +// ARM-specific extension needed to make Mali GPU behave - not in any +// published header file. +#ifndef EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM +#define EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM 0x328A +#endif + +#ifndef EGL_NO_CONFIG_MESA +#define EGL_NO_CONFIG_MESA ((EGLConfig)0) +#endif + +namespace +{ + +EGLint UnsignedToSigned(uint32_t u) +{ + return *reinterpret_cast<const EGLint *>(&u); +} + +drmModeModeInfoPtr ChooseMode(drmModeConnectorPtr conn) +{ + drmModeModeInfoPtr mode = nullptr; + ASSERT(conn); + ASSERT(conn->connection == DRM_MODE_CONNECTED); + // use first preferred mode if any, else end up with last mode in list + for (int i = 0; i < conn->count_modes; ++i) + { + mode = conn->modes + i; + if (mode->type & DRM_MODE_TYPE_PREFERRED) + { + break; + } + } + return mode; +} + +int ChooseCRTC(int fd, drmModeConnectorPtr conn) +{ + for (int i = 0; i < conn->count_encoders; ++i) + { + drmModeEncoderPtr enc = drmModeGetEncoder(fd, conn->encoders[i]); + unsigned long crtcs = enc->possible_crtcs; + drmModeFreeEncoder(enc); + if (crtcs) + { + return __builtin_ctzl(crtcs); + } + } + return -1; +} +} // namespace + +namespace rx +{ + +// TODO(fjhenigman) Implement swap control. Until then this is unused. +SwapControlData::SwapControlData() + : targetSwapInterval(0), maxSwapInterval(-1), currentSwapInterval(-1) +{ +} + +DisplayOzone::Buffer::Buffer(DisplayOzone *display, + uint32_t useFlags, + uint32_t gbmFormat, + uint32_t drmFormat, + uint32_t drmFormatFB, + int depthBits, + int stencilBits) + : mDisplay(display), + mNative(nullptr), + mWidth(0), + mHeight(0), + mDepthBits(depthBits), + mStencilBits(stencilBits), + mUseFlags(useFlags), + mGBMFormat(gbmFormat), + mDRMFormat(drmFormat), + mDRMFormatFB(drmFormatFB), + mBO(nullptr), + mDMABuf(-1), + mHasDRMFB(false), + mDRMFB(0), + mImage(EGL_NO_IMAGE_KHR), + mColorBuffer(0), + mDSBuffer(0), + mGLFB(0), + mTexture(0) +{ +} + +DisplayOzone::Buffer::~Buffer() +{ + mDisplay->mFunctionsGL->deleteFramebuffers(1, &mGLFB); + reset(); +} + +void DisplayOzone::Buffer::reset() +{ + if (mHasDRMFB) + { + int fd = gbm_device_get_fd(mDisplay->mGBM); + drmModeRmFB(fd, mDRMFB); + mHasDRMFB = false; + } + + FunctionsGL *gl = mDisplay->mFunctionsGL; + gl->deleteRenderbuffers(1, &mColorBuffer); + mColorBuffer = 0; + gl->deleteRenderbuffers(1, &mDSBuffer); + mDSBuffer = 0; + + // Here we might destroy the GL framebuffer (mGLFB) but unlike every other resource in Buffer, + // it does not get destroyed (and recreated) because when it is the default framebuffer for + // an ANGLE surface then ANGLE expects it to have the same lifetime as that surface. + + if (mImage != EGL_NO_IMAGE_KHR) + { + mDisplay->mEGL->destroyImageKHR(mImage); + mImage = EGL_NO_IMAGE_KHR; + } + + if (mTexture) + { + gl->deleteTextures(1, &mTexture); + mTexture = 0; + } + + if (mDMABuf >= 0) + { + close(mDMABuf); + mDMABuf = -1; + } + + if (mBO) + { + gbm_bo_destroy(mBO); + mBO = nullptr; + } +} + +bool DisplayOzone::Buffer::resize(int32_t width, int32_t height) +{ + if (mWidth == width && mHeight == height) + { + return true; + } + + reset(); + + if (width <= 0 || height <= 0) + { + return true; + } + + mBO = gbm_bo_create(mDisplay->mGBM, width, height, mGBMFormat, mUseFlags); + if (!mBO) + { + return false; + } + + mDMABuf = gbm_bo_get_fd(mBO); + if (mDMABuf < 0) + { + return false; + } + + // clang-format off + const EGLint attr[] = + { + EGL_WIDTH, width, + EGL_HEIGHT, height, + EGL_LINUX_DRM_FOURCC_EXT, UnsignedToSigned(mDRMFormat), + EGL_DMA_BUF_PLANE0_FD_EXT, mDMABuf, + EGL_DMA_BUF_PLANE0_PITCH_EXT, UnsignedToSigned(gbm_bo_get_stride(mBO)), + EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, + EGL_NONE, + }; + // clang-format on + + mImage = mDisplay->mEGL->createImageKHR(EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attr); + if (mImage == EGL_NO_IMAGE_KHR) + { + return false; + } + + FunctionsGL *gl = mDisplay->mFunctionsGL; + StateManagerGL *sm = mDisplay->getRenderer()->getStateManager(); + + gl->genRenderbuffers(1, &mColorBuffer); + sm->bindRenderbuffer(GL_RENDERBUFFER, mColorBuffer); + gl->eglImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mImage); + + sm->bindFramebuffer(GL_FRAMEBUFFER, mGLFB); + gl->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER, + mColorBuffer); + + if (mDepthBits || mStencilBits) + { + gl->genRenderbuffers(1, &mDSBuffer); + sm->bindRenderbuffer(GL_RENDERBUFFER, mDSBuffer); + gl->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); + } + + if (mDepthBits) + { + gl->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, + mDSBuffer); + } + + if (mStencilBits) + { + gl->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, + mDSBuffer); + } + + mWidth = width; + mHeight = height; + return true; +} + +bool DisplayOzone::Buffer::initialize(const NativeWindow *native) +{ + mNative = native; + mDisplay->mFunctionsGL->genFramebuffers(1, &mGLFB); + return resize(native->width, native->height); +} + +bool DisplayOzone::Buffer::initialize(int width, int height) +{ + mDisplay->mFunctionsGL->genFramebuffers(1, &mGLFB); + return resize(width, height); +} + +void DisplayOzone::Buffer::bindTexImage() +{ + mDisplay->mFunctionsGL->eglImageTargetTexture2DOES(GL_TEXTURE_2D, mImage); +} + +GLuint DisplayOzone::Buffer::getTexture() +{ + // TODO(fjhenigman) Try not to create a new texture every time. That already works on Intel + // and should work on Mali with proper fences. + FunctionsGL *gl = mDisplay->mFunctionsGL; + StateManagerGL *sm = mDisplay->getRenderer()->getStateManager(); + + gl->genTextures(1, &mTexture); + sm->bindTexture(GL_TEXTURE_2D, mTexture); + gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + ASSERT(mImage != EGL_NO_IMAGE_KHR); + gl->eglImageTargetTexture2DOES(GL_TEXTURE_2D, mImage); + return mTexture; +} + +uint32_t DisplayOzone::Buffer::getDRMFB() +{ + if (!mHasDRMFB) + { + int fd = gbm_device_get_fd(mDisplay->mGBM); + uint32_t handles[4] = {gbm_bo_get_handle(mBO).u32}; + uint32_t pitches[4] = {gbm_bo_get_stride(mBO)}; + uint32_t offsets[4] = {0}; + if (drmModeAddFB2(fd, mWidth, mHeight, mDRMFormatFB, handles, pitches, offsets, &mDRMFB, 0)) + { + std::cerr << "drmModeAddFB2 failed" << std::endl; + } + else + { + mHasDRMFB = true; + } + } + + return mDRMFB; +} + +FramebufferGL *DisplayOzone::Buffer::framebufferGL(const gl::FramebufferState &state) +{ + return new FramebufferGL( + mGLFB, state, mDisplay->mFunctionsGL, mDisplay->getRenderer()->getWorkarounds(), + mDisplay->getRenderer()->getBlitter(), mDisplay->getRenderer()->getStateManager()); +} + +void DisplayOzone::Buffer::present() +{ + if (mNative) + { + if (mNative->visible) + { + mDisplay->drawBuffer(this); + } + resize(mNative->width, mNative->height); + } +} + +DisplayOzone::DisplayOzone() + : DisplayEGL(), + mSwapControl(SwapControl::ABSENT), + mMinSwapInterval(0), + mMaxSwapInterval(0), + mCurrentSwapInterval(-1), + mGBM(nullptr), + mConnector(nullptr), + mMode(nullptr), + mCRTC(nullptr), + mSetCRTC(true), + mWidth(0), + mHeight(0), + mScanning(nullptr), + mPending(nullptr), + mDrawing(nullptr), + mUnused(nullptr), + mProgram(0), + mVertexShader(0), + mFragmentShader(0), + mVertexBuffer(0), + mIndexBuffer(0), + mCenterUniform(0), + mWindowSizeUniform(0), + mBorderSizeUniform(0), + mDepthUniform(0) +{ +} + +DisplayOzone::~DisplayOzone() +{ +} + +egl::Error DisplayOzone::initialize(egl::Display *display) +{ + int fd; + char deviceName[30]; + drmModeResPtr resources = nullptr; + + for (int i = 0; i < 9; ++i) + { + snprintf(deviceName, sizeof(deviceName), "/dev/dri/card%d", i); + fd = open(deviceName, O_RDWR | O_CLOEXEC); + if (fd >= 0) + { + resources = drmModeGetResources(fd); + if (resources) + { + if (resources->count_connectors > 0) + { + break; + } + drmModeFreeResources(resources); + resources = nullptr; + } + close(fd); + } + } + if (!resources) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not open drm device."); + } + + mGBM = gbm_create_device(fd); + if (!mGBM) + { + close(fd); + drmModeFreeResources(resources); + return egl::Error(EGL_NOT_INITIALIZED, "Could not create gbm device."); + } + + mConnector = nullptr; + bool monitorConnected = false; + for (int i = 0; !mCRTC && i < resources->count_connectors; ++i) + { + drmModeFreeConnector(mConnector); + mConnector = drmModeGetConnector(fd, resources->connectors[i]); + if (!mConnector || mConnector->connection != DRM_MODE_CONNECTED) + { + continue; + } + monitorConnected = true; + mMode = ChooseMode(mConnector); + if (!mMode) + { + continue; + } + int n = ChooseCRTC(fd, mConnector); + if (n < 0) + { + continue; + } + mCRTC = drmModeGetCrtc(fd, resources->crtcs[n]); + } + drmModeFreeResources(resources); + + if (mCRTC) + { + mWidth = mMode->hdisplay; + mHeight = mMode->vdisplay; + } + else if (!monitorConnected) + { + // Even though there is no monitor to show it, we still do + // everything the same as if there were one, so we need an + // arbitrary size for our buffers. + mWidth = 1280; + mHeight = 1024; + } + else + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to choose mode/crtc."); + } + + // ANGLE builds its executables with an RPATH so they pull in ANGLE's libGL and libEGL. + // Here we need to open the native libEGL. An absolute path would work, but then we + // couldn't use LD_LIBRARY_PATH which is often useful during development. Instead we take + // advantage of the fact that the system lib is available under multiple names (for example + // with a .1 suffix) while Angle only installs libEGL.so. + FunctionsEGLDL *egl = new FunctionsEGLDL(); + mEGL = egl; + ANGLE_TRY(egl->initialize(display->getNativeDisplayId(), "libEGL.so.1")); + + const char *necessaryExtensions[] = { + "EGL_KHR_image_base", "EGL_EXT_image_dma_buf_import", "EGL_KHR_surfaceless_context", + }; + for (auto &ext : necessaryExtensions) + { + if (!mEGL->hasExtension(ext)) + { + return egl::Error(EGL_NOT_INITIALIZED, "need %s", ext); + } + } + + if (mEGL->hasExtension("EGL_MESA_configless_context")) + { + mConfig = EGL_NO_CONFIG_MESA; + } + else + { + // clang-format off + const EGLint attrib[] = + { + // We want RGBA8 and DEPTH24_STENCIL8 + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 24, + EGL_STENCIL_SIZE, 8, + EGL_NONE, + }; + // clang-format on + EGLint numConfig; + EGLConfig config[1]; + if (!mEGL->chooseConfig(attrib, config, 1, &numConfig) || numConfig < 1) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not get EGL config."); + } + mConfig = config[0]; + } + + ANGLE_TRY(initializeContext(display->getAttributeMap())); + + if (!mEGL->makeCurrent(EGL_NO_SURFACE, mContext)) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not make context current."); + } + + mFunctionsGL = mEGL->makeFunctionsGL(); + mFunctionsGL->initialize(); + + return DisplayGL::initialize(display); +} + +void DisplayOzone::pageFlipHandler(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *data) +{ + DisplayOzone *display = reinterpret_cast<DisplayOzone *>(data); + uint64_t tv = tv_sec; + display->pageFlipHandler(sequence, tv * 1000000 + tv_usec); +} + +void DisplayOzone::pageFlipHandler(unsigned int sequence, uint64_t tv) +{ + ASSERT(mPending); + mUnused = mScanning; + mScanning = mPending; + mPending = nullptr; +} + +void DisplayOzone::presentScreen() +{ + if (!mCRTC) + { + // no monitor + return; + } + + // see if pending flip has finished, without blocking + int fd = gbm_device_get_fd(mGBM); + if (mPending) + { + pollfd pfd; + pfd.fd = fd; + pfd.events = POLLIN; + if (poll(&pfd, 1, 0) < 0) + { + std::cerr << "poll failed: " << errno << " " << strerror(errno) << std::endl; + } + if (pfd.revents & POLLIN) + { + drmEventContext event; + event.version = DRM_EVENT_CONTEXT_VERSION; + event.page_flip_handler = pageFlipHandler; + drmHandleEvent(fd, &event); + } + } + + // if pending flip has finished, schedule next one + if (!mPending && mDrawing) + { + flushGL(); + if (mSetCRTC) + { + if (drmModeSetCrtc(fd, mCRTC->crtc_id, mDrawing->getDRMFB(), 0, 0, + &mConnector->connector_id, 1, mMode)) + { + std::cerr << "set crtc failed: " << errno << " " << strerror(errno) << std::endl; + } + mSetCRTC = false; + } + if (drmModePageFlip(fd, mCRTC->crtc_id, mDrawing->getDRMFB(), DRM_MODE_PAGE_FLIP_EVENT, + this)) + { + std::cerr << "page flip failed: " << errno << " " << strerror(errno) << std::endl; + } + mPending = mDrawing; + mDrawing = nullptr; + } +} + +GLuint DisplayOzone::makeShader(GLuint type, const char *src) +{ + FunctionsGL *gl = mFunctionsGL; + GLuint shader = gl->createShader(type); + gl->shaderSource(shader, 1, &src, nullptr); + gl->compileShader(shader); + + GLchar buf[999]; + GLsizei len; + GLint compiled; + gl->getShaderInfoLog(shader, sizeof(buf), &len, buf); + gl->getShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (compiled != GL_TRUE) + { + ANGLEPlatformCurrent()->logError("DisplayOzone shader compilation error:"); + ANGLEPlatformCurrent()->logError(buf); + } + + return shader; +} + +void DisplayOzone::drawWithTexture(Buffer *buffer) +{ + FunctionsGL *gl = mFunctionsGL; + StateManagerGL *sm = getRenderer()->getStateManager(); + + if (!mProgram) + { + const GLchar *vertexSource = + "#version 100\n" + "attribute vec3 vertex;\n" + "uniform vec2 center;\n" + "uniform vec2 windowSize;\n" + "uniform vec2 borderSize;\n" + "uniform float depth;\n" + "varying vec3 texCoord;\n" + "void main()\n" + "{\n" + " vec2 pos = vertex.xy * (windowSize + borderSize * vertex.z);\n" + " gl_Position = vec4(center + pos, depth, 1);\n" + " texCoord = vec3(pos / windowSize * vec2(.5, -.5) + vec2(.5, .5), vertex.z);\n" + "}\n"; + + const GLchar *fragmentSource = + "#version 100\n" + "precision mediump float;\n" + "uniform sampler2D tex;\n" + "varying vec3 texCoord;\n" + "void main()\n" + "{\n" + " if (texCoord.z > 0.)\n" + " {\n" + " float c = abs((texCoord.z * 2.) - 1.);\n" + " gl_FragColor = vec4(c, c, c, 1);\n" + " }\n" + " else\n" + " {\n" + " gl_FragColor = texture2D(tex, texCoord.xy);\n" + " }\n" + "}\n"; + + mVertexShader = makeShader(GL_VERTEX_SHADER, vertexSource); + mFragmentShader = makeShader(GL_FRAGMENT_SHADER, fragmentSource); + mProgram = gl->createProgram(); + gl->attachShader(mProgram, mVertexShader); + gl->attachShader(mProgram, mFragmentShader); + gl->bindAttribLocation(mProgram, 0, "vertex"); + gl->linkProgram(mProgram); + GLint linked; + gl->getProgramiv(mProgram, GL_LINK_STATUS, &linked); + ASSERT(linked); + mCenterUniform = gl->getUniformLocation(mProgram, "center"); + mWindowSizeUniform = gl->getUniformLocation(mProgram, "windowSize"); + mBorderSizeUniform = gl->getUniformLocation(mProgram, "borderSize"); + mDepthUniform = gl->getUniformLocation(mProgram, "depth"); + GLint texUniform = gl->getUniformLocation(mProgram, "tex"); + sm->useProgram(mProgram); + gl->uniform1i(texUniform, 0); + + // clang-format off + const GLfloat vertices[] = + { + // window corners, and window border inside corners + 1, -1, 0, + -1, -1, 0, + 1, 1, 0, + -1, 1, 0, + // window border outside corners + 1, -1, 1, + -1, -1, 1, + 1, 1, 1, + -1, 1, 1, + }; + // clang-format on + gl->genBuffers(1, &mVertexBuffer); + sm->bindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); + gl->bufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + // window border triangle strip + const GLuint borderStrip[] = {5, 0, 4, 2, 6, 3, 7, 1, 5, 0}; + + gl->genBuffers(1, &mIndexBuffer); + sm->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer); + gl->bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(borderStrip), borderStrip, GL_STATIC_DRAW); + } + else + { + sm->useProgram(mProgram); + sm->bindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); + sm->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer); + } + + // convert from pixels to "-1 to 1" space + const NativeWindow *n = buffer->getNative(); + double x = n->x * 2. / mWidth - 1; + double y = n->y * 2. / mHeight - 1; + double halfw = n->width * 1. / mWidth; + double halfh = n->height * 1. / mHeight; + double borderw = n->borderWidth * 2. / mWidth; + double borderh = n->borderHeight * 2. / mHeight; + + gl->uniform2f(mCenterUniform, x + halfw, y + halfh); + gl->uniform2f(mWindowSizeUniform, halfw, halfh); + gl->uniform2f(mBorderSizeUniform, borderw, borderh); + gl->uniform1f(mDepthUniform, n->depth / 1e6); + + sm->setBlendEnabled(false); + sm->setCullFaceEnabled(false); + sm->setStencilTestEnabled(false); + sm->setScissorTestEnabled(false); + sm->setDepthTestEnabled(true); + sm->setColorMask(true, true, true, true); + sm->setDepthMask(true); + sm->setDepthRange(0, 1); + sm->setDepthFunc(GL_LESS); + sm->setViewport(gl::Rectangle(0, 0, mWidth, mHeight)); + sm->activeTexture(0); + GLuint tex = buffer->getTexture(); + sm->bindTexture(GL_TEXTURE_2D, tex); + gl->vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); + gl->enableVertexAttribArray(0); + sm->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawing->getGLFB()); + gl->drawArrays(GL_TRIANGLE_STRIP, 0, 4); + gl->drawElements(GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, 0); + sm->deleteTexture(tex); +} + +void DisplayOzone::drawBuffer(Buffer *buffer) +{ + if (!mDrawing) + { + // get buffer on which to draw window + if (mUnused) + { + mDrawing = mUnused; + mUnused = nullptr; + } + else + { + mDrawing = new Buffer(this, GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT, + GBM_FORMAT_ARGB8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, + true, true); // XXX shouldn't need stencil + if (!mDrawing || !mDrawing->initialize(mWidth, mHeight)) + { + return; + } + } + + StateManagerGL *sm = getRenderer()->getStateManager(); + sm->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawing->getGLFB()); + sm->setClearColor(gl::ColorF(0, 0, 0, 1)); + sm->setClearDepth(1); + sm->setScissorTestEnabled(false); + sm->setColorMask(true, true, true, true); + sm->setDepthMask(true); + mFunctionsGL->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + + drawWithTexture(buffer); + presentScreen(); +} + +void DisplayOzone::flushGL() +{ + mFunctionsGL->flush(); + if (mEGL->hasExtension("EGL_KHR_fence_sync")) + { + const EGLint attrib[] = {EGL_SYNC_CONDITION_KHR, + EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM, EGL_NONE}; + EGLSyncKHR fence = mEGL->createSyncKHR(EGL_SYNC_FENCE_KHR, attrib); + if (fence) + { + // TODO(fjhenigman) Figure out the right way to use fences on Mali GPU + // to maximize throughput and avoid hangs when a program is interrupted. + // This busy wait was an attempt to reduce hangs when interrupted by SIGINT, + // but we still get some. + for (;;) + { + EGLint r = mEGL->clientWaitSyncKHR(fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 0); + if (r != EGL_TIMEOUT_EXPIRED_KHR) + { + break; + } + usleep(99); + } + mEGL->destroySyncKHR(fence); + return; + } + } +} + +void DisplayOzone::terminate() +{ + SafeDelete(mScanning); + SafeDelete(mPending); + SafeDelete(mDrawing); + SafeDelete(mUnused); + + if (mProgram) + { + mFunctionsGL->deleteProgram(mProgram); + mFunctionsGL->deleteShader(mVertexShader); + mFunctionsGL->deleteShader(mFragmentShader); + mFunctionsGL->deleteBuffers(1, &mVertexBuffer); + mFunctionsGL->deleteBuffers(1, &mIndexBuffer); + mProgram = 0; + } + + DisplayGL::terminate(); + + if (mContext) + { + // Mesa might crash if you terminate EGL with a context current + // then re-initialize EGL, so make our context not current. + mEGL->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT); + mEGL->destroyContext(mContext); + mContext = nullptr; + } + + SafeDelete(mFunctionsGL); + + if (mEGL) + { + mEGL->terminate(); + SafeDelete(mEGL); + } + + drmModeFreeCrtc(mCRTC); + + if (mGBM) + { + int fd = gbm_device_get_fd(mGBM); + gbm_device_destroy(mGBM); + mGBM = nullptr; + close(fd); + } +} + +SurfaceImpl *DisplayOzone::createWindowSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) +{ + Buffer *buffer = new Buffer(this, GBM_BO_USE_RENDERING, GBM_FORMAT_ARGB8888, + DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, true, true); + if (!buffer || !buffer->initialize(reinterpret_cast<const NativeWindow *>(window))) + { + return nullptr; + } + return new SurfaceOzone(state, getRenderer(), buffer); +} + +SurfaceImpl *DisplayOzone::createPbufferSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + const egl::AttributeMap &attribs) +{ + EGLAttrib width = attribs.get(EGL_WIDTH, 0); + EGLAttrib height = attribs.get(EGL_HEIGHT, 0); + Buffer *buffer = new Buffer(this, GBM_BO_USE_RENDERING, GBM_FORMAT_ARGB8888, + DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, true, true); + if (!buffer || !buffer->initialize(width, height)) + { + return nullptr; + } + return new SurfaceOzone(state, getRenderer(), buffer); +} + +SurfaceImpl *DisplayOzone::createPbufferFromClientBuffer(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) +{ + UNIMPLEMENTED(); + return nullptr; +} + +SurfaceImpl *DisplayOzone::createPixmapSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) +{ + UNIMPLEMENTED(); + return nullptr; +} + +egl::Error DisplayOzone::getDevice(DeviceImpl **device) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_BAD_DISPLAY); +} + +egl::ConfigSet DisplayOzone::generateConfigs() +{ + egl::ConfigSet configs; + + egl::Config config; + config.redSize = 8; + config.greenSize = 8; + config.blueSize = 8; + config.alphaSize = 8; + config.depthSize = 24; + config.stencilSize = 8; + config.bindToTextureRGBA = EGL_TRUE; + config.renderableType = EGL_OPENGL_ES2_BIT; + config.surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; + + configs.add(config); + return configs; +} + +bool DisplayOzone::testDeviceLost() +{ + return false; +} + +egl::Error DisplayOzone::restoreLostDevice() +{ + UNIMPLEMENTED(); + return egl::Error(EGL_BAD_DISPLAY); +} + +bool DisplayOzone::isValidNativeWindow(EGLNativeWindowType window) const +{ + return true; +} + +egl::Error DisplayOzone::getDriverVersion(std::string *version) const +{ + *version = ""; + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayOzone::waitClient() const +{ + // TODO(fjhenigman) Implement this. + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayOzone::waitNative(EGLint engine, + egl::Surface *drawSurface, + egl::Surface *readSurface) const +{ + // TODO(fjhenigman) Implement this. + return egl::Error(EGL_SUCCESS); +} + +void DisplayOzone::setSwapInterval(EGLSurface drawable, SwapControlData *data) +{ + ASSERT(data != nullptr); +} + +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h new file mode 100755 index 000000000..77c669314 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h @@ -0,0 +1,211 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayOzone.h: Ozone implementation of egl::Display + +#ifndef LIBANGLE_RENDERER_GL_EGL_OZONE_DISPLAYOZONE_H_ +#define LIBANGLE_RENDERER_GL_EGL_OZONE_DISPLAYOZONE_H_ + +#include <xf86drm.h> +#include <xf86drmMode.h> + +#include <string> + +#include "libANGLE/renderer/gl/egl/DisplayEGL.h" + +struct gbm_device; +struct gbm_bo; + +namespace gl +{ +class FramebufferState; +} + +namespace rx +{ + +class FramebufferGL; + +// TODO(fjhenigman) Implement swap control. The following struct will be used for that. +// State-tracking data for the swap control to allow DisplayOzone to remember per +// drawable information for swap control. +struct SwapControlData final +{ + SwapControlData(); + + // Set by the drawable + int targetSwapInterval; + + // DisplayOzone-side state-tracking + int maxSwapInterval; + int currentSwapInterval; +}; + +class DisplayOzone final : public DisplayEGL +{ + public: + struct NativeWindow + { + int32_t x; + int32_t y; + int32_t width; + int32_t height; + int32_t borderWidth; + int32_t borderHeight; + int32_t visible; + int32_t depth; + }; + + class Buffer final : angle::NonCopyable + { + public: + Buffer(DisplayOzone *display, + uint32_t useFlags, + uint32_t gbmFormat, + uint32_t drmFormat, + uint32_t drmFormatFB, + int depthBits, + int stencilBits); + + ~Buffer(); + bool initialize(const NativeWindow *window); + bool initialize(int32_t width, int32_t height); + void reset(); + bool resize(int32_t width, int32_t height); + FramebufferGL *framebufferGL(const gl::FramebufferState &state); + void present(); + uint32_t getDRMFB(); + void bindTexImage(); + GLuint getTexture(); + int32_t getWidth() const { return mWidth; } + int32_t getHeight() const { return mHeight; } + GLuint getGLFB() const { return mGLFB; } + const NativeWindow *getNative() const { return mNative; } + + private: + DisplayOzone *mDisplay; + const NativeWindow *mNative; + int mWidth; + int mHeight; + const int mDepthBits; + const int mStencilBits; + const uint32_t mUseFlags; + const uint32_t mGBMFormat; + const uint32_t mDRMFormat; + const uint32_t mDRMFormatFB; + gbm_bo *mBO; + int mDMABuf; + bool mHasDRMFB; + uint32_t mDRMFB; + EGLImageKHR mImage; + GLuint mColorBuffer; + GLuint mDSBuffer; + GLuint mGLFB; + GLuint mTexture; + }; + + DisplayOzone(); + ~DisplayOzone() override; + + egl::Error initialize(egl::Display *display) override; + void terminate() override; + + SurfaceImpl *createWindowSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) override; + + egl::ConfigSet generateConfigs() override; + + bool testDeviceLost() override; + egl::Error restoreLostDevice() override; + + bool isValidNativeWindow(EGLNativeWindowType window) const override; + + egl::Error getDevice(DeviceImpl **device) override; + + egl::Error waitClient() const override; + egl::Error waitNative(EGLint engine, + egl::Surface *drawSurface, + egl::Surface *readSurface) const override; + + // TODO(fjhenigman) Implement this. + // Swap interval can be set globally or per drawable. + // This function will make sure the drawable's swap interval is the + // one required so that the subsequent swapBuffers acts as expected. + void setSwapInterval(EGLSurface drawable, SwapControlData *data); + + egl::Error getDriverVersion(std::string *version) const override; + + private: + GLuint makeShader(GLuint type, const char *src); + void drawBuffer(Buffer *buffer); + void drawWithBlit(Buffer *buffer); + void drawWithTexture(Buffer *buffer); + void flushGL(); + void presentScreen(); + static void pageFlipHandler(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *data); + void pageFlipHandler(unsigned int sequence, uint64_t tv); + + // TODO(fjhenigman) Implement swap control. The following stuff will be used for that. + enum class SwapControl + { + ABSENT, + EXT, + MESA, + SGI, + }; + SwapControl mSwapControl; + int mMinSwapInterval; + int mMaxSwapInterval; + int mCurrentSwapInterval; + + gbm_device *mGBM; + drmModeConnectorPtr mConnector; + drmModeModeInfoPtr mMode; + drmModeCrtcPtr mCRTC; + bool mSetCRTC; + + int32_t mWidth; + int32_t mHeight; + + // Three scanout buffers cycle through four states. The state of a buffer + // is indicated by which of these pointers points to it. + // TODO(fjhenigman) It might be simpler/clearer to use a ring buffer. + Buffer *mScanning; + Buffer *mPending; + Buffer *mDrawing; + Buffer *mUnused; + + GLuint mProgram; + GLuint mVertexShader; + GLuint mFragmentShader; + GLuint mVertexBuffer; + GLuint mIndexBuffer; + GLint mCenterUniform; + GLint mWindowSizeUniform; + GLint mBorderSizeUniform; + GLint mDepthUniform; +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_GL_EGL_OZONE_DISPLAYOZONE_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.cpp new file mode 100755 index 000000000..614fed0fd --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.cpp @@ -0,0 +1,98 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SurfaceOzone.cpp: Ozone implementation of egl::SurfaceGL + +#include "libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h" + +#include "libANGLE/renderer/gl/FramebufferGL.h" +#include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h" + +namespace rx +{ + +SurfaceOzone::SurfaceOzone(const egl::SurfaceState &state, + RendererGL *renderer, + DisplayOzone::Buffer *buffer) + : SurfaceGL(state, renderer), mBuffer(buffer) +{ +} + +SurfaceOzone::~SurfaceOzone() +{ + delete mBuffer; +} + +egl::Error SurfaceOzone::initialize() +{ + return egl::Error(EGL_SUCCESS); +} + +FramebufferImpl *SurfaceOzone::createDefaultFramebuffer(const gl::FramebufferState &state) +{ + return mBuffer->framebufferGL(state); +} + +egl::Error SurfaceOzone::makeCurrent() +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceOzone::swap() +{ + mBuffer->present(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceOzone::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceOzone::querySurfacePointerANGLE(EGLint attribute, void **value) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceOzone::bindTexImage(gl::Texture *texture, EGLint buffer) +{ + mBuffer->bindTexImage(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceOzone::releaseTexImage(EGLint buffer) +{ + return egl::Error(EGL_SUCCESS); +} + +void SurfaceOzone::setSwapInterval(EGLint interval) +{ + mSwapControl.targetSwapInterval = interval; +} + +EGLint SurfaceOzone::getWidth() const +{ + return mBuffer->getWidth(); +} + +EGLint SurfaceOzone::getHeight() const +{ + return mBuffer->getHeight(); +} + +EGLint SurfaceOzone::isPostSubBufferSupported() const +{ + UNIMPLEMENTED(); + return EGL_FALSE; +} + +EGLint SurfaceOzone::getSwapBehavior() const +{ + return EGL_BUFFER_PRESERVED; +} +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h new file mode 100755 index 000000000..24b8ec8c9 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h @@ -0,0 +1,52 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SurfaceOzone.h: Ozone implementation of egl::SurfaceGL + +#ifndef LIBANGLE_RENDERER_GL_EGL_OZONE_SURFACEOZONE_H_ +#define LIBANGLE_RENDERER_GL_EGL_OZONE_SURFACEOZONE_H_ + +#include "libANGLE/renderer/gl/SurfaceGL.h" +#include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h" + +namespace rx +{ + +class SurfaceOzone : public SurfaceGL +{ + public: + SurfaceOzone(const egl::SurfaceState &state, + RendererGL *renderer, + DisplayOzone::Buffer *buffer); + ~SurfaceOzone() override; + + FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override; + + egl::Error initialize() override; + egl::Error makeCurrent() override; + + egl::Error swap() override; + egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; + egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; + egl::Error releaseTexImage(EGLint buffer) override; + void setSwapInterval(EGLint interval) override; + + EGLint getWidth() const override; + EGLint getHeight() const override; + + EGLint isPostSubBufferSupported() const override; + EGLint getSwapBehavior() const override; + + private: + DisplayOzone::Buffer *mBuffer; + + // TODO(fjhenigman) Implement swap control. This will be used for that. + SwapControlData mSwapControl; +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_GL_EGL_OZONE_SURFACEOZONE_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp b/gfx/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp new file mode 100755 index 000000000..c5219b4b8 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp @@ -0,0 +1,553 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// formatutilsgl.cpp: Queries for GL image formats and their translations to native +// GL formats. + +#include "libANGLE/renderer/gl/formatutilsgl.h" + +#include <limits> + +#include "common/string_utils.h" +#include "libANGLE/formatutils.h" + +namespace rx +{ + +namespace nativegl +{ + +SupportRequirement::SupportRequirement() + : version(std::numeric_limits<GLuint>::max(), std::numeric_limits<GLuint>::max()), + versionExtensions(), + requiredExtensions() +{ +} + +InternalFormat::InternalFormat() + : texture(), + filter(), + renderbuffer(), + framebufferAttachment() +{ +} + +// supported = version || vertexExt +static inline SupportRequirement VersionOrExts(GLuint major, GLuint minor, const std::string &versionExt) +{ + SupportRequirement requirement; + requirement.version.major = major; + requirement.version.minor = minor; + angle::SplitStringAlongWhitespace(versionExt, &requirement.versionExtensions); + return requirement; +} + +// supported = (version || vertexExt) && requiredExt +static inline SupportRequirement VersionOrExtsAndExts(GLuint major, + GLuint minor, + const std::string &versionExt, + const std::string &requiredExt) +{ + SupportRequirement requirement; + requirement.version.major = major; + requirement.version.minor = minor; + angle::SplitStringAlongWhitespace(versionExt, &requirement.versionExtensions); + angle::SplitStringAlongWhitespace(requiredExt, &requirement.requiredExtensions); + return requirement; +} + +// supported = version +static inline SupportRequirement VersionOnly(GLuint major, GLuint minor) +{ + SupportRequirement requirement; + requirement.version.major = major; + requirement.version.minor = minor; + return requirement; +} + +// supported = ext +static inline SupportRequirement ExtsOnly(const std::string &ext) +{ + SupportRequirement requirement; + requirement.version.major = 0; + requirement.version.minor = 0; + angle::SplitStringAlongWhitespace(ext, &requirement.requiredExtensions); + return requirement; +} + +// supported = true +static inline SupportRequirement AlwaysSupported() +{ + SupportRequirement requirement; + requirement.version.major = 0; + requirement.version.minor = 0; + return requirement; +} + +// supported = false +static inline SupportRequirement NeverSupported() +{ + SupportRequirement requirement; + requirement.version.major = std::numeric_limits<GLuint>::max(); + requirement.version.minor = std::numeric_limits<GLuint>::max(); + return requirement; +} + +struct InternalFormatInfo +{ + InternalFormat glesInfo; + InternalFormat glInfo; +}; + +typedef std::pair<GLenum, InternalFormatInfo> InternalFormatInfoPair; +typedef std::map<GLenum, InternalFormatInfo> InternalFormatInfoMap; + +// A helper function to insert data into the format map with fewer characters. +static inline void InsertFormatMapping(InternalFormatInfoMap *map, GLenum internalFormat, + const SupportRequirement &desktopTexture, const SupportRequirement &desktopFilter, const SupportRequirement &desktopRender, + const SupportRequirement &esTexture, const SupportRequirement &esFilter, const SupportRequirement &esRender) +{ + InternalFormatInfo formatInfo; + formatInfo.glInfo.texture = desktopTexture; + formatInfo.glInfo.filter = desktopFilter; + formatInfo.glInfo.renderbuffer = desktopRender; + formatInfo.glInfo.framebufferAttachment = desktopRender; + formatInfo.glesInfo.texture = esTexture; + formatInfo.glesInfo.filter = esTexture; + formatInfo.glesInfo.renderbuffer = esFilter; + formatInfo.glesInfo.framebufferAttachment = esRender; + map->insert(std::make_pair(internalFormat, formatInfo)); +} + +static InternalFormatInfoMap BuildInternalFormatInfoMap() +{ + InternalFormatInfoMap map; + + // clang-format off + // | Format | OpenGL texture support | Filter | OpenGL render support | OpenGL ES texture support | Filter | OpenGL ES render support | + InsertFormatMapping(&map, GL_R8, VersionOrExts(3, 0, "GL_ARB_texture_rg"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOrExts(3, 0, "GL_EXT_texture_rg"), AlwaysSupported(), VersionOrExts(3, 0, "GL_EXT_texture_rg") ); + InsertFormatMapping(&map, GL_R8_SNORM, VersionOnly(3, 1), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_RG8, VersionOrExts(3, 0, "GL_ARB_texture_rg"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOrExts(3, 0, "GL_EXT_texture_rg"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg") ); + InsertFormatMapping(&map, GL_RG8_SNORM, VersionOnly(3, 1), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_RGB8, AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), VersionOrExts(3, 0, "GL_OES_rgb8_rgba8"), AlwaysSupported(), AlwaysSupported() ); + InsertFormatMapping(&map, GL_RG8_SNORM, VersionOnly(3, 1), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_RGB565, AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported() ); + InsertFormatMapping(&map, GL_RGBA4, AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported() ); + InsertFormatMapping(&map, GL_RGB5_A1, AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported() ); + InsertFormatMapping(&map, GL_RGBA8, AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), VersionOrExts(3, 0, "GL_OES_rgb8_rgba8"), AlwaysSupported(), VersionOrExts(3, 0, "GL_OES_rgb8_rgba8") ); + InsertFormatMapping(&map, GL_RGBA8_SNORM, VersionOnly(3, 1), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_RGB10_A2, AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), VersionOnly(3, 0), AlwaysSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_RGB10_A2UI, VersionOrExts(3, 3, "GL_ARB_texture_rgb10_a2ui"), NeverSupported(), AlwaysSupported(), VersionOnly(3, 0), NeverSupported(), AlwaysSupported() ); + InsertFormatMapping(&map, GL_SRGB8, VersionOrExts(2, 1, "GL_EXT_texture_sRGB"), AlwaysSupported(), VersionOrExts(2, 1, "GL_EXT_texture_sRGB"), VersionOnly(3, 0), AlwaysSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_SRGB8_ALPHA8, VersionOrExts(2, 1, "GL_EXT_texture_sRGB"), AlwaysSupported(), VersionOrExts(2, 1, "GL_EXT_texture_sRGB"), VersionOnly(3, 0), AlwaysSupported(), VersionOrExts(3, 0, "GL_EXT_sRGB") ); + InsertFormatMapping(&map, GL_R8I, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_R8UI, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_R16I, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_R16UI, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_R32I, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_R32UI, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_RG8I, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_RG8UI, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_RG16I, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_RG16UI, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_RG32I, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_RG32UI, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_RGB8I, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), NeverSupported(), VersionOnly(3, 0), NeverSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_RGB8UI, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), NeverSupported(), VersionOnly(3, 0), NeverSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_RGB16I, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), NeverSupported(), VersionOnly(3, 0), NeverSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_RGB16UI, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), NeverSupported(), VersionOnly(3, 0), NeverSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_RGB32I, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), NeverSupported(), VersionOnly(3, 0), NeverSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_RGB32UI, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), NeverSupported(), VersionOnly(3, 0), NeverSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_RGBA8I, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_RGBA8UI, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_RGBA16I, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_RGBA16UI, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_RGBA32I, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_RGBA32UI, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + + // Unsized formats + InsertFormatMapping(&map, GL_ALPHA, NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_LUMINANCE, NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_RED, VersionOrExts(3, 0, "GL_ARB_texture_rg"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOrExts(3, 0, "GL_EXT_texture_rg"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg") ); + InsertFormatMapping(&map, GL_RG, VersionOrExts(3, 0, "GL_ARB_texture_rg"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOrExts(3, 0, "GL_EXT_texture_rg"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg") ); + InsertFormatMapping(&map, GL_RGB, AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported() ); + InsertFormatMapping(&map, GL_RGBA, AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported() ); + InsertFormatMapping(&map, GL_RED_INTEGER, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_RG_INTEGER, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_RGB_INTEGER, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), NeverSupported(), VersionOnly(3, 0), NeverSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_RGBA_INTEGER, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_SRGB, VersionOrExts(2, 1, "GL_EXT_texture_sRGB"), AlwaysSupported(), VersionOrExts(2, 1, "GL_EXT_texture_sRGB"), ExtsOnly("GL_EXT_sRGB"), AlwaysSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_SRGB_ALPHA, VersionOrExts(2, 1, "GL_EXT_texture_sRGB"), AlwaysSupported(), VersionOrExts(2, 1, "GL_EXT_texture_sRGB"), ExtsOnly("GL_EXT_sRGB"), AlwaysSupported(), NeverSupported() ); + + // From GL_EXT_texture_format_BGRA8888 + InsertFormatMapping(&map, GL_BGRA8_EXT, VersionOrExts(1, 2, "GL_EXT_bgra"), AlwaysSupported(), VersionOrExts(1, 2, "GL_EXT_bgra"), ExtsOnly("GL_EXT_texture_format_BGRA8888"), AlwaysSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_BGRA_EXT, VersionOrExts(1, 2, "GL_EXT_bgra"), AlwaysSupported(), VersionOrExts(1, 2, "GL_EXT_bgra"), ExtsOnly("GL_EXT_texture_format_BGRA8888"), AlwaysSupported(), NeverSupported() ); + + // Floating point formats + // | Format | OpenGL texture support | Filter | OpenGL render support | OpenGL ES texture support | Filter | OpenGL ES render support | + InsertFormatMapping(&map, GL_R11F_G11F_B10F, VersionOrExts(3, 0, "GL_EXT_packed_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_EXT_packed_float GL_ARB_color_buffer_float"), VersionOnly(3, 0), AlwaysSupported(), ExtsOnly("GL_EXT_color_buffer_float") ); + InsertFormatMapping(&map, GL_RGB9_E5, VersionOrExts(3, 0, "GL_EXT_texture_shared_exponent"), AlwaysSupported(), VersionOrExts(3, 0, "GL_EXT_texture_shared_exponent GL_ARB_color_buffer_float"), VersionOnly(3, 0), AlwaysSupported(), NeverSupported() ); + InsertFormatMapping(&map, GL_R16F, VersionOrExts(3, 0, "GL_ARB_texture_rg ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float GL_EXT_texture_rg"), VersionOrExts(3, 0, "GL_OES_texture_half_float_linear"), VersionOrExtsAndExts(3, 0, "GL_EXT_texture_rg", "GL_EXT_color_buffer_half_float")); + InsertFormatMapping(&map, GL_RG16F, VersionOrExts(3, 0, "GL_ARB_texture_rg ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float GL_EXT_texture_rg"), VersionOrExts(3, 0, "GL_OES_texture_half_float_linear"), VersionOrExtsAndExts(3, 0, "GL_EXT_texture_rg", "GL_EXT_color_buffer_half_float")); + InsertFormatMapping(&map, GL_RGB16F, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float_linear"), ExtsOnly("GL_EXT_color_buffer_half_float") ); + InsertFormatMapping(&map, GL_RGBA16F, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float_linear"), ExtsOnly("GL_EXT_color_buffer_half_float") ); + InsertFormatMapping(&map, GL_R32F, VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_float GL_EXT_texture_rg"), VersionOrExts(3, 0, "GL_OES_texture_float_linear"), ExtsOnly("GL_EXT_color_buffer_float") ); + InsertFormatMapping(&map, GL_RG32F, VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_float GL_EXT_texture_rg"), VersionOrExts(3, 0, "GL_OES_texture_float_linear"), ExtsOnly("GL_EXT_color_buffer_float") ); + InsertFormatMapping(&map, GL_RGB32F, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_float"), VersionOrExts(3, 0, "GL_OES_texture_float_linear"), NeverSupported() ); + InsertFormatMapping(&map, GL_RGBA32F, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_float"), VersionOrExts(3, 0, "GL_OES_texture_float_linear"), ExtsOnly("GL_EXT_color_buffer_float") ); + + // Depth stencil formats + // | Format | OpenGL texture support | Filter | OpenGL render support | OpenGL ES texture support | Filter | OpenGL ES render support | + InsertFormatMapping(&map, GL_DEPTH_COMPONENT16, VersionOnly(1, 5), VersionOrExts(1, 5, "GL_ARB_depth_texture"), VersionOnly(1, 5), VersionOnly(2, 0), VersionOrExts(3, 0, "GL_OES_depth_texture"), VersionOnly(2, 0) ); + InsertFormatMapping(&map, GL_DEPTH_COMPONENT24, VersionOnly(1, 5), VersionOrExts(1, 5, "GL_ARB_depth_texture"), VersionOnly(1, 5), VersionOnly(2, 0), VersionOrExts(3, 0, "GL_OES_depth_texture"), VersionOnly(2, 0) ); + InsertFormatMapping(&map, GL_DEPTH_COMPONENT32_OES, VersionOnly(1, 5), VersionOrExts(1, 5, "GL_ARB_depth_texture"), VersionOnly(1, 5), ExtsOnly("GL_OES_depth_texture"), AlwaysSupported(), ExtsOnly("GL_OES_depth32") ); + InsertFormatMapping(&map, GL_DEPTH_COMPONENT32F, VersionOrExts(3, 0, "GL_ARB_depth_buffer_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_depth_buffer_float"), VersionOnly(3, 0), VersionOrExts(3, 0, "GL_OES_depth_texture"), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_STENCIL_INDEX8, VersionOrExts(3, 0, "GL_EXT_packed_depth_stencil"), NeverSupported(), VersionOrExts(3, 0, "GL_EXT_packed_depth_stencil"), VersionOnly(2, 0), NeverSupported(), VersionOnly(2, 0) ); + InsertFormatMapping(&map, GL_DEPTH24_STENCIL8, VersionOrExts(3, 0, "GL_ARB_framebuffer_object"), VersionOrExts(3, 0, "GL_ARB_depth_texture"), VersionOrExts(3, 0, "GL_ARB_framebuffer_object"), VersionOrExts(3, 0, "GL_OES_depth_texture"), AlwaysSupported(), VersionOrExts(3, 0, "GL_OES_depth_texture GL_OES_packed_depth_stencil")); + InsertFormatMapping(&map, GL_DEPTH32F_STENCIL8, VersionOrExts(3, 0, "GL_ARB_depth_buffer_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_depth_buffer_float"), VersionOnly(3, 0), AlwaysSupported(), VersionOnly(3, 0) ); + InsertFormatMapping(&map, GL_DEPTH_COMPONENT, VersionOnly(1, 5), VersionOrExts(1, 5, "GL_ARB_depth_texture"), VersionOnly(1, 5), VersionOnly(2, 0), VersionOrExts(3, 0, "GL_OES_depth_texture"), VersionOnly(2, 0) ); + InsertFormatMapping(&map, GL_DEPTH_STENCIL, VersionOnly(1, 5), VersionOrExts(1, 5, "GL_ARB_depth_texture"), VersionOnly(1, 5), VersionOnly(2, 0), VersionOrExts(3, 0, "GL_OES_depth_texture"), VersionOnly(2, 0) ); + + // Luminance alpha formats + // | Format | OpenGL texture support | Filter | Render | OpenGL ES texture support | Filter | Render | + InsertFormatMapping(&map, GL_ALPHA8_EXT, AlwaysSupported(), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_LUMINANCE8_EXT, AlwaysSupported(), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_ALPHA32F_EXT, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_LUMINANCE32F_EXT, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_ALPHA16F_EXT, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_LUMINANCE16F_EXT, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_LUMINANCE8_ALPHA8_EXT, AlwaysSupported(), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_LUMINANCE_ALPHA32F_EXT, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_LUMINANCE_ALPHA16F_EXT, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported()); + + // Compressed formats, From ES 3.0.1 spec, table 3.16 + InsertFormatMapping(&map, GL_COMPRESSED_R11_EAC, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_COMPRESSED_SIGNED_R11_EAC, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_COMPRESSED_RG11_EAC, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_COMPRESSED_SIGNED_RG11_EAC, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_COMPRESSED_RGB8_ETC2, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_COMPRESSED_SRGB8_ETC2, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported()); + + // From GL_EXT_texture_compression_dxt1 + // | Format | OpenGL texture support | Filter | Render | OpenGL ES texture support | Filter | Render | + InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, ExtsOnly("GL_EXT_texture_compression_s3tc"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_compression_dxt1"), AlwaysSupported(), NeverSupported()); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, ExtsOnly("GL_EXT_texture_compression_s3tc"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_compression_dxt1"), AlwaysSupported(), NeverSupported()); + + // From GL_ANGLE_texture_compression_dxt3 + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, ExtsOnly("GL_EXT_texture_compression_s3tc"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_ANGLE_texture_compression_dxt3"), AlwaysSupported(), NeverSupported()); + + // From GL_ANGLE_texture_compression_dxt5 + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, ExtsOnly("GL_EXT_texture_compression_s3tc"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_ANGLE_texture_compression_dxt5"), AlwaysSupported(), NeverSupported()); + + // From GL_ETC1_RGB8_OES + InsertFormatMapping(&map, GL_ETC1_RGB8_OES, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOrExts(3, 0, "GL_ETC1_RGB8_OES"), AlwaysSupported(), NeverSupported()); + + // clang-format on + + return map; +} + +static const InternalFormatInfoMap &GetInternalFormatMap() +{ + static const InternalFormatInfoMap formatMap = BuildInternalFormatInfoMap(); + return formatMap; +} + +const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, StandardGL standard) +{ + const InternalFormatInfoMap &formatMap = GetInternalFormatMap(); + InternalFormatInfoMap::const_iterator iter = formatMap.find(internalFormat); + if (iter != formatMap.end()) + { + const InternalFormatInfo &info = iter->second; + switch (standard) + { + case STANDARD_GL_ES: return info.glesInfo; + case STANDARD_GL_DESKTOP: return info.glInfo; + default: UNREACHABLE(); break; + } + } + + static const InternalFormat defaultInternalFormat; + return defaultInternalFormat; +} + +static GLenum GetNativeInternalFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum internalFormat, + GLenum sizedInternalFormat) +{ + GLenum result = internalFormat; + + if (functions->standard == STANDARD_GL_DESKTOP) + { + // Use sized internal formats whenever possible to guarantee the requested precision. + // On Desktop GL, passing an internal format of GL_RGBA will generate a GL_RGBA8 texture + // even if the provided type is GL_FLOAT. + result = sizedInternalFormat; + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); + + if (workarounds.avoid1BitAlphaTextureFormats && formatInfo.alphaBits == 1) + { + // Use an 8-bit format instead + result = GL_RGBA8; + } + + if (workarounds.rgba4IsNotSupportedForColorRendering && sizedInternalFormat == GL_RGBA4) + { + // Use an 8-bit format instead + result = GL_RGBA8; + } + + if (sizedInternalFormat == GL_RGB565 && !functions->isAtLeastGL(gl::Version(4, 1)) && + !functions->hasGLExtension("GL_ARB_ES2_compatibility")) + { + // GL_RGB565 is required for basic ES2 functionality but was not added to desktop GL + // until 4.1. + // Work around this by using an 8-bit format instead. + result = GL_RGB8; + } + + if (sizedInternalFormat == GL_BGRA8_EXT) + { + // GLES accepts GL_BGRA as an internal format but desktop GL only accepts it as a type. + // Update the internal format to GL_RGBA. + result = GL_RGBA8; + } + + if ((functions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0) + { + // Work around deprecated luminance alpha formats in the OpenGL core profile by backing + // them with R or RG textures. + if (formatInfo.format == GL_LUMINANCE || formatInfo.format == GL_ALPHA) + { + result = gl::GetSizedInternalFormat(GL_RED, formatInfo.type); + } + + if (formatInfo.format == GL_LUMINANCE_ALPHA) + { + result = gl::GetSizedInternalFormat(GL_RG, formatInfo.type); + } + } + } + + return result; +} + +static GLenum GetNativeFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum format) +{ + GLenum result = format; + + if (functions->standard == STANDARD_GL_DESKTOP) + { + // The ES SRGB extensions require that the provided format is GL_SRGB or SRGB_ALPHA but + // the desktop GL extensions only accept GL_RGB or GL_RGBA. Convert them. + if (format == GL_SRGB) + { + result = GL_RGB; + } + + if (format == GL_SRGB_ALPHA) + { + result = GL_RGBA; + } + + if ((functions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0) + { + // Work around deprecated luminance alpha formats in the OpenGL core profile by backing + // them with R or RG textures. + if (format == GL_LUMINANCE || format == GL_ALPHA) + { + result = GL_RED; + } + + if (format == GL_LUMINANCE_ALPHA) + { + result = GL_RG; + } + } + } + + return result; +} + +static GLenum GetNativeCompressedFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum format) +{ + GLenum result = format; + + if (functions->standard == STANDARD_GL_DESKTOP) + { + if (format == GL_ETC1_RGB8_OES) + { + // GL_ETC1_RGB8_OES is not available in any desktop GL extension but the compression + // format is forwards compatible so just use the ETC2 format. + result = GL_COMPRESSED_RGB8_ETC2; + } + } + + if (functions->isAtLeastGLES(gl::Version(3, 0))) + { + if (format == GL_ETC1_RGB8_OES) + { + // Pass GL_COMPRESSED_RGB8_ETC2 as the target format in ES3 and higher because it + // becomes a core format. + result = GL_COMPRESSED_RGB8_ETC2; + } + } + + return result; +} + +static GLenum GetNativeType(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum type) +{ + GLenum result = type; + + if (functions->standard == STANDARD_GL_DESKTOP) + { + if (type == GL_HALF_FLOAT_OES) + { + // The enums differ for the OES half float extensions and desktop GL spec. Update it. + result = GL_HALF_FLOAT; + } + } + + if (functions->isAtLeastGLES(gl::Version(3, 0))) + { + if (type == GL_HALF_FLOAT_OES) + { + // The enums differ for the OES half float extensions and ES 3 spec. Update it. + result = GL_HALF_FLOAT; + } + } + + return result; +} + +static GLenum GetNativeReadType(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum type) +{ + GLenum result = type; + + if (functions->standard == STANDARD_GL_DESKTOP) + { + if (type == GL_HALF_FLOAT_OES) + { + // The enums differ for the OES half float extensions and desktop GL spec. Update it. + result = GL_HALF_FLOAT; + } + } + + return result; +} + +static GLenum GetNativeReadFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum format) +{ + GLenum result = format; + return result; +} + +TexImageFormat GetTexImageFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum internalFormat, + GLenum format, + GLenum type) +{ + TexImageFormat result; + result.internalFormat = GetNativeInternalFormat( + functions, workarounds, internalFormat, gl::GetSizedInternalFormat(internalFormat, type)); + result.format = GetNativeFormat(functions, workarounds, format); + result.type = GetNativeType(functions, workarounds, type); + return result; +} + +TexSubImageFormat GetTexSubImageFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum format, + GLenum type) +{ + TexSubImageFormat result; + result.format = GetNativeFormat(functions, workarounds, format); + result.type = GetNativeType(functions, workarounds, type); + return result; +} + +CompressedTexImageFormat GetCompressedTexImageFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum internalFormat) +{ + CompressedTexImageFormat result; + result.internalFormat = GetNativeCompressedFormat(functions, workarounds, internalFormat); + return result; +} + +CompressedTexSubImageFormat GetCompressedSubTexImageFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum format) +{ + CompressedTexSubImageFormat result; + result.format = GetNativeCompressedFormat(functions, workarounds, format); + return result; +} + +CopyTexImageImageFormat GetCopyTexImageImageFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum internalFormat, + GLenum framebufferType) +{ + CopyTexImageImageFormat result; + result.internalFormat = + GetNativeInternalFormat(functions, workarounds, internalFormat, + gl::GetSizedInternalFormat(internalFormat, framebufferType)); + return result; +} + +TexStorageFormat GetTexStorageFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum internalFormat) +{ + TexStorageFormat result; + result.internalFormat = + GetNativeInternalFormat(functions, workarounds, internalFormat, internalFormat); + return result; +} + +RenderbufferFormat GetRenderbufferFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum internalFormat) +{ + RenderbufferFormat result; + result.internalFormat = + GetNativeInternalFormat(functions, workarounds, internalFormat, internalFormat); + return result; +} +ReadPixelsFormat GetReadPixelsFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum format, + GLenum type) +{ + ReadPixelsFormat result; + result.format = GetNativeReadFormat(functions, workarounds, format); + result.type = GetNativeReadType(functions, workarounds, type); + return result; +} +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/formatutilsgl.h b/gfx/angle/src/libANGLE/renderer/gl/formatutilsgl.h new file mode 100755 index 000000000..616f37af2 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/formatutilsgl.h @@ -0,0 +1,129 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// formatutilsgl.h: Queries for GL image formats and their translations to native +// GL formats. + +#ifndef LIBANGLE_RENDERER_GL_FORMATUTILSGL_H_ +#define LIBANGLE_RENDERER_GL_FORMATUTILSGL_H_ + +#include <map> +#include <string> +#include <vector> + +#include "angle_gl.h" +#include "libANGLE/Version.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/WorkaroundsGL.h" + +namespace rx +{ + +namespace nativegl +{ + +struct SupportRequirement +{ + SupportRequirement(); + + // Version that this format became supported without extensions + gl::Version version; + + // Extensions that are required if the minimum version is not met + std::vector<std::string> versionExtensions; + + // Extensions that are always required to support this format + std::vector<std::string> requiredExtensions; +}; + +struct InternalFormat +{ + InternalFormat(); + + SupportRequirement texture; + SupportRequirement filter; + SupportRequirement renderbuffer; + SupportRequirement framebufferAttachment; +}; +const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, StandardGL standard); + +struct TexImageFormat +{ + GLenum internalFormat; + GLenum format; + GLenum type; +}; +TexImageFormat GetTexImageFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum internalFormat, + GLenum format, + GLenum type); + +struct TexSubImageFormat +{ + GLenum format; + GLenum type; +}; +TexSubImageFormat GetTexSubImageFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum format, + GLenum type); + +struct CompressedTexImageFormat +{ + GLenum internalFormat; +}; +CompressedTexImageFormat GetCompressedTexImageFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum internalFormat); + +struct CompressedTexSubImageFormat +{ + GLenum format; +}; +CompressedTexSubImageFormat GetCompressedSubTexImageFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum format); + +struct CopyTexImageImageFormat +{ + GLenum internalFormat; +}; +CopyTexImageImageFormat GetCopyTexImageImageFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum internalFormat, + GLenum framebufferType); + +struct TexStorageFormat +{ + GLenum internalFormat; +}; +TexStorageFormat GetTexStorageFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum internalFormat); + +struct RenderbufferFormat +{ + GLenum internalFormat; +}; +RenderbufferFormat GetRenderbufferFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum internalFormat); + +struct ReadPixelsFormat +{ + GLenum format; + GLenum type; +}; +ReadPixelsFormat GetReadPixelsFormat(const FunctionsGL *functions, + const WorkaroundsGL &workarounds, + GLenum format, + GLenum type); +} + +} + +#endif // LIBANGLE_RENDERER_GL_FORMATUTILSGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/functionsgl_enums.h b/gfx/angle/src/libANGLE/renderer/gl/functionsgl_enums.h new file mode 100755 index 000000000..918a7a1e6 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/functionsgl_enums.h @@ -0,0 +1,1375 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// functionsgl_enums.h: OpenGL enums for versions 1.0 through 4.5. + +#ifndef LIBANGLE_RENDERER_GL_FUNCTIONSGLENUMS_H_ +#define LIBANGLE_RENDERER_GL_FUNCTIONSGLENUMS_H_ + +// 1.0 +#define GL_ALPHA 0x1906 +#define GL_ALWAYS 0x0207 +#define GL_AND 0x1501 +#define GL_AND_INVERTED 0x1504 +#define GL_AND_REVERSE 0x1502 +#define GL_BACK 0x0405 +#define GL_BACK_LEFT 0x0402 +#define GL_BACK_RIGHT 0x0403 +#define GL_BLEND 0x0BE2 +#define GL_BLEND_DST 0x0BE0 +#define GL_BLEND_SRC 0x0BE1 +#define GL_BLUE 0x1905 +#define GL_BYTE 0x1400 +#define GL_CCW 0x0901 +#define GL_CLEAR 0x1500 +#define GL_COLOR 0x1800 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_COPY 0x1503 +#define GL_COPY_INVERTED 0x150C +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_CW 0x0900 +#define GL_DECR 0x1E03 +#define GL_DEPTH 0x1801 +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DITHER 0x0BD0 +#define GL_DONT_CARE 0x1100 +#define GL_DOUBLE 0x140A +#define GL_DOUBLEBUFFER 0x0C32 +#define GL_DRAW_BUFFER 0x0C01 +#define GL_DST_ALPHA 0x0304 +#define GL_DST_COLOR 0x0306 +#define GL_EQUAL 0x0202 +#define GL_EQUIV 0x1509 +#define GL_EXTENSIONS 0x1F03 +#define GL_FALSE 0 +#define GL_FASTEST 0x1101 +#define GL_FILL 0x1B02 +#define GL_FLOAT 0x1406 +#define GL_FRONT 0x0404 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_FRONT_FACE 0x0B46 +#define GL_FRONT_LEFT 0x0400 +#define GL_FRONT_RIGHT 0x0401 +#define GL_GEQUAL 0x0206 +#define GL_GREATER 0x0204 +#define GL_GREEN 0x1904 +#define GL_INCR 0x1E02 +#define GL_INT 0x1404 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_OPERATION 0x0502 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVERT 0x150A +#define GL_KEEP 0x1E00 +#define GL_LEFT 0x0406 +#define GL_LEQUAL 0x0203 +#define GL_LESS 0x0201 +#define GL_LINE 0x1B01 +#define GL_LINEAR 0x2601 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_LINE_STRIP 0x0003 +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_LINE_WIDTH_RANGE 0x0B22 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_NAND 0x150E +#define GL_NEAREST 0x2600 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_NEVER 0x0200 +#define GL_NICEST 0x1102 +#define GL_NONE 0 +#define GL_NOOP 0x1505 +#define GL_NOR 0x1508 +#define GL_NOTEQUAL 0x0205 +#define GL_NO_ERROR 0 +#define GL_ONE 1 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_OR 0x1507 +#define GL_OR_INVERTED 0x150D +#define GL_OR_REVERSE 0x150B +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_PACK_LSB_FIRST 0x0D01 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SWAP_BYTES 0x0D00 +#define GL_POINT 0x1B00 +#define GL_POINTS 0x0000 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_POINT_SIZE_RANGE 0x0B12 +#define GL_POLYGON_MODE 0x0B40 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_POLYGON_OFFSET_LINE 0x2A02 +#define GL_POLYGON_OFFSET_POINT 0x2A01 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_SMOOTH 0x0B41 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_QUADS 0x0007 +#define GL_R3_G3_B2 0x2A10 +#define GL_READ_BUFFER 0x0C02 +#define GL_RED 0x1903 +#define GL_RENDERER 0x1F01 +#define GL_REPEAT 0x2901 +#define GL_REPLACE 0x1E01 +#define GL_RGB 0x1907 +#define GL_RGB10 0x8052 +#define GL_RGB10_A2 0x8059 +#define GL_RGB12 0x8053 +#define GL_RGB16 0x8054 +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB5_A1 0x8057 +#define GL_RGB8 0x8051 +#define GL_RGBA 0x1908 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B +#define GL_RGBA2 0x8055 +#define GL_RGBA4 0x8056 +#define GL_RGBA8 0x8058 +#define GL_RIGHT 0x0407 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_SET 0x150F +#define GL_SHORT 0x1402 +#define GL_SRC_ALPHA 0x0302 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_SRC_COLOR 0x0300 +#define GL_STENCIL 0x1802 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_INDEX 0x1901 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STEREO 0x0C33 +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_TEXTURE 0x1702 +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRUE 1 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_UNPACK_LSB_FIRST 0x0CF1 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SWAP_BYTES 0x0CF0 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_UNSIGNED_INT 0x1405 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_VENDOR 0x1F00 +#define GL_VERSION 0x1F02 +#define GL_VIEWPORT 0x0BA2 +#define GL_XOR 0x1506 +#define GL_ZERO 0 + +// 1.2 +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 + +// 1.2 Extensions +#define GL_ALL_COMPLETED_NV 0x84F2 +#define GL_FENCE_STATUS_NV 0x84F3 +#define GL_FENCE_CONDITION_NV 0x84F4 + +// 1.3 +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_MULTISAMPLE 0x809D +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 + +// 1.5 +#define GL_BLEND_COLOR 0x8005 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_EQUATION 0x8009 +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_DECR_WRAP 0x8508 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_FUNC_SUBTRACT 0x800A +#define GL_INCR_WRAP 0x8507 +#define GL_MAX 0x8008 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_MIN 0x8007 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_TEXTURE_LOD_BIAS 0x8501 + +// 1.5 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_CURRENT_QUERY 0x8865 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_READ_ONLY 0x88B8 +#define GL_READ_WRITE 0x88BA +#define GL_SAMPLES_PASSED 0x8914 +#define GL_SRC1_ALPHA 0x8589 +#define GL_STATIC_COPY 0x88E6 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STREAM_COPY 0x88E2 +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_WRITE_ONLY 0x88B9 + +// 2.0 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_DELETE_STATUS 0x8B80 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_LINK_STATUS 0x8B82 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_POINT_SPRITE 0x8861 +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_TYPE 0x8B4F +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_SHADER 0x8B31 + +// 2.1 +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_SRGB_ALPHA 0x8C42 + +// 3.0 +#define GL_BGRA_INTEGER 0x8D9B +#define GL_BGR_INTEGER 0x8D9A +#define GL_BLUE_INTEGER 0x8D96 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_CLIP_DISTANCE0 0x3000 +#define GL_CLIP_DISTANCE1 0x3001 +#define GL_CLIP_DISTANCE2 0x3002 +#define GL_CLIP_DISTANCE3 0x3003 +#define GL_CLIP_DISTANCE4 0x3004 +#define GL_CLIP_DISTANCE5 0x3005 +#define GL_CLIP_DISTANCE6 0x3006 +#define GL_CLIP_DISTANCE7 0x3007 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_RG 0x8226 +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE +#define GL_CONTEXT_FLAGS 0x821E +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001 +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_FIXED_ONLY 0x891D +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_FRAMEBUFFER 0x8D40 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_SRGB 0x8DB9 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_GREEN_INTEGER 0x8D95 +#define GL_HALF_FLOAT 0x140B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_MAJOR_VERSION 0x821B +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MAX_CLIP_DISTANCES 0x0D32 +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_MINOR_VERSION 0x821C +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_NUM_EXTENSIONS 0x821D +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_WAIT 0x8E13 +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_R16 0x822A +#define GL_R16F 0x822D +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32F 0x822E +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_R8 0x8229 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RED_INTEGER 0x8D94 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RG 0x8227 +#define GL_RG16 0x822C +#define GL_RG16F 0x822F +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32F 0x8230 +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_RG8 0x822B +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RGB16F 0x881B +#define GL_RGB16I 0x8D89 +#define GL_RGB16UI 0x8D77 +#define GL_RGB32F 0x8815 +#define GL_RGB32I 0x8D83 +#define GL_RGB32UI 0x8D71 +#define GL_RGB8I 0x8D8F +#define GL_RGB8UI 0x8D7D +#define GL_RGB9_E5 0x8C3D +#define GL_RGBA16F 0x881A +#define GL_RGBA16I 0x8D88 +#define GL_RGBA16UI 0x8D76 +#define GL_RGBA32F 0x8814 +#define GL_RGBA32I 0x8D82 +#define GL_RGBA32UI 0x8D70 +#define GL_RGBA8I 0x8D8E +#define GL_RGBA8UI 0x8D7C +#define GL_RGBA_INTEGER 0x8D99 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RG_INTEGER 0x8228 +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_STENCIL_INDEX1 0x8D46 +#define GL_STENCIL_INDEX16 0x8D49 +#define GL_STENCIL_INDEX4 0x8D47 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_TEXTURE_1D_ARRAY 0x8C18 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD + +// 3.1 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_INVALID_INDEX 0xFFFFFFFFu +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_PRIMITIVE_RESTART 0x8F9D +#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E +#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7 +#define GL_R16_SNORM 0x8F98 +#define GL_R8_SNORM 0x8F94 +#define GL_RG16_SNORM 0x8F99 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA16_SNORM 0x8F9B +#define GL_RGBA8_SNORM 0x8F97 +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_TEXTURE_BINDING_BUFFER 0x8C2C +#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6 +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +#define GL_TEXTURE_RECTANGLE 0x84F5 +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 + +// 3.2 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_CONDITION_SATISFIED 0x911C +#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 +#define GL_CONTEXT_PROFILE_MASK 0x9126 +#define GL_DEPTH_CLAMP 0x864F +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 +#define GL_GEOMETRY_SHADER 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_LINES_ADJACENCY 0x000A +#define GL_LINE_STRIP_ADJACENCY 0x000B +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF +#define GL_MAX_INTEGER_SAMPLES 0x9110 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_OBJECT_TYPE 0x9112 +#define GL_PROGRAM_POINT_SIZE 0x8642 +#define GL_PROVOKING_VERTEX 0x8E4F +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SIGNALED 0x9119 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_SYNC_STATUS 0x9114 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#define GL_TRIANGLES_ADJACENCY 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D +#define GL_UNSIGNALED 0x9118 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_WAIT_FAILED 0x911D + +// 3.3 +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_INT_2_10_10_10_REV 0x8D9F +#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC +#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB +#define GL_ONE_MINUS_SRC1_COLOR 0x88FA +#define GL_RGB10_A2UI 0x906F +#define GL_SAMPLER_BINDING 0x8919 +#define GL_SRC1_COLOR 0x88F9 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 +#define GL_TIMESTAMP 0x8E28 +#define GL_TIME_ELAPSED 0x88BF +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE + +// 4.0 +#define GL_ACTIVE_SUBROUTINES 0x8DE5 +#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48 +#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6 +#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47 +#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49 +#define GL_COMPATIBLE_SUBROUTINES 0x8E4B +#define GL_DOUBLE_MAT2 0x8F46 +#define GL_DOUBLE_MAT2x3 0x8F49 +#define GL_DOUBLE_MAT2x4 0x8F4A +#define GL_DOUBLE_MAT3 0x8F47 +#define GL_DOUBLE_MAT3x2 0x8F4B +#define GL_DOUBLE_MAT3x4 0x8F4C +#define GL_DOUBLE_MAT4 0x8F48 +#define GL_DOUBLE_MAT4x2 0x8F4D +#define GL_DOUBLE_MAT4x3 0x8F4E +#define GL_DOUBLE_VEC2 0x8FFC +#define GL_DOUBLE_VEC3 0x8FFD +#define GL_DOUBLE_VEC4 0x8FFE +#define GL_DRAW_INDIRECT_BUFFER 0x8F3F +#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 +#define GL_FRACTIONAL_EVEN 0x8E7C +#define GL_FRACTIONAL_ODD 0x8E7B +#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D +#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#define GL_ISOLINES 0x8E7A +#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E +#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C +#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A +#define GL_MAX_PATCH_VERTICES 0x8E7D +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F +#define GL_MAX_SUBROUTINES 0x8DE7 +#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8 +#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C +#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83 +#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81 +#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85 +#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89 +#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F +#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D +#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86 +#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82 +#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A +#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80 +#define GL_MAX_TESS_GEN_LEVEL 0x8E7E +#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84 +#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70 +#define GL_MAX_VERTEX_STREAMS 0x8E71 +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E +#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37 +#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A +#define GL_PATCHES 0x000E +#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73 +#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74 +#define GL_PATCH_VERTICES 0x8E72 +#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B +#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#define GL_SAMPLE_SHADING 0x8C36 +#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75 +#define GL_TESS_CONTROL_SHADER 0x8E88 +#define GL_TESS_EVALUATION_SHADER 0x8E87 +#define GL_TESS_GEN_MODE 0x8E76 +#define GL_TESS_GEN_POINT_MODE 0x8E79 +#define GL_TESS_GEN_SPACING 0x8E77 +#define GL_TESS_GEN_VERTEX_ORDER 0x8E78 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A +#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009 +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 +#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1 +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F + +// 4.1 +#define GL_ACTIVE_PROGRAM 0x8259 +#define GL_ALL_SHADER_BITS 0xFFFFFFFF +#define GL_FIXED 0x140C +#define GL_FRAGMENT_SHADER_BIT 0x00000002 +#define GL_GEOMETRY_SHADER_BIT 0x00000004 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_HIGH_INT 0x8DF5 +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_LAYER_PROVOKING_VERTEX 0x825E +#define GL_LOW_FLOAT 0x8DF0 +#define GL_LOW_INT 0x8DF3 +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VIEWPORTS 0x825B +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#define GL_PROGRAM_BINARY_FORMATS 0x87FF +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_PIPELINE_BINDING 0x825A +#define GL_PROGRAM_SEPARABLE 0x8258 +#define GL_RGB565 0x8D62 +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_SHADER_COMPILER 0x8DFA +#define GL_TESS_CONTROL_SHADER_BIT 0x00000008 +#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010 +#define GL_UNDEFINED_VERTEX 0x8260 +#define GL_VERTEX_SHADER_BIT 0x00000001 +#define GL_VIEWPORT_BOUNDS_RANGE 0x825D +#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F +#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C + +// 4.2 +#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9 +#define GL_ALL_BARRIER_BITS 0xFFFFFFFF +#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000 +#define GL_ATOMIC_COUNTER_BUFFER 0x92C0 +#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5 +#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6 +#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1 +#define GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7 +#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3 +#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2 +#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200 +#define GL_COMMAND_BARRIER_BIT 0x00000040 +#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C +#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E +#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F +#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D +#define GL_COPY_READ_BUFFER_BINDING 0x8F36 +#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37 +#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002 +#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400 +#define GL_IMAGE_1D 0x904C +#define GL_IMAGE_1D_ARRAY 0x9052 +#define GL_IMAGE_2D 0x904D +#define GL_IMAGE_2D_ARRAY 0x9053 +#define GL_IMAGE_2D_MULTISAMPLE 0x9055 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056 +#define GL_IMAGE_2D_RECT 0x904F +#define GL_IMAGE_3D 0x904E +#define GL_IMAGE_BINDING_ACCESS 0x8F3E +#define GL_IMAGE_BINDING_FORMAT 0x906E +#define GL_IMAGE_BINDING_LAYER 0x8F3D +#define GL_IMAGE_BINDING_LAYERED 0x8F3C +#define GL_IMAGE_BINDING_LEVEL 0x8F3B +#define GL_IMAGE_BINDING_NAME 0x8F3A +#define GL_IMAGE_BUFFER 0x9051 +#define GL_IMAGE_CUBE 0x9050 +#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8 +#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7 +#define GL_INT_IMAGE_1D 0x9057 +#define GL_INT_IMAGE_1D_ARRAY 0x905D +#define GL_INT_IMAGE_2D 0x9058 +#define GL_INT_IMAGE_2D_ARRAY 0x905E +#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061 +#define GL_INT_IMAGE_2D_RECT 0x905A +#define GL_INT_IMAGE_3D 0x9059 +#define GL_INT_IMAGE_BUFFER 0x905C +#define GL_INT_IMAGE_CUBE 0x905B +#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F +#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC +#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8 +#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7 +#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1 +#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF +#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39 +#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6 +#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0 +#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE +#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5 +#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF +#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD +#define GL_MAX_IMAGE_SAMPLES 0x906D +#define GL_MAX_IMAGE_UNITS 0x8F38 +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3 +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD +#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4 +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE +#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC +#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2 +#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC +#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA +#define GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC +#define GL_NUM_SAMPLE_COUNTS 0x9380 +#define GL_PACK_COMPRESSED_BLOCK_DEPTH 0x912D +#define GL_PACK_COMPRESSED_BLOCK_HEIGHT 0x912C +#define GL_PACK_COMPRESSED_BLOCK_SIZE 0x912E +#define GL_PACK_COMPRESSED_BLOCK_WIDTH 0x912B +#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080 +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 +#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008 +#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F +#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100 +#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800 +#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 +#define GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA +#define GL_UNIFORM_BARRIER_BIT 0x00000004 +#define GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129 +#define GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128 +#define GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A +#define GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127 +#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB +#define GL_UNSIGNED_INT_IMAGE_1D 0x9062 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068 +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C +#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 +#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067 +#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001 + +// 4.3 +#define GL_ACTIVE_RESOURCES 0x92F5 +#define GL_ACTIVE_VARIABLES 0x9305 +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A +#define GL_ARRAY_SIZE 0x92FB +#define GL_ARRAY_STRIDE 0x92FE +#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED +#define GL_AUTO_GENERATE_MIPMAP 0x8295 +#define GL_BLOCK_INDEX 0x92FD +#define GL_BUFFER 0x82E0 +#define GL_BUFFER_BINDING 0x9302 +#define GL_BUFFER_DATA_SIZE 0x9303 +#define GL_BUFFER_VARIABLE 0x92E5 +#define GL_CAVEAT_SUPPORT 0x82B8 +#define GL_CLEAR_BUFFER 0x82B4 +#define GL_COLOR_COMPONENTS 0x8283 +#define GL_COLOR_ENCODING 0x8296 +#define GL_COLOR_RENDERABLE 0x8286 +#define GL_COMPRESSED_R11_EAC 0x9270 +#define GL_COMPRESSED_RG11_EAC 0x9272 +#define GL_COMPRESSED_RGB8_ETC2 0x9274 +#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 +#define GL_COMPRESSED_SRGB8_ETC2 0x9275 +#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define GL_COMPUTE_SHADER 0x91B9 +#define GL_COMPUTE_SHADER_BIT 0x00000020 +#define GL_COMPUTE_SUBROUTINE 0x92ED +#define GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3 +#define GL_COMPUTE_TEXTURE 0x82A0 +#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267 +#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 +#define GL_DEBUG_CALLBACK_FUNCTION 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245 +#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D +#define GL_DEBUG_LOGGED_MESSAGES 0x9145 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243 +#define GL_DEBUG_OUTPUT 0x92E0 +#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 +#define GL_DEBUG_SEVERITY_HIGH 0x9146 +#define GL_DEBUG_SEVERITY_LOW 0x9148 +#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 +#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B +#define GL_DEBUG_SOURCE_API 0x8246 +#define GL_DEBUG_SOURCE_APPLICATION 0x824A +#define GL_DEBUG_SOURCE_OTHER 0x824B +#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D +#define GL_DEBUG_TYPE_ERROR 0x824C +#define GL_DEBUG_TYPE_MARKER 0x8268 +#define GL_DEBUG_TYPE_OTHER 0x8251 +#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 +#define GL_DEBUG_TYPE_POP_GROUP 0x826A +#define GL_DEBUG_TYPE_PORTABILITY 0x824F +#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269 +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E +#define GL_DEPTH_COMPONENTS 0x8284 +#define GL_DEPTH_RENDERABLE 0x8287 +#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA +#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE +#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF +#define GL_FILTER 0x829A +#define GL_FRAGMENT_SUBROUTINE 0x92EC +#define GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2 +#define GL_FRAGMENT_TEXTURE 0x829F +#define GL_FRAMEBUFFER_BLEND 0x828B +#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314 +#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311 +#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312 +#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313 +#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310 +#define GL_FRAMEBUFFER_RENDERABLE 0x8289 +#define GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A +#define GL_FULL_SUPPORT 0x82B7 +#define GL_GEOMETRY_SUBROUTINE 0x92EB +#define GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1 +#define GL_GEOMETRY_TEXTURE 0x829E +#define GL_GET_TEXTURE_IMAGE_FORMAT 0x8291 +#define GL_GET_TEXTURE_IMAGE_TYPE 0x8292 +#define GL_IMAGE_CLASS_10_10_10_2 0x82C3 +#define GL_IMAGE_CLASS_11_11_10 0x82C2 +#define GL_IMAGE_CLASS_1_X_16 0x82BE +#define GL_IMAGE_CLASS_1_X_32 0x82BB +#define GL_IMAGE_CLASS_1_X_8 0x82C1 +#define GL_IMAGE_CLASS_2_X_16 0x82BD +#define GL_IMAGE_CLASS_2_X_32 0x82BA +#define GL_IMAGE_CLASS_2_X_8 0x82C0 +#define GL_IMAGE_CLASS_4_X_16 0x82BC +#define GL_IMAGE_CLASS_4_X_32 0x82B9 +#define GL_IMAGE_CLASS_4_X_8 0x82BF +#define GL_IMAGE_COMPATIBILITY_CLASS 0x82A8 +#define GL_IMAGE_PIXEL_FORMAT 0x82A9 +#define GL_IMAGE_PIXEL_TYPE 0x82AA +#define GL_IMAGE_TEXEL_SIZE 0x82A7 +#define GL_INTERNALFORMAT_ALPHA_SIZE 0x8274 +#define GL_INTERNALFORMAT_ALPHA_TYPE 0x827B +#define GL_INTERNALFORMAT_BLUE_SIZE 0x8273 +#define GL_INTERNALFORMAT_BLUE_TYPE 0x827A +#define GL_INTERNALFORMAT_DEPTH_SIZE 0x8275 +#define GL_INTERNALFORMAT_DEPTH_TYPE 0x827C +#define GL_INTERNALFORMAT_GREEN_SIZE 0x8272 +#define GL_INTERNALFORMAT_GREEN_TYPE 0x8279 +#define GL_INTERNALFORMAT_PREFERRED 0x8270 +#define GL_INTERNALFORMAT_RED_SIZE 0x8271 +#define GL_INTERNALFORMAT_RED_TYPE 0x8278 +#define GL_INTERNALFORMAT_SHARED_SIZE 0x8277 +#define GL_INTERNALFORMAT_STENCIL_SIZE 0x8276 +#define GL_INTERNALFORMAT_STENCIL_TYPE 0x827D +#define GL_INTERNALFORMAT_SUPPORTED 0x826F +#define GL_IS_PER_PATCH 0x92E7 +#define GL_IS_ROW_MAJOR 0x9300 +#define GL_LOCATION 0x930E +#define GL_LOCATION_INDEX 0x930F +#define GL_MANUAL_GENERATE_MIPMAP 0x8294 +#define GL_MATRIX_STRIDE 0x92FF +#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266 +#define GL_MAX_COMBINED_DIMENSIONS 0x8282 +#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39 +#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC +#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265 +#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264 +#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD +#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB +#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262 +#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC +#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB +#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263 +#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE +#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB +#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF +#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C +#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144 +#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143 +#define GL_MAX_DEPTH 0x8280 +#define GL_MAX_ELEMENT_INDEX 0x8D6B +#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA +#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316 +#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317 +#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318 +#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315 +#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7 +#define GL_MAX_HEIGHT 0x827F +#define GL_MAX_LABEL_LENGTH 0x82E8 +#define GL_MAX_LAYERS 0x8281 +#define GL_MAX_NAME_LENGTH 0x92F6 +#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7 +#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8 +#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE +#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD +#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8 +#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9 +#define GL_MAX_UNIFORM_LOCATIONS 0x826E +#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA +#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9 +#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6 +#define GL_MAX_WIDTH 0x827E +#define GL_MIPMAP 0x8293 +#define GL_NAME_LENGTH 0x92F9 +#define GL_NUM_ACTIVE_VARIABLES 0x9304 +#define GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9 +#define GL_OFFSET 0x92FC +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_PROGRAM 0x82E2 +#define GL_PROGRAM_INPUT 0x92E3 +#define GL_PROGRAM_OUTPUT 0x92E4 +#define GL_PROGRAM_PIPELINE 0x82E4 +#define GL_QUERY 0x82E3 +#define GL_READ_PIXELS 0x828C +#define GL_READ_PIXELS_FORMAT 0x828D +#define GL_READ_PIXELS_TYPE 0x828E +#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B +#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A +#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309 +#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307 +#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308 +#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306 +#define GL_SAMPLER 0x82E6 +#define GL_SHADER 0x82E1 +#define GL_SHADER_IMAGE_ATOMIC 0x82A6 +#define GL_SHADER_IMAGE_LOAD 0x82A4 +#define GL_SHADER_IMAGE_STORE 0x82A5 +#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000 +#define GL_SHADER_STORAGE_BLOCK 0x92E6 +#define GL_SHADER_STORAGE_BUFFER 0x90D2 +#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3 +#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF +#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5 +#define GL_SHADER_STORAGE_BUFFER_START 0x90D4 +#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC +#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE +#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD +#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF +#define GL_SRGB_READ 0x8297 +#define GL_SRGB_WRITE 0x8298 +#define GL_STENCIL_COMPONENTS 0x8285 +#define GL_STENCIL_RENDERABLE 0x8288 +#define GL_TESS_CONTROL_SUBROUTINE 0x92E9 +#define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF +#define GL_TESS_CONTROL_TEXTURE 0x829C +#define GL_TESS_EVALUATION_SUBROUTINE 0x92EA +#define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0 +#define GL_TESS_EVALUATION_TEXTURE 0x829D +#define GL_TEXTURE_BUFFER_OFFSET 0x919D +#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F +#define GL_TEXTURE_BUFFER_SIZE 0x919E +#define GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2 +#define GL_TEXTURE_COMPRESSED_BLOCK_SIZE 0x82B3 +#define GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1 +#define GL_TEXTURE_GATHER 0x82A2 +#define GL_TEXTURE_GATHER_SHADOW 0x82A3 +#define GL_TEXTURE_IMAGE_FORMAT 0x828F +#define GL_TEXTURE_IMAGE_TYPE 0x8290 +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF +#define GL_TEXTURE_SHADOW 0x82A1 +#define GL_TEXTURE_VIEW 0x82B5 +#define GL_TEXTURE_VIEW_MIN_LAYER 0x82DD +#define GL_TEXTURE_VIEW_MIN_LEVEL 0x82DB +#define GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE +#define GL_TEXTURE_VIEW_NUM_LEVELS 0x82DC +#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C +#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D +#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4 +#define GL_TYPE 0x92FA +#define GL_UNIFORM 0x92E1 +#define GL_UNIFORM_BLOCK 0x92E2 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC +#define GL_VERTEX_ATTRIB_ARRAY_LONG 0x874E +#define GL_VERTEX_ATTRIB_BINDING 0x82D4 +#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5 +#define GL_VERTEX_BINDING_BUFFER 0x8F4F +#define GL_VERTEX_BINDING_DIVISOR 0x82D6 +#define GL_VERTEX_BINDING_OFFSET 0x82D7 +#define GL_VERTEX_BINDING_STRIDE 0x82D8 +#define GL_VERTEX_SUBROUTINE 0x92E8 +#define GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE +#define GL_VERTEX_TEXTURE 0x829B +#define GL_VIEW_CLASS_128_BITS 0x82C4 +#define GL_VIEW_CLASS_16_BITS 0x82CA +#define GL_VIEW_CLASS_24_BITS 0x82C9 +#define GL_VIEW_CLASS_32_BITS 0x82C8 +#define GL_VIEW_CLASS_48_BITS 0x82C7 +#define GL_VIEW_CLASS_64_BITS 0x82C6 +#define GL_VIEW_CLASS_8_BITS 0x82CB +#define GL_VIEW_CLASS_96_BITS 0x82C5 +#define GL_VIEW_CLASS_BPTC_FLOAT 0x82D3 +#define GL_VIEW_CLASS_BPTC_UNORM 0x82D2 +#define GL_VIEW_CLASS_RGTC1_RED 0x82D0 +#define GL_VIEW_CLASS_RGTC2_RG 0x82D1 +#define GL_VIEW_CLASS_S3TC_DXT1_RGB 0x82CC +#define GL_VIEW_CLASS_S3TC_DXT1_RGBA 0x82CD +#define GL_VIEW_CLASS_S3TC_DXT3_RGBA 0x82CE +#define GL_VIEW_CLASS_S3TC_DXT5_RGBA 0x82CF +#define GL_VIEW_COMPATIBILITY_CLASS 0x82B6 + +// 4.4 +#define GL_BUFFER_IMMUTABLE_STORAGE 0x821F +#define GL_BUFFER_STORAGE_FLAGS 0x8220 +#define GL_CLEAR_TEXTURE 0x9365 +#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT 0x00004000 +#define GL_CLIENT_STORAGE_BIT 0x0200 +#define GL_DYNAMIC_STORAGE_BIT 0x0100 +#define GL_LOCATION_COMPONENT 0x934A +#define GL_MAP_COHERENT_BIT 0x0080 +#define GL_MAP_PERSISTENT_BIT 0x0040 +#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5 +#define GL_MIRROR_CLAMP_TO_EDGE 0x8743 +#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221 +#define GL_QUERY_BUFFER 0x9192 +#define GL_QUERY_BUFFER_BARRIER_BIT 0x00008000 +#define GL_QUERY_BUFFER_BINDING 0x9193 +#define GL_QUERY_RESULT_NO_WAIT 0x9194 +#define GL_TEXTURE_BUFFER_BINDING 0x8C2A +#define GL_TRANSFORM_FEEDBACK_BUFFER_INDEX 0x934B +#define GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE 0x934C + +// 4.5 +#define GL_CLIP_DEPTH_MODE 0x935D +#define GL_CLIP_ORIGIN 0x935C +#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004 +#define GL_CONTEXT_LOST 0x0507 +#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB +#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC +#define GL_GUILTY_CONTEXT_RESET 0x8253 +#define GL_INNOCENT_CONTEXT_RESET 0x8254 +#define GL_LOSE_CONTEXT_ON_RESET 0x8252 +#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES 0x82FA +#define GL_MAX_CULL_DISTANCES 0x82F9 +#define GL_NEGATIVE_ONE_TO_ONE 0x935E +#define GL_NO_RESET_NOTIFICATION 0x8261 +#define GL_QUERY_BY_REGION_NO_WAIT_INVERTED 0x8E1A +#define GL_QUERY_BY_REGION_WAIT_INVERTED 0x8E19 +#define GL_QUERY_NO_WAIT_INVERTED 0x8E18 +#define GL_QUERY_TARGET 0x82EA +#define GL_QUERY_WAIT_INVERTED 0x8E17 +#define GL_RESET_NOTIFICATION_STRATEGY 0x8256 +#define GL_TEXTURE_TARGET 0x1006 +#define GL_UNKNOWN_CONTEXT_RESET 0x8255 +#define GL_ZERO_TO_ONE 0x935F + +#endif // LIBANGLE_RENDERER_GL_FUNCTIONSGLENUMS_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/functionsgl_typedefs.h b/gfx/angle/src/libANGLE/renderer/gl/functionsgl_typedefs.h new file mode 100755 index 000000000..daf7ff74e --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/functionsgl_typedefs.h @@ -0,0 +1,758 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// functionsgl_typedefs.h: Typedefs of OpenGL types and functions for versions 1.0 through 4.5. + +#ifndef LIBANGLE_RENDERER_GL_FUNCTIONSGLTYPEDEFS_H_ +#define LIBANGLE_RENDERER_GL_FUNCTIONSGLTYPEDEFS_H_ + +#include "common/platform.h" + +#include <KHR/khrplatform.h> +#include <stdint.h> + +#ifndef INTERNAL_GL_APIENTRY +# ifdef ANGLE_PLATFORM_WINDOWS +# define INTERNAL_GL_APIENTRY __stdcall +# else +# define INTERNAL_GL_APIENTRY +# endif +#endif + +typedef void GLvoid; +typedef char GLchar; +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef khronos_int8_t GLbyte; +typedef short GLshort; +typedef int GLint; +typedef int GLsizei; +typedef khronos_uint8_t GLubyte; +typedef unsigned short GLushort; +typedef unsigned int GLuint; +typedef khronos_float_t GLfloat; +typedef khronos_float_t GLclampf; +typedef double GLdouble; +typedef double GLclampd; +typedef khronos_int32_t GLfixed; +typedef khronos_intptr_t GLintptr; +typedef khronos_ssize_t GLsizeiptr; +typedef unsigned short GLhalf; +typedef khronos_int64_t GLint64; +typedef khronos_uint64_t GLuint64; +typedef struct __GLsync *GLsync; + +namespace rx +{ +typedef void (INTERNAL_GL_APIENTRY *GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam); +typedef void (INTERNAL_GL_APIENTRY *GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam); +typedef void (INTERNAL_GL_APIENTRY *GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar *message, void *userParam); + +// 1.0 +typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDFUNCPROC)(GLenum, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARPROC)(GLbitfield); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARCOLORPROC)(GLfloat, GLfloat, GLfloat, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARDEPTHPROC)(GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARSTENCILPROC)(GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOLORMASKPROC)(GLboolean, GLboolean, GLboolean, GLboolean); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCULLFACEPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHFUNCPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHMASKPROC)(GLboolean); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHRANGEPROC)(GLdouble, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDISABLEPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWBUFFERPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLENABLEPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLFINISHPROC)(); +typedef void (INTERNAL_GL_APIENTRY *PFNGLFLUSHPROC)(); +typedef void (INTERNAL_GL_APIENTRY *PFNGLFRONTFACEPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBOOLEANVPROC)(GLenum, GLboolean *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETDOUBLEVPROC)(GLenum, GLdouble *); +typedef GLenum (INTERNAL_GL_APIENTRY *PFNGLGETERRORPROC)(); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETFLOATVPROC)(GLenum, GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTEGERVPROC)(GLenum, GLint *); +typedef const GLubyte * (INTERNAL_GL_APIENTRY *PFNGLGETSTRINGPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXIMAGEPROC)(GLenum, GLint, GLenum, GLenum, GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum, GLint, GLenum, GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum, GLint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXPARAMETERFVPROC)(GLenum, GLenum, GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXPARAMETERIVPROC)(GLenum, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLHINTPROC)(GLenum, GLenum); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISENABLEDPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLLINEWIDTHPROC)(GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLLOGICOPPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPIXELSTOREFPROC)(GLenum, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPIXELSTOREIPROC)(GLenum, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPOINTSIZEPROC)(GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPOLYGONMODEPROC)(GLenum, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLREADBUFFERPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLREADPIXELSPROC)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSCISSORPROC)(GLint, GLint, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILFUNCPROC)(GLenum, GLint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILMASKPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILOPPROC)(GLenum, GLenum, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXIMAGE1DPROC)(GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, const GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXIMAGE2DPROC)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERFPROC)(GLenum, GLenum, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERFVPROC)(GLenum, GLenum, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERIPROC)(GLenum, GLenum, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERIVPROC)(GLenum, GLenum, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVIEWPORTPROC)(GLint, GLint, GLsizei, GLsizei); + +// 1.1 +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDTEXTUREPROC)(GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXIMAGE1DPROC)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXIMAGE2DPROC)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum, GLint, GLint, GLint, GLint, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETETEXTURESPROC)(GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWARRAYSPROC)(GLenum, GLint, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSPROC)(GLenum, GLsizei, GLenum, const GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGENTEXTURESPROC)(GLsizei, GLuint *); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISTEXTUREPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPOLYGONOFFSETPROC)(GLfloat, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSUBIMAGE1DPROC)(GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSUBIMAGE2DPROC)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); + +// 1.2 +typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDCOLORPROC)(GLfloat, GLfloat, GLfloat, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDEQUATIONPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWRANGEELEMENTSPROC)(GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXIMAGE3DPROC)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSUBIMAGE3DPROC)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); + +// 1.2 Extensions +typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEFENCESNVPROC)(GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGENFENCESNVPROC)(GLsizei, GLuint *); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISFENCENVPROC)(GLuint); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLTESTFENCENVPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETFENCEIVNVPROC)(GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLFINISHFENCENVPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSETFENCENVPROC)(GLuint, GLenum); + +// 1.3 +typedef void (INTERNAL_GL_APIENTRY *PFNGLACTIVETEXTUREPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum, GLint, GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLECOVERAGEPROC)(GLfloat, GLboolean); + +// 1.4 +typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDFUNCSEPARATEPROC)(GLenum, GLenum, GLenum, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLMULTIDRAWARRAYSPROC)(GLenum, const GLint *, const GLsizei *, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLMULTIDRAWELEMENTSPROC)(GLenum, const GLsizei *, GLenum, const GLvoid *const*, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPOINTPARAMETERFPROC)(GLenum, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPOINTPARAMETERFVPROC)(GLenum, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPOINTPARAMETERIPROC)(GLenum, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPOINTPARAMETERIVPROC)(GLenum, const GLint *); + +// 1.5 +typedef void (INTERNAL_GL_APIENTRY *PFNGLBEGINQUERYPROC)(GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERPROC)(GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBUFFERDATAPROC)(GLenum, GLsizeiptr, const GLvoid *, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBUFFERSUBDATAPROC)(GLenum, GLintptr, GLsizeiptr, const GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEBUFFERSPROC)(GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEQUERIESPROC)(GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLENDQUERYPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGENBUFFERSPROC)(GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGENQUERIESPROC)(GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBUFFERPARAMETERIVPROC)(GLenum, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBUFFERPOINTERVPROC)(GLenum, GLenum, GLvoid **); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBUFFERSUBDATAPROC)(GLenum, GLintptr, GLsizeiptr, GLvoid *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYOBJECTIVPROC)(GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYOBJECTUIVPROC)(GLuint, GLenum, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYIVPROC)(GLenum, GLenum, GLint *); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISBUFFERPROC)(GLuint); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISQUERYPROC)(GLuint); +typedef void * (INTERNAL_GL_APIENTRY *PFNGLMAPBUFFERPROC)(GLenum, GLenum); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLUNMAPBUFFERPROC)(GLenum); + +// 2.0 +typedef void (INTERNAL_GL_APIENTRY *PFNGLATTACHSHADERPROC)(GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDATTRIBLOCATIONPROC)(GLuint, GLuint, const GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPILESHADERPROC)(GLuint); +typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLCREATEPROGRAMPROC)(); +typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLCREATESHADERPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEPROGRAMPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETESHADERPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDETACHSHADERPROC)(GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWBUFFERSPROC)(GLsizei, const GLenum *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEATTRIBPROC)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEUNIFORMPROC)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETATTACHEDSHADERSPROC)(GLuint, GLsizei, GLsizei *, GLuint *); +typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETATTRIBLOCATIONPROC)(GLuint, const GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMINFOLOGPROC)(GLuint, GLsizei, GLsizei *, GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMIVPROC)(GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSHADERINFOLOGPROC)(GLuint, GLsizei, GLsizei *, GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSHADERSOURCEPROC)(GLuint, GLsizei, GLsizei *, GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSHADERIVPROC)(GLuint, GLenum, GLint *); +typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMLOCATIONPROC)(GLuint, const GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMFVPROC)(GLuint, GLint, GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMIVPROC)(GLuint, GLint, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint, GLenum, GLvoid **); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint, GLenum, GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBFVPROC)(GLuint, GLenum, GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBIVPROC)(GLuint, GLenum, GLint *); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISPROGRAMPROC)(GLuint); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISSHADERPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLLINKPROGRAMPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSHADERSOURCEPROC)(GLuint, GLsizei, const GLchar *const*, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILFUNCSEPARATEPROC)(GLenum, GLenum, GLint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILMASKSEPARATEPROC)(GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILOPSEPARATEPROC)(GLenum, GLenum, GLenum, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1FPROC)(GLint, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1FVPROC)(GLint, GLsizei, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1IPROC)(GLint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1IVPROC)(GLint, GLsizei, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2FPROC)(GLint, GLfloat, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2FVPROC)(GLint, GLsizei, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2IPROC)(GLint, GLint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2IVPROC)(GLint, GLsizei, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3FPROC)(GLint, GLfloat, GLfloat, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3FVPROC)(GLint, GLsizei, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3IPROC)(GLint, GLint, GLint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3IVPROC)(GLint, GLsizei, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4FPROC)(GLint, GLfloat, GLfloat, GLfloat, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4FVPROC)(GLint, GLsizei, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4IPROC)(GLint, GLint, GLint, GLint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4IVPROC)(GLint, GLsizei, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUSEPROGRAMPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVALIDATEPROGRAMPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1DPROC)(GLuint, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1DVPROC)(GLuint, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1FPROC)(GLuint, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1FVPROC)(GLuint, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1SPROC)(GLuint, GLshort); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1SVPROC)(GLuint, const GLshort *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2DPROC)(GLuint, GLdouble, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2DVPROC)(GLuint, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2FPROC)(GLuint, GLfloat, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2FVPROC)(GLuint, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2SPROC)(GLuint, GLshort, GLshort); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2SVPROC)(GLuint, const GLshort *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3DPROC)(GLuint, GLdouble, GLdouble, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3DVPROC)(GLuint, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3FPROC)(GLuint, GLfloat, GLfloat, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3FVPROC)(GLuint, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3SPROC)(GLuint, GLshort, GLshort, GLshort); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3SVPROC)(GLuint, const GLshort *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NBVPROC)(GLuint, const GLbyte *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NIVPROC)(GLuint, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NSVPROC)(GLuint, const GLshort *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NUBPROC)(GLuint, GLubyte, GLubyte, GLubyte, GLubyte); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NUBVPROC)(GLuint, const GLubyte *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NUIVPROC)(GLuint, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NUSVPROC)(GLuint, const GLushort *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4BVPROC)(GLuint, const GLbyte *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4DPROC)(GLuint, GLdouble, GLdouble, GLdouble, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4DVPROC)(GLuint, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4FPROC)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4FVPROC)(GLuint, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4IVPROC)(GLuint, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4SPROC)(GLuint, GLshort, GLshort, GLshort, GLshort); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4SVPROC)(GLuint, const GLshort *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4UBVPROC)(GLuint, const GLubyte *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4UIVPROC)(GLuint, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4USVPROC)(GLuint, const GLushort *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBPOINTERPROC)(GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *); + +// 2.1 +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2X3FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2X4FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3X2FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3X4FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4X2FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4X3FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *); + +// 3.0 +typedef void (INTERNAL_GL_APIENTRY *PFNGLBEGINCONDITIONALRENDERPROC)(GLuint, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERBASEPROC)(GLenum, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERRANGEPROC)(GLenum, GLuint, GLuint, GLintptr, GLsizeiptr); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDFRAGDATALOCATIONPROC)(GLuint, GLuint, const GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDFRAMEBUFFERPROC)(GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDRENDERBUFFERPROC)(GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDVERTEXARRAYPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBLITFRAMEBUFFERPROC)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum); +typedef GLenum (INTERNAL_GL_APIENTRY *PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLAMPCOLORPROC)(GLenum, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERFIPROC)(GLenum, GLint, GLfloat, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERFVPROC)(GLenum, GLint, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERIVPROC)(GLenum, GLint, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERUIVPROC)(GLenum, GLint, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOLORMASKIPROC)(GLuint, GLboolean, GLboolean, GLboolean, GLboolean); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETERENDERBUFFERSPROC)(GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEVERTEXARRAYSPROC)(GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDISABLEIPROC)(GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLENABLEIPROC)(GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLENDCONDITIONALRENDERPROC)(); +typedef void (INTERNAL_GL_APIENTRY *PFNGLENDTRANSFORMFEEDBACKPROC)(); +typedef void (INTERNAL_GL_APIENTRY *PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum, GLintptr, GLsizeiptr); +typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum, GLenum, GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum, GLenum, GLenum, GLuint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum, GLenum, GLenum, GLuint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum, GLenum, GLenum, GLuint, GLint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum, GLenum, GLuint, GLint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGENFRAMEBUFFERSPROC)(GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGENRENDERBUFFERSPROC)(GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGENVERTEXARRAYSPROC)(GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGENERATEMIPMAPPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBOOLEANI_VPROC)(GLenum, GLuint, GLboolean *); +typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETFRAGDATALOCATIONPROC)(GLuint, const GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum, GLenum, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTEGERI_VPROC)(GLenum, GLuint, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum, GLenum, GLint *); +typedef const GLubyte * (INTERNAL_GL_APIENTRY *PFNGLGETSTRINGIPROC)(GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXPARAMETERIIVPROC)(GLenum, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXPARAMETERIUIVPROC)(GLenum, GLenum, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMUIVPROC)(GLuint, GLint, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBIIVPROC)(GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint, GLenum, GLuint *); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISENABLEDIPROC)(GLenum, GLuint); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISFRAMEBUFFERPROC)(GLuint); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISRENDERBUFFERPROC)(GLuint); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISVERTEXARRAYPROC)(GLuint); +typedef void * (INTERNAL_GL_APIENTRY *PFNGLMAPBUFFERRANGEPROC)(GLenum, GLintptr, GLsizeiptr, GLbitfield); +typedef void (INTERNAL_GL_APIENTRY *PFNGLRENDERBUFFERSTORAGEPROC)(GLenum, GLenum, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERIIVPROC)(GLenum, GLenum, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERIUIVPROC)(GLenum, GLenum, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint, GLsizei, const GLchar *const*, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1UIPROC)(GLint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1UIVPROC)(GLint, GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2UIPROC)(GLint, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2UIVPROC)(GLint, GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3UIPROC)(GLint, GLuint, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3UIVPROC)(GLint, GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4UIPROC)(GLint, GLuint, GLuint, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4UIVPROC)(GLint, GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI1IPROC)(GLuint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI1IVPROC)(GLuint, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI1UIPROC)(GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI1UIVPROC)(GLuint, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI2IPROC)(GLuint, GLint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI2IVPROC)(GLuint, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI2UIPROC)(GLuint, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI2UIVPROC)(GLuint, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI3IPROC)(GLuint, GLint, GLint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI3IVPROC)(GLuint, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI3UIPROC)(GLuint, GLuint, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI3UIVPROC)(GLuint, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4BVPROC)(GLuint, const GLbyte *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4IPROC)(GLuint, GLint, GLint, GLint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4IVPROC)(GLuint, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4SVPROC)(GLuint, const GLshort *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4UBVPROC)(GLuint, const GLubyte *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4UIPROC)(GLuint, GLuint, GLuint, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4UIVPROC)(GLuint, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4USVPROC)(GLuint, const GLushort *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint, GLint, GLenum, GLsizei, const GLvoid *); + +// 3.1 +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYBUFFERSUBDATAPROC)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum, GLint, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum, GLsizei, GLenum, const GLvoid *, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint, GLuint, GLsizei, GLsizei *, GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint, GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint, GLuint, GLsizei, GLsizei *, GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint, GLsizei, const GLuint *, GLenum, GLint *); +typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint, const GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMINDICESPROC)(GLuint, GLsizei, const GLchar *const*, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXBUFFERPROC)(GLenum, GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint, GLuint, GLuint); + +// 3.2 +typedef GLenum (INTERNAL_GL_APIENTRY *PFNGLCLIENTWAITSYNCPROC)(GLsync, GLbitfield, GLuint64); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETESYNCPROC)(GLsync); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum, GLsizei, GLenum, const GLvoid *, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum, GLsizei, GLenum, const GLvoid *, GLsizei, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *, GLint); +typedef GLsync (INTERNAL_GL_APIENTRY *PFNGLFENCESYNCPROC)(GLenum, GLbitfield); +typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum, GLenum, GLuint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum, GLenum, GLint64 *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTEGER64I_VPROC)(GLenum, GLuint, GLint64 *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTEGER64VPROC)(GLenum, GLint64 *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETMULTISAMPLEFVPROC)(GLenum, GLuint, GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSYNCIVPROC)(GLsync, GLenum, GLsizei, GLsizei *, GLint *); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISSYNCPROC)(GLsync); +typedef void (INTERNAL_GL_APIENTRY *PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum, const GLsizei *, GLenum, const GLvoid *const*, GLsizei, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROVOKINGVERTEXPROC)(GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLEMASKIPROC)(GLuint, GLbitfield); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum, GLsizei, GLint, GLsizei, GLsizei, GLboolean); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum, GLsizei, GLint, GLsizei, GLsizei, GLsizei, GLboolean); +typedef void (INTERNAL_GL_APIENTRY *PFNGLWAITSYNCPROC)(GLsync, GLbitfield, GLuint64); + +// 3.3 +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)(GLuint, GLuint, GLuint, const GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDSAMPLERPROC)(GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETESAMPLERSPROC)(GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGENSAMPLERSPROC)(GLsizei, GLuint *); +typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETFRAGDATAINDEXPROC)(GLuint, const GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYOBJECTI64VPROC)(GLuint, GLenum, GLint64 *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYOBJECTUI64VPROC)(GLuint, GLenum, GLuint64 *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint, GLenum, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint, GLenum, GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint, GLenum, GLint *); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISSAMPLERPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLQUERYCOUNTERPROC)(GLuint, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERIIVPROC)(GLuint, GLenum, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint, GLenum, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERFPROC)(GLuint, GLenum, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERFVPROC)(GLuint, GLenum, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERIPROC)(GLuint, GLenum, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERIVPROC)(GLuint, GLenum, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBDIVISORPROC)(GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP1UIPROC)(GLuint, GLenum, GLboolean, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP1UIVPROC)(GLuint, GLenum, GLboolean, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP2UIPROC)(GLuint, GLenum, GLboolean, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP2UIVPROC)(GLuint, GLenum, GLboolean, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP3UIPROC)(GLuint, GLenum, GLboolean, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP3UIVPROC)(GLuint, GLenum, GLboolean, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP4UIPROC)(GLuint, GLenum, GLboolean, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP4UIVPROC)(GLuint, GLenum, GLboolean, const GLuint *); + +// 4.0 +typedef void (INTERNAL_GL_APIENTRY *PFNGLBEGINQUERYINDEXEDPROC)(GLenum, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDTRANSFORMFEEDBACKPROC)(GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDEQUATIONSEPARATEIPROC)(GLuint, GLenum, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDEQUATIONIPROC)(GLuint, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDFUNCSEPARATEIPROC)(GLuint, GLenum, GLenum, GLenum, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDFUNCIPROC)(GLuint, GLenum, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETETRANSFORMFEEDBACKSPROC)(GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWARRAYSINDIRECTPROC)(GLenum, const void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSINDIRECTPROC)(GLenum, GLenum, const void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWTRANSFORMFEEDBACKPROC)(GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC)(GLenum, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLENDQUERYINDEXEDPROC)(GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGENTRANSFORMFEEDBACKSPROC)(GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVESUBROUTINENAMEPROC)(GLuint, GLenum, GLuint, GLsizei, GLsizei *, GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC)(GLuint, GLenum, GLuint, GLsizei, GLsizei *, GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC)(GLuint, GLenum, GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMSTAGEIVPROC)(GLuint, GLenum, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYINDEXEDIVPROC)(GLenum, GLuint, GLenum, GLint *); +typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLGETSUBROUTINEINDEXPROC)(GLuint, GLenum, const GLchar *); +typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC)(GLuint, GLenum, const GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMSUBROUTINEUIVPROC)(GLenum, GLint, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMDVPROC)(GLuint, GLint, GLdouble *); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISTRANSFORMFEEDBACKPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLMINSAMPLESHADINGPROC)(GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPATCHPARAMETERFVPROC)(GLenum, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPATCHPARAMETERIPROC)(GLenum, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPAUSETRANSFORMFEEDBACKPROC)(); +typedef void (INTERNAL_GL_APIENTRY *PFNGLRESUMETRANSFORMFEEDBACKPROC)(); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1DPROC)(GLint, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1DVPROC)(GLint, GLsizei, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2DPROC)(GLint, GLdouble, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2DVPROC)(GLint, GLsizei, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3DPROC)(GLint, GLdouble, GLdouble, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3DVPROC)(GLint, GLsizei, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4DPROC)(GLint, GLdouble, GLdouble, GLdouble, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4DVPROC)(GLint, GLsizei, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2X3DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2X4DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3X2DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3X4DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4X2DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4X3DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMSUBROUTINESUIVPROC)(GLenum, GLsizei, const GLuint *); + +// 4.1 +typedef void (INTERNAL_GL_APIENTRY *PFNGLACTIVESHADERPROGRAMPROC)(GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDPROGRAMPIPELINEPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARDEPTHFPROC)(GLfloat); +typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLCREATESHADERPROGRAMVPROC)(GLenum, GLsizei, const GLchar *const*); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEPROGRAMPIPELINESPROC)(GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHRANGEARRAYVPROC)(GLuint, GLsizei, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHRANGEINDEXEDPROC)(GLuint, GLdouble, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHRANGEFPROC)(GLfloat, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGENPROGRAMPIPELINESPROC)(GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETDOUBLEI_VPROC)(GLenum, GLuint, GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETFLOATI_VPROC)(GLenum, GLuint, GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMBINARYPROC)(GLuint, GLsizei, GLsizei *, GLenum *, void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMPIPELINEINFOLOGPROC)(GLuint, GLsizei, GLsizei *, GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMPIPELINEIVPROC)(GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSHADERPRECISIONFORMATPROC)(GLenum, GLenum, GLint *, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBLDVPROC)(GLuint, GLenum, GLdouble *); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISPROGRAMPIPELINEPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMBINARYPROC)(GLuint, GLenum, const void *, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMPARAMETERIPROC)(GLuint, GLenum, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1DPROC)(GLuint, GLint, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1DVPROC)(GLuint, GLint, GLsizei, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1FPROC)(GLuint, GLint, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1FVPROC)(GLuint, GLint, GLsizei, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1IPROC)(GLuint, GLint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1IVPROC)(GLuint, GLint, GLsizei, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1UIPROC)(GLuint, GLint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1UIVPROC)(GLuint, GLint, GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2DPROC)(GLuint, GLint, GLdouble, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2DVPROC)(GLuint, GLint, GLsizei, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2FPROC)(GLuint, GLint, GLfloat, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2FVPROC)(GLuint, GLint, GLsizei, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2IPROC)(GLuint, GLint, GLint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2IVPROC)(GLuint, GLint, GLsizei, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2UIPROC)(GLuint, GLint, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2UIVPROC)(GLuint, GLint, GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3DPROC)(GLuint, GLint, GLdouble, GLdouble, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3DVPROC)(GLuint, GLint, GLsizei, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3FPROC)(GLuint, GLint, GLfloat, GLfloat, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3FVPROC)(GLuint, GLint, GLsizei, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3IPROC)(GLuint, GLint, GLint, GLint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3IVPROC)(GLuint, GLint, GLsizei, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3UIPROC)(GLuint, GLint, GLuint, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3UIVPROC)(GLuint, GLint, GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4DPROC)(GLuint, GLint, GLdouble, GLdouble, GLdouble, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4DVPROC)(GLuint, GLint, GLsizei, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4FPROC)(GLuint, GLint, GLfloat, GLfloat, GLfloat, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4FVPROC)(GLuint, GLint, GLsizei, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4IPROC)(GLuint, GLint, GLint, GLint, GLint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4IVPROC)(GLuint, GLint, GLsizei, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4UIPROC)(GLuint, GLint, GLuint, GLuint, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4UIVPROC)(GLuint, GLint, GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLRELEASESHADERCOMPILERPROC)(); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSCISSORARRAYVPROC)(GLuint, GLsizei, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSCISSORINDEXEDPROC)(GLuint, GLint, GLint, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSCISSORINDEXEDVPROC)(GLuint, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSHADERBINARYPROC)(GLsizei, const GLuint *, GLenum, const void *, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLUSEPROGRAMSTAGESPROC)(GLuint, GLbitfield, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVALIDATEPROGRAMPIPELINEPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL1DPROC)(GLuint, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL1DVPROC)(GLuint, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL2DPROC)(GLuint, GLdouble, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL2DVPROC)(GLuint, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL3DPROC)(GLuint, GLdouble, GLdouble, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL3DVPROC)(GLuint, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL4DPROC)(GLuint, GLdouble, GLdouble, GLdouble, GLdouble); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL4DVPROC)(GLuint, const GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBLPOINTERPROC)(GLuint, GLint, GLenum, GLsizei, const void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVIEWPORTARRAYVPROC)(GLuint, GLsizei, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVIEWPORTINDEXEDFPROC)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVIEWPORTINDEXEDFVPROC)(GLuint, const GLfloat *); + +// 4.2 +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDIMAGETEXTUREPROC)(GLuint, GLuint, GLint, GLboolean, GLint, GLenum, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC)(GLenum, GLint, GLsizei, GLsizei, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC)(GLenum, GLsizei, GLenum, const void *, GLsizei, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC)(GLenum, GLsizei, GLenum, const void *, GLsizei, GLint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC)(GLenum, GLuint, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC)(GLenum, GLuint, GLuint, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC)(GLuint, GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTERNALFORMATIVPROC)(GLenum, GLenum, GLenum, GLsizei, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLMEMORYBARRIERPROC)(GLbitfield); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSTORAGE1DPROC)(GLenum, GLsizei, GLenum, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSTORAGE2DPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSTORAGE3DPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei); + +// 4.3 +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDVERTEXBUFFERPROC)(GLuint, GLuint, GLintptr, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERDATAPROC)(GLenum, GLenum, GLenum, GLenum, const void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERSUBDATAPROC)(GLenum, GLenum, GLintptr, GLsizeiptr, GLenum, GLenum, const void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYIMAGESUBDATAPROC)(GLuint, GLenum, GLint, GLint, GLint, GLint, GLuint, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDEBUGMESSAGECALLBACKPROC)(GLDEBUGPROC, const void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDEBUGMESSAGECONTROLPROC)(GLenum, GLenum, GLenum, GLsizei, const GLuint *, GLboolean); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDEBUGMESSAGEINSERTPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDISPATCHCOMPUTEPROC)(GLuint, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDISPATCHCOMPUTEINDIRECTPROC)(GLintptr); +typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERPARAMETERIPROC)(GLenum, GLenum, GLint); +typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLGETDEBUGMESSAGELOGPROC)(GLuint, GLsizei, GLenum *, GLenum *, GLuint *, GLenum *, GLsizei *, GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETFRAMEBUFFERPARAMETERIVPROC)(GLenum, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTERNALFORMATI64VPROC)(GLenum, GLenum, GLenum, GLsizei, GLint64 *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPOINTERVPROC)(GLenum, void **); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETOBJECTLABELPROC)(GLenum, GLuint, GLsizei, GLsizei *, GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETOBJECTPTRLABELPROC)(const void *, GLsizei, GLsizei *, GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMINTERFACEIVPROC)(GLuint, GLenum, GLenum, GLint *); +typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMRESOURCEINDEXPROC)(GLuint, GLenum, const GLchar *); +typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMRESOURCELOCATIONPROC)(GLuint, GLenum, const GLchar *); +typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC)(GLuint, GLenum, const GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMRESOURCENAMEPROC)(GLuint, GLenum, GLuint, GLsizei, GLsizei *, GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMRESOURCEIVPROC)(GLuint, GLenum, GLuint, GLsizei, const GLenum *, GLsizei, GLsizei *, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATEBUFFERDATAPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATEBUFFERSUBDATAPROC)(GLuint, GLintptr, GLsizeiptr); +typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATEFRAMEBUFFERPROC)(GLenum, GLsizei, const GLenum *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATESUBFRAMEBUFFERPROC)(GLenum, GLsizei, const GLenum *, GLint, GLint, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATETEXIMAGEPROC)(GLuint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATETEXSUBIMAGEPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLMULTIDRAWARRAYSINDIRECTPROC)(GLenum, const void *, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLMULTIDRAWELEMENTSINDIRECTPROC)(GLenum, GLenum, const void *, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLOBJECTLABELPROC)(GLenum, GLuint, GLsizei, const GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLOBJECTPTRLABELPROC)(const void *, GLsizei, const GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPOPDEBUGGROUPPROC)(); +typedef void (INTERNAL_GL_APIENTRY *PFNGLPUSHDEBUGGROUPPROC)(GLenum, GLuint, GLsizei, const GLchar *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLSHADERSTORAGEBLOCKBINDINGPROC)(GLuint, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXBUFFERRANGEPROC)(GLenum, GLenum, GLuint, GLintptr, GLsizeiptr); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSTORAGE2DMULTISAMPLEPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLboolean); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSTORAGE3DMULTISAMPLEPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREVIEWPROC)(GLuint, GLenum, GLuint, GLenum, GLuint, GLuint, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBBINDINGPROC)(GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBFORMATPROC)(GLuint, GLint, GLenum, GLboolean, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBIFORMATPROC)(GLuint, GLint, GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBLFORMATPROC)(GLuint, GLint, GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXBINDINGDIVISORPROC)(GLuint, GLuint); + +// NV_framebuffer_mixed_samples +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOVERAGEMODULATIONNVPROC)(GLenum); + +// 4.4 +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERSBASEPROC)(GLenum, GLuint, GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERSRANGEPROC)(GLenum, GLuint, GLsizei, const GLuint *, const GLintptr *, const GLsizeiptr *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDIMAGETEXTURESPROC)(GLuint, GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDSAMPLERSPROC)(GLuint, GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDTEXTURESPROC)(GLuint, GLsizei, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDVERTEXBUFFERSPROC)(GLuint, GLsizei, const GLuint *, const GLintptr *, const GLsizei *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBUFFERSTORAGEPROC)(GLenum, GLsizeiptr, const void *, GLbitfield); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARTEXIMAGEPROC)(GLuint, GLint, GLenum, GLenum, const void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARTEXSUBIMAGEPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void *); + +// 4.5 +typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDTEXTUREUNITPROC)(GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLBLITNAMEDFRAMEBUFFERPROC)(GLuint, GLuint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum); +typedef GLenum (INTERNAL_GL_APIENTRY *PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC)(GLuint, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDBUFFERDATAPROC)(GLuint, GLenum, GLenum, GLenum, const void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDBUFFERSUBDATAPROC)(GLuint, GLenum, GLintptr, GLsizeiptr, GLenum, GLenum, const void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDFRAMEBUFFERFIPROC)(GLuint, GLenum, const GLfloat, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDFRAMEBUFFERFVPROC)(GLuint, GLenum, GLint, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDFRAMEBUFFERIVPROC)(GLuint, GLenum, GLint, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC)(GLuint, GLenum, GLint, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCLIPCONTROLPROC)(GLenum, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC)(GLuint, GLint, GLint, GLsizei, GLenum, GLsizei, const void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC)(GLuint, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYNAMEDBUFFERSUBDATAPROC)(GLuint, GLuint, GLintptr, GLintptr, GLsizeiptr); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXTURESUBIMAGE1DPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXTURESUBIMAGE2DPROC)(GLuint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXTURESUBIMAGE3DPROC)(GLuint, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATEBUFFERSPROC)(GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATEFRAMEBUFFERSPROC)(GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATEPROGRAMPIPELINESPROC)(GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATEQUERIESPROC)(GLenum, GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATERENDERBUFFERSPROC)(GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATESAMPLERSPROC)(GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATETEXTURESPROC)(GLenum, GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATETRANSFORMFEEDBACKSPROC)(GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATEVERTEXARRAYSPROC)(GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLDISABLEVERTEXARRAYATTRIBPROC)(GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLENABLEVERTEXARRAYATTRIBPROC)(GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC)(GLuint, GLintptr, GLsizeiptr); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGENERATETEXTUREMIPMAPPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC)(GLuint, GLint, GLsizei, void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLsizei, void *); +typedef GLenum (INTERNAL_GL_APIENTRY *PFNGLGETGRAPHICSRESETSTATUSPROC)(); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDBUFFERPARAMETERI64VPROC)(GLuint, GLenum, GLint64 *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDBUFFERPARAMETERIVPROC)(GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDBUFFERPOINTERVPROC)(GLuint, GLenum, void **); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDBUFFERSUBDATAPROC)(GLuint, GLintptr, GLsizeiptr, void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLuint, GLenum, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC)(GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC)(GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYBUFFEROBJECTI64VPROC)(GLuint, GLuint, GLenum, GLintptr); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYBUFFEROBJECTIVPROC)(GLuint, GLuint, GLenum, GLintptr); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYBUFFEROBJECTUI64VPROC)(GLuint, GLuint, GLenum, GLintptr); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYBUFFEROBJECTUIVPROC)(GLuint, GLuint, GLenum, GLintptr); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTUREIMAGEPROC)(GLuint, GLint, GLenum, GLenum, GLsizei, void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTURELEVELPARAMETERFVPROC)(GLuint, GLint, GLenum, GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTURELEVELPARAMETERIVPROC)(GLuint, GLint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTUREPARAMETERIIVPROC)(GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTUREPARAMETERIUIVPROC)(GLuint, GLenum, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTUREPARAMETERFVPROC)(GLuint, GLenum, GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTUREPARAMETERIVPROC)(GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTURESUBIMAGEPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTRANSFORMFEEDBACKI64_VPROC)(GLuint, GLenum, GLuint, GLint64 *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTRANSFORMFEEDBACKI_VPROC)(GLuint, GLenum, GLuint, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTRANSFORMFEEDBACKIVPROC)(GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXARRAYINDEXED64IVPROC)(GLuint, GLuint, GLenum, GLint64 *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXARRAYINDEXEDIVPROC)(GLuint, GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXARRAYIVPROC)(GLuint, GLenum, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNCOMPRESSEDTEXIMAGEPROC)(GLenum, GLint, GLsizei, void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNTEXIMAGEPROC)(GLenum, GLint, GLenum, GLenum, GLsizei, void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNUNIFORMDVPROC)(GLuint, GLint, GLsizei, GLdouble *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNUNIFORMFVPROC)(GLuint, GLint, GLsizei, GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNUNIFORMIVPROC)(GLuint, GLint, GLsizei, GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNUNIFORMUIVPROC)(GLuint, GLint, GLsizei, GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC)(GLuint, GLsizei, const GLenum *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC)(GLuint, GLsizei, const GLenum *, GLint, GLint, GLsizei, GLsizei); +typedef void *(INTERNAL_GL_APIENTRY *PFNGLMAPNAMEDBUFFERPROC)(GLuint, GLenum); +typedef void *(INTERNAL_GL_APIENTRY *PFNGLMAPNAMEDBUFFERRANGEPROC)(GLuint, GLintptr, GLsizeiptr, GLbitfield); +typedef void (INTERNAL_GL_APIENTRY *PFNGLMEMORYBARRIERBYREGIONPROC)(GLbitfield); +typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDBUFFERDATAPROC)(GLuint, GLsizeiptr, const void *, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDBUFFERSTORAGEPROC)(GLuint, GLsizeiptr, const void *, GLbitfield); +typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDBUFFERSUBDATAPROC)(GLuint, GLintptr, GLsizeiptr, const void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC)(GLuint, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC)(GLuint, GLsizei, const GLenum *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC)(GLuint, GLenum, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC)(GLuint, GLenum); +typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC)(GLuint, GLenum, GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERTEXTUREPROC)(GLuint, GLenum, GLuint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC)(GLuint, GLenum, GLuint, GLint, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDRENDERBUFFERSTORAGEPROC)(GLuint, GLenum, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLuint, GLsizei, GLenum, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLREADNPIXELSPROC)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREBARRIERPROC)(); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREBUFFERPROC)(GLuint, GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREBUFFERRANGEPROC)(GLuint, GLenum, GLuint, GLintptr, GLsizeiptr); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERIIVPROC)(GLuint, GLenum, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERIUIVPROC)(GLuint, GLenum, const GLuint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERFPROC)(GLuint, GLenum, GLfloat); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERFVPROC)(GLuint, GLenum, const GLfloat *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERIPROC)(GLuint, GLenum, GLint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERIVPROC)(GLuint, GLenum, const GLint *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESTORAGE1DPROC)(GLuint, GLsizei, GLenum, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESTORAGE2DPROC)(GLuint, GLsizei, GLenum, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC)(GLuint, GLsizei, GLenum, GLsizei, GLsizei, GLboolean); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESTORAGE3DPROC)(GLuint, GLsizei, GLenum, GLsizei, GLsizei, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC)(GLuint, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESUBIMAGE1DPROC)(GLuint, GLint, GLint, GLsizei, GLenum, GLenum, const void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESUBIMAGE2DPROC)(GLuint, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESUBIMAGE3DPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void *); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC)(GLuint, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC)(GLuint, GLuint, GLuint, GLintptr, GLsizeiptr); +typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLUNMAPNAMEDBUFFERPROC)(GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYATTRIBBINDINGPROC)(GLuint, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYATTRIBFORMATPROC)(GLuint, GLuint, GLint, GLenum, GLboolean, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYATTRIBIFORMATPROC)(GLuint, GLuint, GLint, GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYATTRIBLFORMATPROC)(GLuint, GLuint, GLint, GLenum, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYBINDINGDIVISORPROC)(GLuint, GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYELEMENTBUFFERPROC)(GLuint, GLuint); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYVERTEXBUFFERPROC)(GLuint, GLuint, GLuint, GLintptr, GLsizei); +typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYVERTEXBUFFERSPROC)(GLuint, GLuint, GLsizei, const GLuint *, const GLintptr *, const GLsizei *); + +} + +#endif // LIBANGLE_RENDERER_GL_FUNCTIONSGLTYPEDEFS_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp b/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp new file mode 100755 index 000000000..e98401d0a --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp @@ -0,0 +1,981 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayGLX.cpp: GLX implementation of egl::Display + +#include "libANGLE/renderer/gl/glx/DisplayGLX.h" + +#include <EGL/eglext.h> +#include <algorithm> +#include <cstring> +#include <fstream> + +#include "common/debug.h" +#include "libANGLE/Config.h" +#include "libANGLE/Display.h" +#include "libANGLE/Surface.h" +#include "libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h" +#include "libANGLE/renderer/gl/glx/WindowSurfaceGLX.h" +#include "libANGLE/renderer/gl/RendererGL.h" +#include "libANGLE/renderer/gl/renderergl_utils.h" +#include "third_party/libXNVCtrl/NVCtrl.h" +#include "third_party/libXNVCtrl/NVCtrlLib.h" + +namespace +{ + +// Scan /etc/ati/amdpcsdb.default for "ReleaseVersion". +// Return empty string on failing. +egl::Error GetAMDDriverVersion(std::string *version) +{ + *version = ""; + + const char kAMDDriverInfoFileName[] = "/etc/ati/amdpcsdb.default"; + std::ifstream file(kAMDDriverInfoFileName); + + if (!file) + { + return egl::Error(EGL_SUCCESS); + } + + std::string line; + while (std::getline(file, line)) + { + static const char kReleaseVersion[] = "ReleaseVersion="; + if (line.compare(0, std::strlen(kReleaseVersion), kReleaseVersion) != 0) + { + continue; + } + + const size_t begin = line.find_first_of("0123456789"); + if (begin == std::string::npos) + { + continue; + } + + const size_t end = line.find_first_not_of("0123456789.", begin); + if (end == std::string::npos) + { + *version = line.substr(begin); + } + else + { + *version = line.substr(begin, end - begin); + } + return egl::Error(EGL_SUCCESS); + } + return egl::Error(EGL_SUCCESS); +} + +} // anonymous namespace + +namespace rx +{ + +static int IgnoreX11Errors(Display *, XErrorEvent *) +{ + return 0; +} + +SwapControlData::SwapControlData() + : targetSwapInterval(0), + maxSwapInterval(-1), + currentSwapInterval(-1) +{ +} + +class FunctionsGLGLX : public FunctionsGL +{ + public: + FunctionsGLGLX(PFNGETPROCPROC getProc) + : mGetProc(getProc) + { + } + + ~FunctionsGLGLX() override {} + + private: + void *loadProcAddress(const std::string &function) override + { + return reinterpret_cast<void*>(mGetProc(function.c_str())); + } + + PFNGETPROCPROC mGetProc; +}; + +DisplayGLX::DisplayGLX() + : DisplayGL(), + mFunctionsGL(nullptr), + mRequestedVisual(-1), + mContextConfig(nullptr), + mContext(nullptr), + mDummyPbuffer(0), + mUsesNewXDisplay(false), + mIsMesa(false), + mHasMultisample(false), + mHasARBCreateContext(false), + mHasARBCreateContextProfile(false), + mHasARBCreateContextRobustness(false), + mHasEXTCreateContextES2Profile(false), + mSwapControl(SwapControl::Absent), + mMinSwapInterval(0), + mMaxSwapInterval(0), + mCurrentSwapInterval(-1), + mXDisplay(nullptr), + mEGLDisplay(nullptr) +{ +} + +DisplayGLX::~DisplayGLX() +{ +} + +egl::Error DisplayGLX::initialize(egl::Display *display) +{ + mEGLDisplay = display; + mXDisplay = display->getNativeDisplayId(); + const auto &attribMap = display->getAttributeMap(); + + // ANGLE_platform_angle allows the creation of a default display + // using EGL_DEFAULT_DISPLAY (= nullptr). In this case just open + // the display specified by the DISPLAY environment variable. + if (mXDisplay == EGL_DEFAULT_DISPLAY) + { + mUsesNewXDisplay = true; + mXDisplay = XOpenDisplay(NULL); + if (!mXDisplay) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not open the default X display."); + } + } + + std::string glxInitError; + if (!mGLX.initialize(mXDisplay, DefaultScreen(mXDisplay), &glxInitError)) + { + return egl::Error(EGL_NOT_INITIALIZED, glxInitError.c_str()); + } + + mHasMultisample = mGLX.minorVersion > 3 || mGLX.hasExtension("GLX_ARB_multisample"); + mHasARBCreateContext = mGLX.hasExtension("GLX_ARB_create_context"); + mHasARBCreateContextProfile = mGLX.hasExtension("GLX_ARB_create_context_profile"); + mHasARBCreateContextRobustness = mGLX.hasExtension("GLX_ARB_create_context_robustness"); + mHasEXTCreateContextES2Profile = mGLX.hasExtension("GLX_EXT_create_context_es2_profile"); + + std::string clientVendor = mGLX.getClientString(GLX_VENDOR); + mIsMesa = clientVendor.find("Mesa") != std::string::npos; + + // Choose the swap_control extension to use, if any. + // The EXT version is better as it allows glXSwapInterval to be called per + // window, while we'll potentially need to change the swap interval on each + // swap buffers when using the SGI or MESA versions. + if (mGLX.hasExtension("GLX_EXT_swap_control")) + { + mSwapControl = SwapControl::EXT; + + // In GLX_EXT_swap_control querying these is done on a GLXWindow so we just + // set default values. + mMinSwapInterval = 0; + mMaxSwapInterval = 4; + } + else if (mGLX.hasExtension("GLX_MESA_swap_control")) + { + // If we have the Mesa or SGI extension, assume that you can at least set + // a swap interval of 0 or 1. + mSwapControl = SwapControl::Mesa; + mMinSwapInterval = 0; + mMinSwapInterval = 1; + } + else if (mGLX.hasExtension("GLX_SGI_swap_control")) + { + mSwapControl = SwapControl::SGI; + mMinSwapInterval = 0; + mMinSwapInterval = 1; + } + else + { + mSwapControl = SwapControl::Absent; + mMinSwapInterval = 1; + mMinSwapInterval = 1; + } + + if (attribMap.contains(EGL_X11_VISUAL_ID_ANGLE)) + { + mRequestedVisual = static_cast<EGLint>(attribMap.get(EGL_X11_VISUAL_ID_ANGLE, -1)); + + // There is no direct way to get the GLXFBConfig matching an X11 visual ID + // so we have to iterate over all the GLXFBConfigs to find the right one. + int nConfigs; + int attribList[] = { + None, + }; + glx::FBConfig *allConfigs = mGLX.chooseFBConfig(attribList, &nConfigs); + + for (int i = 0; i < nConfigs; ++i) + { + if (getGLXFBConfigAttrib(allConfigs[i], GLX_VISUAL_ID) == mRequestedVisual) + { + mContextConfig = allConfigs[i]; + break; + } + } + XFree(allConfigs); + + if (mContextConfig == nullptr) + { + return egl::Error(EGL_NOT_INITIALIZED, "Invalid visual ID requested."); + } + } + else + { + // When glXMakeCurrent is called, the context and the surface must be + // compatible which in glX-speak means that their config have the same + // color buffer type, are both RGBA or ColorIndex, and their buffers have + // the same depth, if they exist. + // Since our whole EGL implementation is backed by only one GL context, this + // context must be compatible with all the GLXFBConfig corresponding to the + // EGLconfigs that we will be exposing. + int nConfigs; + int attribList[] = + { + // We want RGBA8 and DEPTH24_STENCIL8 + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_DEPTH_SIZE, 24, + GLX_STENCIL_SIZE, 8, + // We want RGBA rendering (vs COLOR_INDEX) and doublebuffer + GLX_RENDER_TYPE, GLX_RGBA_BIT, + // Double buffer is not strictly required as a non-doublebuffer + // context can work with a doublebuffered surface, but it still + // flickers and all applications want doublebuffer anyway. + GLX_DOUBLEBUFFER, True, + // All of these must be supported for full EGL support + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_PBUFFER_BIT | GLX_PIXMAP_BIT, + // This makes sure the config have an associated visual Id + GLX_X_RENDERABLE, True, + GLX_CONFIG_CAVEAT, GLX_NONE, + None + }; + glx::FBConfig *candidates = mGLX.chooseFBConfig(attribList, &nConfigs); + if (nConfigs == 0) + { + XFree(candidates); + return egl::Error(EGL_NOT_INITIALIZED, "Could not find a decent GLX FBConfig to create the context."); + } + mContextConfig = candidates[0]; + XFree(candidates); + } + + const auto &eglAttributes = display->getAttributeMap(); + if (mHasARBCreateContext) + { + egl::Error error = initializeContext(mContextConfig, eglAttributes, &mContext); + if (error.isError()) + { + return error; + } + } + else + { + if (eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, + EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) == + EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE) + { + return egl::Error(EGL_NOT_INITIALIZED, + "Cannot create an OpenGL ES platform on GLX without the " + "GLX_ARB_create_context extension."); + } + + XVisualInfo visualTemplate; + visualTemplate.visualid = getGLXFBConfigAttrib(mContextConfig, GLX_VISUAL_ID); + + int numVisuals = 0; + XVisualInfo *visuals = + XGetVisualInfo(mXDisplay, VisualIDMask, &visualTemplate, &numVisuals); + if (numVisuals <= 0) + { + return egl::Error(EGL_NOT_INITIALIZED, + "Could not get the visual info from the fb config"); + } + ASSERT(numVisuals == 1); + + mContext = mGLX.createContext(&visuals[0], nullptr, true); + XFree(visuals); + + if (!mContext) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context."); + } + } + ASSERT(mContext); + + // FunctionsGL and DisplayGL need to make a few GL calls, for example to + // query the version of the context so we need to make the context current. + // glXMakeCurrent requires a GLXDrawable so we create a temporary Pbuffer + // (of size 1, 1) for the duration of these calls. + // Ideally we would want to unset the current context and destroy the pbuffer + // before going back to the application but this is TODO + // We could use a pbuffer of size (0, 0) but it fails on the Intel Mesa driver + // as commented on https://bugs.freedesktop.org/show_bug.cgi?id=38869 so we + // use (1, 1) instead. + + int dummyPbufferAttribs[] = + { + GLX_PBUFFER_WIDTH, 1, + GLX_PBUFFER_HEIGHT, 1, + None, + }; + mDummyPbuffer = mGLX.createPbuffer(mContextConfig, dummyPbufferAttribs); + if (!mDummyPbuffer) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not create the dummy pbuffer."); + } + + if (!mGLX.makeCurrent(mDummyPbuffer, mContext)) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not make the dummy pbuffer current."); + } + + mFunctionsGL = new FunctionsGLGLX(mGLX.getProc); + mFunctionsGL->initialize(); + + // TODO(cwallez, angleproject:1303) Disable the OpenGL ES backend on Linux NVIDIA and Intel as + // it has problems on our automated testing. An OpenGL ES backend might not trigger this test if + // there is no Desktop OpenGL support, but that's not the case in our automated testing. + VendorID vendor = GetVendorID(mFunctionsGL); + bool isOpenGLES = + eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) == + EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE; + if (isOpenGLES && (IsIntel(vendor) || IsNvidia(vendor))) + { + return egl::Error(EGL_NOT_INITIALIZED, "Intel or NVIDIA OpenGL ES drivers are not supported."); + } + + syncXCommands(); + + return DisplayGL::initialize(display); +} + +void DisplayGLX::terminate() +{ + DisplayGL::terminate(); + + if (mDummyPbuffer) + { + mGLX.destroyPbuffer(mDummyPbuffer); + mDummyPbuffer = 0; + } + + if (mContext) + { + mGLX.destroyContext(mContext); + mContext = nullptr; + } + + mGLX.terminate(); + + SafeDelete(mFunctionsGL); +} + +SurfaceImpl *DisplayGLX::createWindowSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) +{ + ASSERT(configIdToGLXConfig.count(configuration->configID) > 0); + glx::FBConfig fbConfig = configIdToGLXConfig[configuration->configID]; + + return new WindowSurfaceGLX(state, mGLX, this, getRenderer(), window, mGLX.getDisplay(), + mContext, fbConfig); +} + +SurfaceImpl *DisplayGLX::createPbufferSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + const egl::AttributeMap &attribs) +{ + ASSERT(configIdToGLXConfig.count(configuration->configID) > 0); + glx::FBConfig fbConfig = configIdToGLXConfig[configuration->configID]; + + EGLint width = static_cast<EGLint>(attribs.get(EGL_WIDTH, 0)); + EGLint height = static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0)); + bool largest = (attribs.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE); + + return new PbufferSurfaceGLX(state, getRenderer(), width, height, largest, mGLX, mContext, + fbConfig); +} + +SurfaceImpl *DisplayGLX::createPbufferFromClientBuffer(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) +{ + UNIMPLEMENTED(); + return nullptr; +} + +SurfaceImpl *DisplayGLX::createPixmapSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) +{ + UNIMPLEMENTED(); + return nullptr; +} + +egl::Error DisplayGLX::getDevice(DeviceImpl **device) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_BAD_DISPLAY); +} + +egl::Error DisplayGLX::initializeContext(glx::FBConfig config, + const egl::AttributeMap &eglAttributes, + glx::Context *context) +{ + int profileMask = 0; + + EGLint requestedDisplayType = static_cast<EGLint>( + eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)); + if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE) + { + if (!mHasEXTCreateContextES2Profile) + { + return egl::Error(EGL_NOT_INITIALIZED, + "Cannot create an OpenGL ES platform on GLX without the " + "GLX_EXT_create_context_es_profile extension."); + } + + ASSERT(mHasARBCreateContextProfile); + profileMask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT; + } + + // Create a context of the requested version, if any. + gl::Version requestedVersion(static_cast<EGLint>(eglAttributes.get( + EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE)), + static_cast<EGLint>(eglAttributes.get( + EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE))); + if (static_cast<EGLint>(requestedVersion.major) != EGL_DONT_CARE && + static_cast<EGLint>(requestedVersion.minor) != EGL_DONT_CARE) + { + if (!(profileMask & GLX_CONTEXT_ES2_PROFILE_BIT_EXT) && + requestedVersion >= gl::Version(3, 2)) + { + profileMask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + } + return createContextAttribs(config, requestedVersion, profileMask, context); + } + + // It is commonly assumed that glXCreateContextAttrib will create a context + // of the highest version possible but it is not specified in the spec and + // is not true on the Mesa drivers. On Mesa, Instead we try to create a + // context per GL version until we succeed, starting from newer version. + // On both Mesa and other drivers we try to create a desktop context and fall + // back to ES context. + // The code could be simpler if the Mesa code path was used for all drivers, + // however the cost of failing a context creation can be high (3 milliseconds + // for the NVIDIA driver). The good thing is that failed context creation only + // takes 0.1 milliseconds on Mesa. + + struct ContextCreationInfo + { + EGLint displayType; + int profileFlag; + Optional<gl::Version> version; + }; + + // clang-format off + // For regular drivers we try to create a core, compatibility, then ES context. + // Without requiring any specific version (the Optional version is undefined). + const ContextCreationInfo contextsToTry[] = { + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, {} }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, {} }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, {} }, + }; + + // On Mesa we try to create a core context, except for versions below 3.2 + // where it is not applicable. (and fallback to ES as well) + const ContextCreationInfo mesaContextsToTry[] = { + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 5) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 4) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 3) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 2) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 1) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 0) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(3, 3) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(3, 2) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(3, 1) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(3, 0) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(2, 0) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 5) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 4) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 3) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 2) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 1) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 0) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { gl::Version(3, 2) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { gl::Version(3, 1) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { gl::Version(3, 0) } }, + { EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { gl::Version(2, 0) } }, + }; + // clang-format on + + const ContextCreationInfo *toTry = contextsToTry; + size_t toTryLength = ArraySize(contextsToTry); + if (mIsMesa) + { + toTry = mesaContextsToTry; + toTryLength = ArraySize(mesaContextsToTry); + } + + // NOTE: below we return as soon as we're able to create a context so the + // "error" variable is EGL_SUCCESS when returned contrary to the common idiom + // of returning "error" when there is an actual error. + for (size_t i = 0; i < toTryLength; ++i) + { + const ContextCreationInfo &info = toTry[i]; + if (requestedDisplayType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE && + requestedDisplayType != info.displayType) + { + continue; + } + + egl::Error error = createContextAttribs(config, info.version, info.profileFlag, context); + if (!error.isError()) + { + return error; + } + } + + return egl::Error(EGL_NOT_INITIALIZED, "Could not create a backing OpenGL context."); +} + +egl::ConfigSet DisplayGLX::generateConfigs() +{ + egl::ConfigSet configs; + configIdToGLXConfig.clear(); + + const gl::Version &maxVersion = getMaxSupportedESVersion(); + ASSERT(maxVersion >= gl::Version(2, 0)); + bool supportsES3 = maxVersion >= gl::Version(3, 0); + + int contextRedSize = getGLXFBConfigAttrib(mContextConfig, GLX_RED_SIZE); + int contextGreenSize = getGLXFBConfigAttrib(mContextConfig, GLX_GREEN_SIZE); + int contextBlueSize = getGLXFBConfigAttrib(mContextConfig, GLX_BLUE_SIZE); + int contextAlphaSize = getGLXFBConfigAttrib(mContextConfig, GLX_ALPHA_SIZE); + + int contextDepthSize = getGLXFBConfigAttrib(mContextConfig, GLX_DEPTH_SIZE); + int contextStencilSize = getGLXFBConfigAttrib(mContextConfig, GLX_STENCIL_SIZE); + + int contextSamples = mHasMultisample ? getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLES) : 0; + int contextSampleBuffers = + mHasMultisample ? getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLE_BUFFERS) : 0; + + int contextAccumRedSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_RED_SIZE); + int contextAccumGreenSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_GREEN_SIZE); + int contextAccumBlueSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_BLUE_SIZE); + int contextAccumAlphaSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_ALPHA_SIZE); + + int attribList[] = + { + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_X_RENDERABLE, True, + GLX_DOUBLEBUFFER, True, + None, + }; + + int glxConfigCount; + glx::FBConfig *glxConfigs = mGLX.chooseFBConfig(attribList, &glxConfigCount); + + for (int i = 0; i < glxConfigCount; i++) + { + glx::FBConfig glxConfig = glxConfigs[i]; + egl::Config config; + + // Native stuff + config.nativeVisualID = getGLXFBConfigAttrib(glxConfig, GLX_VISUAL_ID); + config.nativeVisualType = getGLXFBConfigAttrib(glxConfig, GLX_X_VISUAL_TYPE); + config.nativeRenderable = EGL_TRUE; + + // When a visual ID has been specified with EGL_ANGLE_x11_visual we should + // only return configs with this visual: it will maximize performance by avoid + // blits in the driver when showing the window on the screen. + if (mRequestedVisual != -1 && config.nativeVisualID != mRequestedVisual) + { + continue; + } + + // Buffer sizes + config.redSize = getGLXFBConfigAttrib(glxConfig, GLX_RED_SIZE); + config.greenSize = getGLXFBConfigAttrib(glxConfig, GLX_GREEN_SIZE); + config.blueSize = getGLXFBConfigAttrib(glxConfig, GLX_BLUE_SIZE); + config.alphaSize = getGLXFBConfigAttrib(glxConfig, GLX_ALPHA_SIZE); + config.depthSize = getGLXFBConfigAttrib(glxConfig, GLX_DEPTH_SIZE); + config.stencilSize = getGLXFBConfigAttrib(glxConfig, GLX_STENCIL_SIZE); + + // We require RGBA8 and the D24S8 (or no DS buffer) + if (config.redSize != contextRedSize || config.greenSize != contextGreenSize || + config.blueSize != contextBlueSize || config.alphaSize != contextAlphaSize) + { + continue; + } + // The GLX spec says that it is ok for a whole buffer to not be present + // however the Mesa Intel driver (and probably on other Mesa drivers) + // fails to make current when the Depth stencil doesn't exactly match the + // configuration. + bool hasSameDepthStencil = + config.depthSize == contextDepthSize && config.stencilSize == contextStencilSize; + bool hasNoDepthStencil = config.depthSize == 0 && config.stencilSize == 0; + if (!hasSameDepthStencil && (mIsMesa || !hasNoDepthStencil)) + { + continue; + } + + config.colorBufferType = EGL_RGB_BUFFER; + config.luminanceSize = 0; + config.alphaMaskSize = 0; + + config.bufferSize = config.redSize + config.greenSize + config.blueSize + config.alphaSize; + + // Multisample and accumulation buffers + int samples = mHasMultisample ? getGLXFBConfigAttrib(glxConfig, GLX_SAMPLES) : 0; + int sampleBuffers = + mHasMultisample ? getGLXFBConfigAttrib(glxConfig, GLX_SAMPLE_BUFFERS) : 0; + + int accumRedSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_RED_SIZE); + int accumGreenSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_GREEN_SIZE); + int accumBlueSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_BLUE_SIZE); + int accumAlphaSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_ALPHA_SIZE); + + if (samples != contextSamples || + sampleBuffers != contextSampleBuffers || + accumRedSize != contextAccumRedSize || + accumGreenSize != contextAccumGreenSize || + accumBlueSize != contextAccumBlueSize || + accumAlphaSize != contextAccumAlphaSize) + { + continue; + } + + config.samples = samples; + config.sampleBuffers = sampleBuffers; + + // Transparency + if (getGLXFBConfigAttrib(glxConfig, GLX_TRANSPARENT_TYPE) == GLX_TRANSPARENT_RGB) + { + config.transparentType = EGL_TRANSPARENT_RGB; + config.transparentRedValue = getGLXFBConfigAttrib(glxConfig, GLX_TRANSPARENT_RED_VALUE); + config.transparentGreenValue = getGLXFBConfigAttrib(glxConfig, GLX_TRANSPARENT_GREEN_VALUE); + config.transparentBlueValue = getGLXFBConfigAttrib(glxConfig, GLX_TRANSPARENT_BLUE_VALUE); + } + else + { + config.transparentType = EGL_NONE; + } + + // Pbuffer + config.maxPBufferWidth = getGLXFBConfigAttrib(glxConfig, GLX_MAX_PBUFFER_WIDTH); + config.maxPBufferHeight = getGLXFBConfigAttrib(glxConfig, GLX_MAX_PBUFFER_HEIGHT); + config.maxPBufferPixels = getGLXFBConfigAttrib(glxConfig, GLX_MAX_PBUFFER_PIXELS); + + // Caveat + config.configCaveat = EGL_NONE; + + int caveat = getGLXFBConfigAttrib(glxConfig, GLX_CONFIG_CAVEAT); + if (caveat == GLX_SLOW_CONFIG) + { + config.configCaveat = EGL_SLOW_CONFIG; + } + else if (caveat == GLX_NON_CONFORMANT_CONFIG) + { + continue; + } + + // Misc + config.level = getGLXFBConfigAttrib(glxConfig, GLX_LEVEL); + + config.bindToTextureRGB = EGL_FALSE; + config.bindToTextureRGBA = EGL_FALSE; + + int glxDrawable = getGLXFBConfigAttrib(glxConfig, GLX_DRAWABLE_TYPE); + config.surfaceType = 0 | + (glxDrawable & GLX_WINDOW_BIT ? EGL_WINDOW_BIT : 0) | + (glxDrawable & GLX_PBUFFER_BIT ? EGL_PBUFFER_BIT : 0) | + (glxDrawable & GLX_PIXMAP_BIT ? EGL_PIXMAP_BIT : 0); + + config.minSwapInterval = mMinSwapInterval; + config.maxSwapInterval = mMaxSwapInterval; + + // TODO(cwallez) wildly guessing these formats, another TODO says they should be removed anyway + config.renderTargetFormat = GL_RGBA8; + config.depthStencilFormat = GL_DEPTH24_STENCIL8; + + config.conformant = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0); + config.renderableType = config.conformant; + + // TODO(cwallez) I have no idea what this is + config.matchNativePixmap = EGL_NONE; + + int id = configs.add(config); + configIdToGLXConfig[id] = glxConfig; + } + + XFree(glxConfigs); + + return configs; +} + +bool DisplayGLX::testDeviceLost() +{ + if (mHasARBCreateContextRobustness) + { + return getRenderer()->getResetStatus() != GL_NO_ERROR; + } + + return false; +} + +egl::Error DisplayGLX::restoreLostDevice() +{ + return egl::Error(EGL_BAD_DISPLAY); +} + +bool DisplayGLX::isValidNativeWindow(EGLNativeWindowType window) const +{ + // There is no function in Xlib to check the validity of a Window directly. + // However a small number of functions used to obtain window information + // return a status code (0 meaning failure) and guarantee that they will + // fail if the window doesn't exist (the rational is that these function + // are used by window managers). Out of these function we use XQueryTree + // as it seems to be the simplest; a drawback is that it will allocate + // memory for the list of children, because we use a child window for + // WindowSurface. + Window root; + Window parent; + Window *children = nullptr; + unsigned nChildren; + int status = XQueryTree(mGLX.getDisplay(), window, &root, &parent, &children, &nChildren); + if (children) + { + XFree(children); + } + return status != 0; +} + +std::string DisplayGLX::getVendorString() const +{ + // UNIMPLEMENTED(); + return ""; +} + +egl::Error DisplayGLX::waitClient() const +{ + mGLX.waitGL(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayGLX::getDriverVersion(std::string *version) const +{ + VendorID vendor = GetVendorID(mFunctionsGL); + + switch (vendor) + { + case VENDOR_ID_NVIDIA: + return getNVIDIADriverVersion(version); + case VENDOR_ID_AMD: + return GetAMDDriverVersion(version); + default: + *version = ""; + return egl::Error(EGL_SUCCESS); + } +} + +egl::Error DisplayGLX::waitNative(EGLint engine, + egl::Surface *drawSurface, + egl::Surface *readSurface) const +{ + // eglWaitNative is used to notice the driver of changes in X11 for the current surface, such as + // changes of the window size. We use this event to update the child window of WindowSurfaceGLX + // to match its parent window's size. + // Handling eglWaitNative this way helps the application control when resize happens. This is + // important because drivers have a tendency to clobber the back buffer when the windows are + // resized. See http://crbug.com/326995 + if (drawSurface != nullptr) + { + SurfaceGLX *glxDrawSurface = GetImplAs<SurfaceGLX>(drawSurface); + egl::Error error = glxDrawSurface->checkForResize(); + if (error.isError()) + { + return error; + } + } + + if (readSurface != drawSurface && readSurface != nullptr) + { + SurfaceGLX *glxReadSurface = GetImplAs<SurfaceGLX>(readSurface); + egl::Error error = glxReadSurface->checkForResize(); + if (error.isError()) + { + return error; + } + } + + // We still need to forward the resizing of the child window to the driver. + mGLX.waitX(); + return egl::Error(EGL_SUCCESS); +} + +void DisplayGLX::syncXCommands() const +{ + if (mUsesNewXDisplay) + { + XSync(mGLX.getDisplay(), False); + } +} + +void DisplayGLX::setSwapInterval(glx::Drawable drawable, SwapControlData *data) +{ + ASSERT(data != nullptr); + + // TODO(cwallez) error checking? + if (mSwapControl == SwapControl::EXT) + { + // Prefer the EXT extension, it gives per-drawable swap intervals, which will + // minimize the number of driver calls. + if (data->maxSwapInterval < 0) + { + unsigned int maxSwapInterval = 0; + mGLX.queryDrawable(drawable, GLX_MAX_SWAP_INTERVAL_EXT, &maxSwapInterval); + data->maxSwapInterval = static_cast<int>(maxSwapInterval); + } + + // When the egl configs were generated we had to guess what the max swap interval + // was because we didn't have a window to query it one (and that this max could + // depend on the monitor). This means that the target interval might be higher + // than the max interval and needs to be clamped. + const int realInterval = std::min(data->targetSwapInterval, data->maxSwapInterval); + if (data->currentSwapInterval != realInterval) + { + mGLX.swapIntervalEXT(drawable, realInterval); + data->currentSwapInterval = realInterval; + } + } + else if (mCurrentSwapInterval != data->targetSwapInterval) + { + // With the Mesa or SGI extensions we can still do per-drawable swap control + // manually but it is more expensive in number of driver calls. + if (mSwapControl == SwapControl::Mesa) + { + mGLX.swapIntervalMESA(data->targetSwapInterval); + } + else if (mSwapControl == SwapControl::SGI) + { + mGLX.swapIntervalSGI(data->targetSwapInterval); + } + mCurrentSwapInterval = data->targetSwapInterval; + } +} + +bool DisplayGLX::isValidWindowVisualId(unsigned long visualId) const +{ + return mRequestedVisual == -1 || static_cast<unsigned long>(mRequestedVisual) == visualId; +} + +const FunctionsGL *DisplayGLX::getFunctionsGL() const +{ + return mFunctionsGL; +} + +void DisplayGLX::generateExtensions(egl::DisplayExtensions *outExtensions) const +{ + outExtensions->createContextRobustness = mHasARBCreateContextRobustness; +} + +void DisplayGLX::generateCaps(egl::Caps *outCaps) const +{ + outCaps->textureNPOT = true; +} + +int DisplayGLX::getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const +{ + int result; + mGLX.getFBConfigAttrib(config, attrib, &result); + return result; +} + +egl::Error DisplayGLX::createContextAttribs(glx::FBConfig, + const Optional<gl::Version> &version, + int profileMask, + glx::Context *context) const +{ + std::vector<int> attribs; + + if (mHasARBCreateContextRobustness) + { + attribs.push_back(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB); + attribs.push_back(GLX_LOSE_CONTEXT_ON_RESET_ARB); + } + + if (version.valid()) + { + attribs.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB); + attribs.push_back(version.value().major); + + attribs.push_back(GLX_CONTEXT_MINOR_VERSION_ARB); + attribs.push_back(version.value().minor); + } + + if (profileMask != 0 && mHasARBCreateContextProfile) + { + attribs.push_back(GLX_CONTEXT_PROFILE_MASK_ARB); + attribs.push_back(profileMask); + } + + attribs.push_back(None); + + // When creating a context with glXCreateContextAttribsARB, a variety of X11 errors can + // be generated. To prevent these errors from crashing our process, we simply ignore + // them and only look if GLXContext was created. + // Process all events before setting the error handler to avoid desynchronizing XCB instances + // (the error handler is NOT per-display). + XSync(mXDisplay, False); + auto oldErrorHandler = XSetErrorHandler(IgnoreX11Errors); + *context = mGLX.createContextAttribsARB(mContextConfig, nullptr, True, attribs.data()); + XSetErrorHandler(oldErrorHandler); + + if (!*context) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context."); + } + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayGLX::getNVIDIADriverVersion(std::string *version) const +{ + *version = ""; + + int eventBase = 0; + int errorBase = 0; + if (XNVCTRLQueryExtension(mXDisplay, &eventBase, &errorBase)) + { + int screenCount = ScreenCount(mXDisplay); + for (int screen = 0; screen < screenCount; ++screen) + { + char *buffer = nullptr; + if (XNVCTRLIsNvScreen(mXDisplay, screen) && + XNVCTRLQueryStringAttribute(mXDisplay, screen, 0, + NV_CTRL_STRING_NVIDIA_DRIVER_VERSION, &buffer)) + { + *version = buffer; + XFree(buffer); + } + } + } + + return egl::Error(EGL_SUCCESS); +} +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h b/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h new file mode 100755 index 000000000..7e870c2f3 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h @@ -0,0 +1,151 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayGLX.h: GLX implementation of egl::Display + +#ifndef LIBANGLE_RENDERER_GL_GLX_DISPLAYGLX_H_ +#define LIBANGLE_RENDERER_GL_GLX_DISPLAYGLX_H_ + +#include <string> +#include <vector> + +#include "common/Optional.h" +#include "libANGLE/renderer/gl/DisplayGL.h" +#include "libANGLE/renderer/gl/glx/FunctionsGLX.h" + +namespace rx +{ + +class FunctionsGLX; + +// State-tracking data for the swap control to allow DisplayGLX to remember per +// drawable information for swap control. +struct SwapControlData +{ + SwapControlData(); + + // Set by the drawable + int targetSwapInterval; + + // DisplayGLX-side state-tracking + int maxSwapInterval; + int currentSwapInterval; +}; + +class DisplayGLX : public DisplayGL +{ + public: + DisplayGLX(); + ~DisplayGLX() override; + + egl::Error initialize(egl::Display *display) override; + void terminate() override; + + SurfaceImpl *createWindowSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) override; + + egl::ConfigSet generateConfigs() override; + + bool testDeviceLost() override; + egl::Error restoreLostDevice() override; + + bool isValidNativeWindow(EGLNativeWindowType window) const override; + + egl::Error getDevice(DeviceImpl **device) override; + + std::string getVendorString() const override; + + egl::Error waitClient() const override; + egl::Error waitNative(EGLint engine, + egl::Surface *drawSurface, + egl::Surface *readSurface) const override; + + egl::Error getDriverVersion(std::string *version) const override; + + // Synchronizes with the X server, if the display has been opened by ANGLE. + // Calling this is required at the end of every functions that does buffered + // X calls (not for glX calls) otherwise there might be race conditions + // between the application's display and ANGLE's one. + void syncXCommands() const; + + // Depending on the supported GLX extension, swap interval can be set + // globally or per drawable. This function will make sure the drawable's + // swap interval is the one required so that the subsequent swapBuffers + // acts as expected. + void setSwapInterval(glx::Drawable drawable, SwapControlData *data); + + bool isValidWindowVisualId(unsigned long visualId) const; + + private: + const FunctionsGL *getFunctionsGL() const override; + + egl::Error initializeContext(glx::FBConfig config, + const egl::AttributeMap &eglAttributes, + glx::Context *context); + + void generateExtensions(egl::DisplayExtensions *outExtensions) const override; + void generateCaps(egl::Caps *outCaps) const override; + + int getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const; + egl::Error createContextAttribs(glx::FBConfig, + const Optional<gl::Version> &version, + int profileMask, + glx::Context *context) const; + + egl::Error getNVIDIADriverVersion(std::string *version) const; + + FunctionsGL *mFunctionsGL; + + std::map<int, glx::FBConfig> configIdToGLXConfig; + + EGLint mRequestedVisual; + glx::FBConfig mContextConfig; + glx::Context mContext; + // A pbuffer the context is current on during ANGLE initialization + glx::Pbuffer mDummyPbuffer; + + bool mUsesNewXDisplay; + bool mIsMesa; + bool mHasMultisample; + bool mHasARBCreateContext; + bool mHasARBCreateContextProfile; + bool mHasARBCreateContextRobustness; + bool mHasEXTCreateContextES2Profile; + + enum class SwapControl + { + Absent, + EXT, + Mesa, + SGI, + }; + SwapControl mSwapControl; + int mMinSwapInterval; + int mMaxSwapInterval; + int mCurrentSwapInterval; + + FunctionsGLX mGLX; + Display *mXDisplay; + egl::Display *mEGLDisplay; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_GLX_DISPLAYGLX_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md b/gfx/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md new file mode 100755 index 000000000..2343ad086 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md @@ -0,0 +1,204 @@ +GLX Framebuffer Compatibility investigation +=========================================== + +In GLX and EGL, contexts are created with respect to a config that +describes the type of surfaces they will be used to render to. +Likewise surfaces are created with respect to a config and for +a context to be able to render to a surface, both their configs +must be compatible. Compatibility is losely described in both +the GLX and EGL specs but the following is clear: + * In GLX the config's color buffer must have the same type, including +RGBA vs. ColorIndex and the buffers must have the same depth, if they +exist. + * In EGL the config's color buffer must have the same type and the +buffers must have the same depth (not clear if it is only if they exist) + +Obviously the EGLconfig we will expose will have a one-to-one +correspondance with GLXFBConfigs. + +Our EGL implementation uses a single OpenGL context to back all +the EGLcontexts created by the application. Since our GL context +and GLXContext are the same object but in two APIs, we will make +the confusion and call the GLX context our backing context. + +The problem we have is that the the GLX context is created before +the application can choose what type of context it wants to use, +that means we have to expose EGLconfigs whose respective GLXFBConfigs +are compatible with the GLXFBConfig of our GLX context; we also need +to choose the GLXFBConfig of our GLX context so that it matches the +most common needs of application. + +Choice of the GLX context GLXFBConfig +------------------------------------- + +We decided that our GLX context's configuration must satisfy the following: + * Have a RGBA8 color buffer and D24S8 depth-stencil buffer which is what +the vast majority of applications use. + * It must render in direct colors, i.e. not in a color indexed format. + * It must be double-buffered (see later) + * It must support rendering to all the types of GLX surfaces so that we can +use it for all types of EGL surfaces + * It must have an associated visual ID so that we can use it with X, it seems +like this would be strongly tied to it having the ```WINDOW_BIT``` set. + * We would like a conformant context. + +Study of compatible GLXFBConfigs +-------------------------------- + +When using the condition of compatibility defined in the GLX spec and filtering +out the non-conformant GLXFBConfig we got the following list (see function +```print_visual_attribs_short``` in [glxinfo's source code](http://cgit.freedesktop.org/mesa/demos/tree/src/xdemos/glxinfo.c) +to understand how to read the table): + +``` + visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav + id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat Result +---------------------------------------------------------------------------- +0x02e 24 tc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail +0x0e4 32 tc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None BadMatch +0x02c 24 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass +0x0e2 32 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None BadMatch +0x089 24 dc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail +0x087 24 dc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass +0x026 24 tc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail +0x0dc 32 tc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None BadMatch +0x024 24 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass +0x0da 32 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None BadMatch +0x081 24 dc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail +0x07f 24 dc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass +``` + +The last column shows the result of trying to render on a window using the config, +with a GLX context using config 0x024. The first thing we see is that BadMatch is +thrown by the X server when creating the subwindow for rendering. This was because +we didn't set the border pixel of the subwindow *shake fist at X11* (see this [StackOverflow question](http://stackoverflow.com/questions/3645632/how-to-create-a-window-with-a-bit-depth-of-32)). +The result updated with this fix give: + +``` + visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav + id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat +---------------------------------------------------------------------------- +0x02e 24 tc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail +0x0e4 32 tc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail +0x02c 24 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass +0x0e2 32 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass +0x089 24 dc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail +0x087 24 dc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass +0x026 24 tc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail +0x0dc 32 tc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail +0x024 24 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass +0x0da 32 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass +0x081 24 dc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail +0x07f 24 dc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass +``` + +From this we see that our rendering test passed if and only if the config was double +buffered like 0x024 which is our GLX context config. The compatible configs are then: + +``` + visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav + id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat +---------------------------------------------------------------------------- +0x02c 24 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None +0x0e2 32 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None +0x087 24 dc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None +0x024 24 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None +0x0da 32 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None +0x07f 24 dc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None +``` + +We can see two dimensions, with our without a depth-stencil buffer and with TrueColor +or DirectColor. The depth-stencil will be useful to expose to application. + +More on double buffering +------------------------ +The tests above show that double-buffered contexts are not compatible with single- +buffered surfaces; however other tests show that single-buffered contexts are +compatible with both single and double-buffered surfaces. The problem is that in +that case, we can see some flickering even with double-buffered surfaces. If we +can find a trick to avoid that flicker, then we would be able to expose single +and double-buffered surfaces at the EGL level. Not exposing them isn't too much +of a problem though as the vast majority of application want double-buffering. + +AMD and extra buffers +--------------------- +As can be seen above, NVIDIA does not expose conformant context with multisampled +buffers or non RGBA16 accumulation buffers. The behavior is different on AMD that +exposes them as conformant, which gives the following list after filtering as +explained above: + +``` + visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav + id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat +---------------------------------------------------------------------------- +0x023 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 16 16 16 16 0 0 None +0x027 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +0x02b 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 2 1 None +0x02f 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 4 1 None +0x03b 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 16 16 16 16 0 0 None +0x03f 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +0x043 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 2 1 None +0x047 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 4 1 None +``` + +ANGLE's context is created using 0x027 and experimentation shows it is only compatible +with 0x03f which is the only other config lacking both an accumulation buffer and a +multisample buffer. The GLX spec seems to hint it should still work ("should have the +same size, if they exist") but it doesn't work in this case. Filtering the configs to +have the same multisample and accumulation buffers gives the following: + +``` + visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav + id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat +---------------------------------------------------------------------------- +0x027 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +0x03f 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +``` + +Mesa Intel driver +----------------- +In GLX, a criterium for context and surface compatibility is that buffers +should have the same depth, if they exist at all in the surface. This means +that it should be possible to make a context with a D24S8 depth-stencil +buffer to a surface without a depth-stencil buffer. This doesn't work on the +Mesa Intel driver. The list before the workaround was the following, with +0x020 being the fbconfig chosen for the context: + +``` + visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav + id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat +---------------------------------------------------------------------------- +0x020 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +0x021 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +0x08f 32 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +0x0d0 24 tc 0 32 0 r y . 8 8 8 8 . . 0 0 0 0 0 0 0 0 0 None +0x0e2 24 dc 0 32 0 r y . 8 8 8 8 . . 0 0 0 0 0 0 0 0 0 None +0x0e9 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +``` + +After the workaround that list becomes the following: + +``` + visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav + id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat +---------------------------------------------------------------------------- +0x020 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +0x021 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +0x08f 32 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +0x0e9 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None +``` + +Future investigation +-------------------- +All the non-conformant configs have a multisampled buffer, so it could be interesting +to see if we can use them to expose another EGL extension. + +Finally this document is written with respect to a small number of drivers, before +using the GLX EGL implementation in the wild it would be good to test it on other +drivers and hardware. + +The drivers tested were: + + - the proprietary NVIDIA driver + - the proprietary AMD driver + - the open source Intel (Broadwell) Mesa driver diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp b/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp new file mode 100755 index 000000000..4ec38dd81 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp @@ -0,0 +1,398 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FunctionsGLX.cpp: Implements the FunctionsGLX class. + +#define ANGLE_SKIP_GLX_DEFINES 1 +#include "libANGLE/renderer/gl/glx/FunctionsGLX.h" +#undef ANGLE_SKIP_GLX_DEFINES + +// We can only include glx.h in files which do not include ANGLE's GLES +// headers, to avoid doubly-defined GLenum macros, typedefs, etc. +#include <GL/glx.h> + +#include <dlfcn.h> +#include <algorithm> + +#include "common/string_utils.h" +#include "libANGLE/renderer/gl/glx/functionsglx_typedefs.h" + +namespace rx +{ + +void* FunctionsGLX::sLibHandle = nullptr; + +template<typename T> +static bool GetProc(PFNGETPROCPROC getProc, T *member, const char *name) +{ + *member = reinterpret_cast<T>(getProc(name)); + return *member != nullptr; +} + +struct FunctionsGLX::GLXFunctionTable +{ + GLXFunctionTable() + : createContextPtr(nullptr), + destroyContextPtr(nullptr), + makeCurrentPtr(nullptr), + swapBuffersPtr(nullptr), + queryExtensionPtr(nullptr), + queryVersionPtr(nullptr), + getCurrentContextPtr(nullptr), + getCurrentDrawablePtr(nullptr), + waitXPtr(nullptr), + waitGLPtr(nullptr), + getClientStringPtr(nullptr), + queryExtensionsStringPtr(nullptr), + getFBConfigsPtr(nullptr), + chooseFBConfigPtr(nullptr), + getFBConfigAttribPtr(nullptr), + getVisualFromFBConfigPtr(nullptr), + createWindowPtr(nullptr), + destroyWindowPtr(nullptr), + createPbufferPtr(nullptr), + destroyPbufferPtr(nullptr), + queryDrawablePtr(nullptr), + createContextAttribsARBPtr(nullptr), + swapIntervalEXTPtr(nullptr), + swapIntervalMESAPtr(nullptr), + swapIntervalSGIPtr(nullptr) + { + } + + // GLX 1.0 + PFNGLXCREATECONTEXTPROC createContextPtr; + PFNGLXDESTROYCONTEXTPROC destroyContextPtr; + PFNGLXMAKECURRENTPROC makeCurrentPtr; + PFNGLXSWAPBUFFERSPROC swapBuffersPtr; + PFNGLXQUERYEXTENSIONPROC queryExtensionPtr; + PFNGLXQUERYVERSIONPROC queryVersionPtr; + PFNGLXGETCURRENTCONTEXTPROC getCurrentContextPtr; + PFNGLXGETCURRENTDRAWABLEPROC getCurrentDrawablePtr; + PFNGLXWAITXPROC waitXPtr; + PFNGLXWAITGLPROC waitGLPtr; + + // GLX 1.1 + PFNGLXGETCLIENTSTRINGPROC getClientStringPtr; + PFNGLXQUERYEXTENSIONSSTRINGPROC queryExtensionsStringPtr; + + //GLX 1.3 + PFNGLXGETFBCONFIGSPROC getFBConfigsPtr; + PFNGLXCHOOSEFBCONFIGPROC chooseFBConfigPtr; + PFNGLXGETFBCONFIGATTRIBPROC getFBConfigAttribPtr; + PFNGLXGETVISUALFROMFBCONFIGPROC getVisualFromFBConfigPtr; + PFNGLXCREATEWINDOWPROC createWindowPtr; + PFNGLXDESTROYWINDOWPROC destroyWindowPtr; + PFNGLXCREATEPBUFFERPROC createPbufferPtr; + PFNGLXDESTROYPBUFFERPROC destroyPbufferPtr; + PFNGLXQUERYDRAWABLEPROC queryDrawablePtr; + + // GLX_ARB_create_context + PFNGLXCREATECONTEXTATTRIBSARBPROC createContextAttribsARBPtr; + + // GLX_EXT_swap_control + PFNGLXSWAPINTERVALEXTPROC swapIntervalEXTPtr; + + // GLX_MESA_swap_control + PFNGLXSWAPINTERVALMESAPROC swapIntervalMESAPtr; + + // GLX_SGI_swap_control + PFNGLXSWAPINTERVALSGIPROC swapIntervalSGIPtr; +}; + +FunctionsGLX::FunctionsGLX() + : majorVersion(0), + minorVersion(0), + mXDisplay(nullptr), + mXScreen(-1), + mFnPtrs(new GLXFunctionTable()) +{ +} + +FunctionsGLX::~FunctionsGLX() +{ + delete mFnPtrs; + terminate(); +} + +bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorString) +{ + terminate(); + mXDisplay = xDisplay; + mXScreen = screen; + +#if !defined(ANGLE_LINK_GLX) + // Some OpenGL implementations can't handle having this library + // handle closed while there's any X window still open against + // which a GLXWindow was ever created. + if (!sLibHandle) + { + sLibHandle = dlopen("libGL.so.1", RTLD_NOW); + if (!sLibHandle) + { + *errorString = std::string("Could not dlopen libGL.so.1: ") + dlerror(); + return false; + } + } + + getProc = reinterpret_cast<PFNGETPROCPROC>(dlsym(sLibHandle, "glXGetProcAddress")); + if (!getProc) + { + getProc = reinterpret_cast<PFNGETPROCPROC>(dlsym(sLibHandle, "glXGetProcAddressARB")); + } + if (!getProc) + { + *errorString = "Could not retrieve glXGetProcAddress"; + return false; + } +#else + getProc = reinterpret_cast<PFNGETPROCPROC>(glXGetProcAddress); +#endif + +#define GET_PROC_OR_ERROR(MEMBER, NAME) \ + if (!GetProc(getProc, MEMBER, #NAME)) \ + { \ + *errorString = "Could not load GLX entry point " #NAME; \ + return false; \ + } +#if !defined(ANGLE_LINK_GLX) +#define GET_FNPTR_OR_ERROR(MEMBER, NAME) GET_PROC_OR_ERROR(MEMBER, NAME) +#else +#define GET_FNPTR_OR_ERROR(MEMBER, NAME) *MEMBER = NAME; +#endif + + // GLX 1.0 + GET_FNPTR_OR_ERROR(&mFnPtrs->createContextPtr, glXCreateContext); + GET_FNPTR_OR_ERROR(&mFnPtrs->destroyContextPtr, glXDestroyContext); + GET_FNPTR_OR_ERROR(&mFnPtrs->makeCurrentPtr, glXMakeCurrent); + GET_FNPTR_OR_ERROR(&mFnPtrs->swapBuffersPtr, glXSwapBuffers); + GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionPtr, glXQueryExtension); + GET_FNPTR_OR_ERROR(&mFnPtrs->queryVersionPtr, glXQueryVersion); + GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentContextPtr, glXGetCurrentContext); + GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentDrawablePtr, glXGetCurrentDrawable); + GET_FNPTR_OR_ERROR(&mFnPtrs->waitXPtr, glXWaitX); + GET_FNPTR_OR_ERROR(&mFnPtrs->waitGLPtr, glXWaitGL); + + // GLX 1.1 + GET_FNPTR_OR_ERROR(&mFnPtrs->getClientStringPtr, glXGetClientString); + GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionsStringPtr, glXQueryExtensionsString); + + // Check we have a working GLX + { + int errorBase; + int eventBase; + if (!queryExtension(&errorBase, &eventBase)) + { + *errorString = "GLX is not present."; + return false; + } + } + + // Check we have a supported version of GLX + if (!queryVersion(&majorVersion, &minorVersion)) + { + *errorString = "Could not query the GLX version."; + return false; + } + if (majorVersion != 1 || minorVersion < 3) + { + *errorString = "Unsupported GLX version (requires at least 1.3)."; + return false; + } + + const char *extensions = queryExtensionsString(); + if (!extensions) + { + *errorString = "glXQueryExtensionsString returned NULL"; + return false; + } + angle::SplitStringAlongWhitespace(extensions, &mExtensions); + + // GLX 1.3 + GET_FNPTR_OR_ERROR(&mFnPtrs->getFBConfigsPtr, glXGetFBConfigs); + GET_FNPTR_OR_ERROR(&mFnPtrs->chooseFBConfigPtr, glXChooseFBConfig); + GET_FNPTR_OR_ERROR(&mFnPtrs->getFBConfigAttribPtr, glXGetFBConfigAttrib); + GET_FNPTR_OR_ERROR(&mFnPtrs->getVisualFromFBConfigPtr, glXGetVisualFromFBConfig); + GET_FNPTR_OR_ERROR(&mFnPtrs->createWindowPtr, glXCreateWindow); + GET_FNPTR_OR_ERROR(&mFnPtrs->destroyWindowPtr, glXDestroyWindow); + GET_FNPTR_OR_ERROR(&mFnPtrs->createPbufferPtr, glXCreatePbuffer); + GET_FNPTR_OR_ERROR(&mFnPtrs->destroyPbufferPtr, glXDestroyPbuffer); + GET_FNPTR_OR_ERROR(&mFnPtrs->queryDrawablePtr, glXQueryDrawable); + + // Extensions + if (hasExtension("GLX_ARB_create_context")) + { + GET_PROC_OR_ERROR(&mFnPtrs->createContextAttribsARBPtr, glXCreateContextAttribsARB); + } + if (hasExtension("GLX_EXT_swap_control")) + { + GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalEXTPtr, glXSwapIntervalEXT); + } + if (hasExtension("GLX_MESA_swap_control")) + { + GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalMESAPtr, glXSwapIntervalMESA); + } + if (hasExtension("GLX_SGI_swap_control")) + { + GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalSGIPtr, glXSwapIntervalSGI); + } + +#undef GET_FNPTR_OR_ERROR +#undef GET_PROC_OR_ERROR + + *errorString = ""; + return true; +} + +void FunctionsGLX::terminate() +{ +} + +bool FunctionsGLX::hasExtension(const char *extension) const +{ + return std::find(mExtensions.begin(), mExtensions.end(), extension) != mExtensions.end(); +} + +Display *FunctionsGLX::getDisplay() const +{ + return mXDisplay; +} + +int FunctionsGLX::getScreen() const +{ + return mXScreen; +} + +// GLX functions + +// GLX 1.0 +glx::Context FunctionsGLX::createContext(XVisualInfo *visual, glx::Context share, bool direct) const +{ + GLXContext shareCtx = reinterpret_cast<GLXContext>(share); + GLXContext context = mFnPtrs->createContextPtr(mXDisplay, visual, shareCtx, direct); + return reinterpret_cast<glx::Context>(context); +} +void FunctionsGLX::destroyContext(glx::Context context) const +{ + GLXContext ctx = reinterpret_cast<GLXContext>(context); + mFnPtrs->destroyContextPtr(mXDisplay, ctx); +} +Bool FunctionsGLX::makeCurrent(glx::Drawable drawable, glx::Context context) const +{ + GLXContext ctx = reinterpret_cast<GLXContext>(context); + return mFnPtrs->makeCurrentPtr(mXDisplay, drawable, ctx); +} +void FunctionsGLX::swapBuffers(glx::Drawable drawable) const +{ + mFnPtrs->swapBuffersPtr(mXDisplay, drawable); +} +Bool FunctionsGLX::queryExtension(int *errorBase, int *event) const +{ + return mFnPtrs->queryExtensionPtr(mXDisplay, errorBase, event); +} +Bool FunctionsGLX::queryVersion(int *major, int *minor) const +{ + return mFnPtrs->queryVersionPtr(mXDisplay, major, minor); +} +glx::Context FunctionsGLX::getCurrentContext() const +{ + GLXContext context = mFnPtrs->getCurrentContextPtr(); + return reinterpret_cast<glx::Context>(context); +} +glx::Drawable FunctionsGLX::getCurrentDrawable() const +{ + GLXDrawable drawable = mFnPtrs->getCurrentDrawablePtr(); + return reinterpret_cast<glx::Drawable>(drawable); +} +void FunctionsGLX::waitX() const +{ + mFnPtrs->waitXPtr(); +} +void FunctionsGLX::waitGL() const +{ + mFnPtrs->waitGLPtr(); +} + +// GLX 1.1 +const char *FunctionsGLX::getClientString(int name) const +{ + return mFnPtrs->getClientStringPtr(mXDisplay, name); +} + +const char *FunctionsGLX::queryExtensionsString() const +{ + return mFnPtrs->queryExtensionsStringPtr(mXDisplay, mXScreen); +} + +// GLX 1.4 +glx::FBConfig *FunctionsGLX::getFBConfigs(int *nElements) const +{ + GLXFBConfig *configs = mFnPtrs->getFBConfigsPtr(mXDisplay, mXScreen, nElements); + return reinterpret_cast<glx::FBConfig*>(configs); +} +glx::FBConfig *FunctionsGLX::chooseFBConfig(const int *attribList, int *nElements) const +{ + GLXFBConfig *configs = mFnPtrs->chooseFBConfigPtr(mXDisplay, mXScreen, attribList, nElements); + return reinterpret_cast<glx::FBConfig*>(configs); +} +int FunctionsGLX::getFBConfigAttrib(glx::FBConfig config, int attribute, int *value) const +{ + GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config); + return mFnPtrs->getFBConfigAttribPtr(mXDisplay, cfg, attribute, value); +} +XVisualInfo *FunctionsGLX::getVisualFromFBConfig(glx::FBConfig config) const +{ + GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config); + return mFnPtrs->getVisualFromFBConfigPtr(mXDisplay, cfg); +} +GLXWindow FunctionsGLX::createWindow(glx::FBConfig config, Window window, const int *attribList) const +{ + GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config); + return mFnPtrs->createWindowPtr(mXDisplay, cfg, window, attribList); +} +void FunctionsGLX::destroyWindow(glx::Window window) const +{ + mFnPtrs->destroyWindowPtr(mXDisplay, window); +} +glx::Pbuffer FunctionsGLX::createPbuffer(glx::FBConfig config, const int *attribList) const +{ + GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config); + return mFnPtrs->createPbufferPtr(mXDisplay, cfg, attribList); +} +void FunctionsGLX::destroyPbuffer(glx::Pbuffer pbuffer) const +{ + mFnPtrs->destroyPbufferPtr(mXDisplay, pbuffer); +} +void FunctionsGLX::queryDrawable(glx::Drawable drawable, int attribute, unsigned int *value) const +{ + mFnPtrs->queryDrawablePtr(mXDisplay, drawable, attribute, value); +} + +// GLX_ARB_create_context +glx::Context FunctionsGLX::createContextAttribsARB(glx::FBConfig config, glx::Context shareContext, Bool direct, const int *attribList) const +{ + GLXContext shareCtx = reinterpret_cast<GLXContext>(shareContext); + GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config); + GLXContext ctx = mFnPtrs->createContextAttribsARBPtr(mXDisplay, cfg, shareCtx, direct, attribList); + return reinterpret_cast<glx::Context>(ctx); +} + +void FunctionsGLX::swapIntervalEXT(glx::Drawable drawable, int intervals) const +{ + mFnPtrs->swapIntervalEXTPtr(mXDisplay, drawable, intervals); +} + +int FunctionsGLX::swapIntervalMESA(int intervals) const +{ + return mFnPtrs->swapIntervalMESAPtr(intervals); +} + +int FunctionsGLX::swapIntervalSGI(int intervals) const +{ + return mFnPtrs->swapIntervalSGIPtr(intervals); +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h b/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h new file mode 100755 index 000000000..98c2fef46 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h @@ -0,0 +1,96 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FunctionsGLX.h: Defines the FunctionsGLX class to load functions and data from GLX + +#ifndef LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLX_H_ +#define LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLX_H_ + +#include <string> +#include <vector> + +#include "libANGLE/renderer/gl/glx/platform_glx.h" + +namespace rx +{ + +class FunctionsGLX +{ + public: + FunctionsGLX(); + ~FunctionsGLX(); + + // Load data from GLX, can be called multiple times + bool initialize(Display *xDisplay, int screen, std::string *errorString); + void terminate(); + + bool hasExtension(const char *extension) const; + int majorVersion; + int minorVersion; + + Display *getDisplay() const; + int getScreen() const; + + PFNGETPROCPROC getProc; + + // GLX 1.0 + glx::Context createContext(XVisualInfo *visual, glx::Context share, bool direct) const; + void destroyContext(glx::Context context) const; + Bool makeCurrent(glx::Drawable drawable, glx::Context context) const; + void swapBuffers(glx::Drawable drawable) const; + Bool queryExtension(int *errorBase, int *event) const; + Bool queryVersion(int *major, int *minor) const; + glx::Context getCurrentContext() const; + glx::Drawable getCurrentDrawable() const; + void waitX() const; + void waitGL() const; + + // GLX 1.1 + const char *getClientString(int name) const; + const char *queryExtensionsString() const; + + // GLX 1.3 + glx::FBConfig *getFBConfigs(int *nElements) const; + glx::FBConfig *chooseFBConfig(const int *attribList, int *nElements) const; + int getFBConfigAttrib(glx::FBConfig config, int attribute, int *value) const; + XVisualInfo *getVisualFromFBConfig(glx::FBConfig config) const; + glx::Window createWindow(glx::FBConfig config, Window window, const int *attribList) const; + void destroyWindow(glx::Window window) const; + glx::Pbuffer createPbuffer(glx::FBConfig config, const int *attribList) const; + void destroyPbuffer(glx::Pbuffer pbuffer) const; + void queryDrawable(glx::Drawable drawable, int attribute, unsigned int *value) const; + + // GLX_ARB_create_context + glx::Context createContextAttribsARB(glx::FBConfig config, glx::Context shareContext, Bool direct, const int *attribList) const; + + // GLX_EXT_swap_control + void swapIntervalEXT(glx::Drawable drawable, int interval) const; + + // GLX_MESA_swap_control + int swapIntervalMESA(int interval) const; + + // GLX_SGI_swap_control + int swapIntervalSGI(int interval) const; + + private: + // So as to isolate GLX from angle we do not include angleutils.h and cannot + // use angle::NonCopyable so we replicated it here instead. + FunctionsGLX(const FunctionsGLX&) = delete; + void operator=(const FunctionsGLX&) = delete; + + struct GLXFunctionTable; + + static void *sLibHandle; + Display *mXDisplay; + int mXScreen; + + GLXFunctionTable *mFnPtrs; + std::vector<std::string> mExtensions; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLX_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp b/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp new file mode 100755 index 000000000..a97021b40 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp @@ -0,0 +1,143 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// PbufferSurfaceGLX.cpp: GLX implementation of egl::Surface for PBuffers + +#include "libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h" + +#include "common/debug.h" +#include "libANGLE/renderer/gl/glx/DisplayGLX.h" +#include "libANGLE/renderer/gl/glx/FunctionsGLX.h" + +namespace rx +{ + +PbufferSurfaceGLX::PbufferSurfaceGLX(const egl::SurfaceState &state, + RendererGL *renderer, + EGLint width, + EGLint height, + bool largest, + const FunctionsGLX &glx, + glx::Context context, + glx::FBConfig fbConfig) + : SurfaceGLX(state, renderer), + mWidth(width), + mHeight(height), + mLargest(largest), + mGLX(glx), + mContext(context), + mFBConfig(fbConfig), + mPbuffer(0) +{ +} + +PbufferSurfaceGLX::~PbufferSurfaceGLX() +{ + if (mPbuffer) + { + mGLX.destroyPbuffer(mPbuffer); + } +} + +egl::Error PbufferSurfaceGLX::initialize() +{ + // Avoid creating 0-sized PBuffers as it fails on the Intel Mesa driver + // as commented on https://bugs.freedesktop.org/show_bug.cgi?id=38869 so we + // use (w, 1) or (1, h) instead. + int width = std::max(1, static_cast<int>(mWidth)); + int height = std::max(1, static_cast<int>(mHeight)); + + const int attribs[] = + { + GLX_PBUFFER_WIDTH, width, + GLX_PBUFFER_HEIGHT, height, + GLX_LARGEST_PBUFFER, mLargest, + None + }; + + mPbuffer = mGLX.createPbuffer(mFBConfig, attribs); + if (!mPbuffer) + { + return egl::Error(EGL_BAD_ALLOC, "Failed to create a native GLX pbuffer."); + } + + if (mLargest) + { + mGLX.queryDrawable(mPbuffer, GLX_WIDTH, &mWidth); + mGLX.queryDrawable(mPbuffer, GLX_HEIGHT, &mHeight); + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceGLX::makeCurrent() +{ + if (mGLX.makeCurrent(mPbuffer, mContext) != True) + { + return egl::Error(EGL_BAD_DISPLAY); + } + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceGLX::swap() +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceGLX::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceGLX::querySurfacePointerANGLE(EGLint attribute, void **value) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceGLX::bindTexImage(gl::Texture *texture, EGLint buffer) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceGLX::releaseTexImage(EGLint buffer) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +void PbufferSurfaceGLX::setSwapInterval(EGLint interval) +{ +} + +EGLint PbufferSurfaceGLX::getWidth() const +{ + return mWidth; +} + +EGLint PbufferSurfaceGLX::getHeight() const +{ + return mHeight; +} + +EGLint PbufferSurfaceGLX::isPostSubBufferSupported() const +{ + UNIMPLEMENTED(); + return EGL_FALSE; +} + +EGLint PbufferSurfaceGLX::getSwapBehavior() const +{ + return EGL_BUFFER_PRESERVED; +} + +egl::Error PbufferSurfaceGLX::checkForResize() +{ + // The size of pbuffers never change + return egl::Error(EGL_SUCCESS); +} +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h b/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h new file mode 100755 index 000000000..d346634b2 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h @@ -0,0 +1,64 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// PBufferSurfaceGLX.h: GLX implementation of egl::Surface for PBuffers + +#ifndef LIBANGLE_RENDERER_GL_GLX_PBUFFERSURFACEGLX_H_ +#define LIBANGLE_RENDERER_GL_GLX_PBUFFERSURFACEGLX_H_ + +#include "libANGLE/renderer/gl/glx/platform_glx.h" +#include "libANGLE/renderer/gl/glx/SurfaceGLX.h" + +namespace rx +{ + +class FunctionsGLX; + +class PbufferSurfaceGLX : public SurfaceGLX +{ + public: + PbufferSurfaceGLX(const egl::SurfaceState &state, + RendererGL *renderer, + EGLint width, + EGLint height, + bool largest, + const FunctionsGLX &glx, + glx::Context context, + glx::FBConfig fbConfig); + ~PbufferSurfaceGLX() override; + + egl::Error initialize() override; + egl::Error makeCurrent() override; + + egl::Error swap() override; + egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; + egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; + egl::Error releaseTexImage(EGLint buffer) override; + void setSwapInterval(EGLint interval) override; + + EGLint getWidth() const override; + EGLint getHeight() const override; + + EGLint isPostSubBufferSupported() const override; + EGLint getSwapBehavior() const override; + + egl::Error checkForResize() override; + + private: + unsigned mWidth; + unsigned mHeight; + bool mLargest; + + const FunctionsGLX &mGLX; + glx::Context mContext; + glx::FBConfig mFBConfig; + glx::Pbuffer mPbuffer; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_GLX_PBUFFERSURFACEGLX_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/SurfaceGLX.h b/gfx/angle/src/libANGLE/renderer/gl/glx/SurfaceGLX.h new file mode 100755 index 000000000..813516e80 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/glx/SurfaceGLX.h @@ -0,0 +1,26 @@ +// +// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SurfaceGLX.h: common interface for GLX surfaces + +#ifndef LIBANGLE_RENDERER_GL_GLX_SURFACEGLX_H_ +#define LIBANGLE_RENDERER_GL_GLX_SURFACEGLX_H_ + +#include "libANGLE/renderer/gl/SurfaceGL.h" + +namespace rx +{ + +class SurfaceGLX : public SurfaceGL +{ + public: + SurfaceGLX(const egl::SurfaceState &state, RendererGL *renderer) : SurfaceGL(state, renderer) {} + + virtual egl::Error checkForResize() = 0; +}; +} + +#endif // LIBANGLE_RENDERER_GL_GLX_SURFACEGLX_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp b/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp new file mode 100755 index 000000000..21b1b316f --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp @@ -0,0 +1,244 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// WindowSurfaceGLX.cpp: GLX implementation of egl::Surface for windows + +#include "libANGLE/renderer/gl/glx/WindowSurfaceGLX.h" + +#include "common/debug.h" + +#include "libANGLE/renderer/gl/glx/DisplayGLX.h" +#include "libANGLE/renderer/gl/glx/FunctionsGLX.h" + +namespace rx +{ + +static int IgnoreX11Errors(Display *, XErrorEvent *) +{ + return 0; +} + +WindowSurfaceGLX::WindowSurfaceGLX(const egl::SurfaceState &state, + const FunctionsGLX &glx, + DisplayGLX *glxDisplay, + RendererGL *renderer, + Window window, + Display *display, + glx::Context context, + glx::FBConfig fbConfig) + : SurfaceGLX(state, renderer), + mParent(window), + mWindow(0), + mDisplay(display), + mGLX(glx), + mGLXDisplay(glxDisplay), + mContext(context), + mFBConfig(fbConfig), + mGLXWindow(0) +{ +} + +WindowSurfaceGLX::~WindowSurfaceGLX() +{ + if (mGLXWindow) + { + mGLX.destroyWindow(mGLXWindow); + } + + if (mWindow) + { + // When destroying the window, it may happen that the window has already been + // destroyed by the application (this happens in Chromium). There is no way to + // atomically check that a window exists and to destroy it so instead we call + // XDestroyWindow, ignoring any errors. + auto oldErrorHandler = XSetErrorHandler(IgnoreX11Errors); + XDestroyWindow(mDisplay, mWindow); + XSync(mDisplay, False); + XSetErrorHandler(oldErrorHandler); + } + + mGLXDisplay->syncXCommands(); +} + +egl::Error WindowSurfaceGLX::initialize() +{ + // Check that the window's visual ID is valid, as part of the AMGLE_x11_visual + // extension. + { + XWindowAttributes windowAttributes; + XGetWindowAttributes(mDisplay, mParent, &windowAttributes); + unsigned long visualId = windowAttributes.visual->visualid; + + if (!mGLXDisplay->isValidWindowVisualId(visualId)) + { + return egl::Error(EGL_BAD_MATCH, + "The visual of native_window doesn't match the visual given with " + "ANGLE_X11_VISUAL_ID"); + } + } + + // The visual of the X window, GLX window and GLX context must match, + // however we received a user-created window that can have any visual + // and wouldn't work with our GLX context. To work in all cases, we + // create a child window with the right visual that covers all of its + // parent. + XVisualInfo *visualInfo = mGLX.getVisualFromFBConfig(mFBConfig); + if (!visualInfo) + { + return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the XVisualInfo for the child window."); + } + Visual* visual = visualInfo->visual; + + if (!getWindowDimensions(mParent, &mParentWidth, &mParentHeight)) + { + return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the parent window's dimensions."); + } + + // The depth, colormap and visual must match otherwise we get a X error + // so we specify the colormap attribute. Also we do not want the window + // to be taken into account for input so we specify the event and + // do-not-propagate masks to 0 (the defaults). Finally we specify the + // border pixel attribute so that we can use a different visual depth + // than our parent (seems like X uses that as a condition to render + // the subwindow in a different buffer) + XSetWindowAttributes attributes; + unsigned long attributeMask = CWColormap | CWBorderPixel; + + Colormap colormap = XCreateColormap(mDisplay, mParent, visual, AllocNone); + if(!colormap) + { + XFree(visualInfo); + return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to create the Colormap for the child window."); + } + attributes.colormap = colormap; + attributes.border_pixel = 0; + + //TODO(cwallez) set up our own error handler to see if the call failed + mWindow = XCreateWindow(mDisplay, mParent, 0, 0, mParentWidth, mParentHeight, + 0, visualInfo->depth, InputOutput, visual, attributeMask, &attributes); + mGLXWindow = mGLX.createWindow(mFBConfig, mWindow, nullptr); + + XMapWindow(mDisplay, mWindow); + XFlush(mDisplay); + + XFree(visualInfo); + XFreeColormap(mDisplay, colormap); + + mGLXDisplay->syncXCommands(); + + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceGLX::makeCurrent() +{ + if (mGLX.makeCurrent(mGLXWindow, mContext) != True) + { + return egl::Error(EGL_BAD_DISPLAY); + } + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceGLX::swap() +{ + // We need to swap before resizing as some drivers clobber the back buffer + // when the window is resized. + mGLXDisplay->setSwapInterval(mGLXWindow, &mSwapControl); + mGLX.swapBuffers(mGLXWindow); + + egl::Error error = checkForResize(); + if (error.isError()) + { + return error; + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceGLX::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceGLX::querySurfacePointerANGLE(EGLint attribute, void **value) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceGLX::bindTexImage(gl::Texture *texture, EGLint buffer) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceGLX::releaseTexImage(EGLint buffer) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +void WindowSurfaceGLX::setSwapInterval(EGLint interval) +{ + mSwapControl.targetSwapInterval = interval; +} + +EGLint WindowSurfaceGLX::getWidth() const +{ + // The size of the window is always the same as the cached size of its parent. + return mParentWidth; +} + +EGLint WindowSurfaceGLX::getHeight() const +{ + // The size of the window is always the same as the cached size of its parent. + return mParentHeight; +} + +EGLint WindowSurfaceGLX::isPostSubBufferSupported() const +{ + UNIMPLEMENTED(); + return EGL_FALSE; +} + +EGLint WindowSurfaceGLX::getSwapBehavior() const +{ + return EGL_BUFFER_PRESERVED; +} + +egl::Error WindowSurfaceGLX::checkForResize() +{ + // TODO(cwallez) set up our own error handler to see if the call failed + unsigned int newParentWidth, newParentHeight; + if (!getWindowDimensions(mParent, &newParentWidth, &newParentHeight)) + { + return egl::Error(EGL_BAD_CURRENT_SURFACE, + "Failed to retrieve the size of the parent window."); + } + + if (mParentWidth != newParentWidth || mParentHeight != newParentHeight) + { + mParentWidth = newParentWidth; + mParentHeight = newParentHeight; + + mGLX.waitGL(); + XResizeWindow(mDisplay, mWindow, mParentWidth, mParentHeight); + mGLX.waitX(); + XSync(mDisplay, False); + } + + return egl::Error(EGL_SUCCESS); +} + +bool WindowSurfaceGLX::getWindowDimensions(Window window, unsigned int *width, unsigned int *height) const +{ + Window root; + int x, y; + unsigned int border, depth; + return XGetGeometry(mDisplay, window, &root, &x, &y, width, height, &border, &depth) != 0; +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h b/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h new file mode 100755 index 000000000..0cdda96e6 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h @@ -0,0 +1,73 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// WindowSurfaceGLX.h: GLX implementation of egl::Surface for windows + +#ifndef LIBANGLE_RENDERER_GL_GLX_WINDOWSURFACEGLX_H_ +#define LIBANGLE_RENDERER_GL_GLX_WINDOWSURFACEGLX_H_ + +#include "libANGLE/renderer/gl/glx/DisplayGLX.h" +#include "libANGLE/renderer/gl/glx/platform_glx.h" +#include "libANGLE/renderer/gl/glx/SurfaceGLX.h" + +namespace rx +{ + +class DisplayGLX; +class FunctionsGLX; + +class WindowSurfaceGLX : public SurfaceGLX +{ + public: + WindowSurfaceGLX(const egl::SurfaceState &state, + const FunctionsGLX &glx, + DisplayGLX *glxDisplay, + RendererGL *renderer, + Window window, + Display *display, + glx::Context context, + glx::FBConfig fbConfig); + ~WindowSurfaceGLX() override; + + egl::Error initialize() override; + egl::Error makeCurrent() override; + + egl::Error swap() override; + egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; + egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; + egl::Error releaseTexImage(EGLint buffer) override; + void setSwapInterval(EGLint interval) override; + + EGLint getWidth() const override; + EGLint getHeight() const override; + + EGLint isPostSubBufferSupported() const override; + EGLint getSwapBehavior() const override; + + egl::Error checkForResize() override; + + private: + bool getWindowDimensions(Window window, unsigned int *width, unsigned int *height) const; + + Window mParent; + unsigned int mParentWidth, mParentHeight; + Window mWindow; + Display *mDisplay; + + const FunctionsGLX &mGLX; + DisplayGLX *mGLXDisplay; + + glx::Context mContext; + glx::FBConfig mFBConfig; + glx::Window mGLXWindow; + + SwapControlData mSwapControl; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_GLX_WINDOWSURFACEGLX_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h b/gfx/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h new file mode 100755 index 000000000..b0ba033c7 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h @@ -0,0 +1,52 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// functionsglx_typedefs.h: Typedefs of GLX functions. + +#ifndef LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLXTYPEDEFS_H_ +#define LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLXTYPEDEFS_H_ + +#include "libANGLE/renderer/gl/glx/platform_glx.h" + +namespace rx +{ + +// Only the functions of GLX 1.2 and earlier need to be typdefed; the other +// functions are already typedefed in glx.h + +// GLX 1.0 +typedef XVisualInfo *(*PFNGLXCHOOSEVISUALPROC) (Display *dpy, int screen, int *attribList); +typedef GLXContext (*PFNGLXCREATECONTEXTPROC) (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct); +typedef void (*PFNGLXDESTROYCONTEXTPROC) (Display *dpy, GLXContext ctx); +typedef Bool (*PFNGLXMAKECURRENTPROC) (Display *dpy, GLXDrawable drawable, GLXContext ctx); +typedef void (*PFNGLXCOPYCONTEXTPROC) (Display *dpy, GLXContext src, GLXContext dst, unsigned long mask); +typedef void (*PFNGLXSWAPBUFFERSPROC) (Display *dpy, GLXDrawable drawable); +typedef GLXPixmap (*PFNGLXCREATEGLXPIXMAPPROC) (Display *dpy, XVisualInfo *visual, Pixmap pixmap); +typedef void (*PFNGLXDESTROYGLXPIXMAPPROC) (Display *dpy, GLXPixmap pixmap); +typedef Bool (*PFNGLXQUERYEXTENSIONPROC) (Display *dpy, int *errorb, int *event); +typedef Bool (*PFNGLXQUERYVERSIONPROC) (Display *dpy, int *maj, int *min); +typedef Bool (*PFNGLXISDIRECTPROC) (Display *dpy, GLXContext ctx); +typedef int (*PFNGLXGETCONFIGPROC) (Display *dpy, XVisualInfo *visual, int attrib, int *value); +typedef GLXContext (*PFNGLXGETCURRENTCONTEXTPROC) (); +typedef GLXDrawable (*PFNGLXGETCURRENTDRAWABLEPROC) (); +typedef GLXContext (*PFNGLXGETCURRENTCONTEXTPROC) (); +typedef GLXDrawable (*PFNGLXGETCURRENTDRAWABLEPROC) (); +typedef void (*PFNGLXWAITGLPROC) (); +typedef void (*PFNGLXWAITXPROC) (); +typedef void (*PFNGLXUSEXFONT) (Font font, int first, int count, int list); + +// GLX 1.1 +typedef const char *(*PFNGLXQUERYEXTENSIONSSTRINGPROC) (Display *dpy, int screen); +typedef const char *(*PFNGLXQUERYSERVERSTRINGPROC) (Display *dpy, int screen, int name); +typedef const char *(*PFNGLXGETCLIENTSTRINGPROC) (Display *dpy, int name); + + +// GLX 1.2 +typedef Display *(*PFNGLXGETCURRENTDISPLAYPROC) (); + +} + +#endif // LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLXTYPEDEFS_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/platform_glx.h b/gfx/angle/src/libANGLE/renderer/gl/glx/platform_glx.h new file mode 100755 index 000000000..3ffb609d5 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/glx/platform_glx.h @@ -0,0 +1,190 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// platform_glx.h: Includes specific to GLX. + +#ifndef LIBANGLE_RENDERER_GL_GLX_PLATFORMGLX_H_ +#define LIBANGLE_RENDERER_GL_GLX_PLATFORMGLX_H_ + +#if !defined(ANGLE_SKIP_GLX_DEFINES) +// GLX 1.0 +#define GLX_USE_GL 1 +#define GLX_BUFFER_SIZE 2 +#define GLX_LEVEL 3 +#define GLX_RGBA 4 +#define GLX_DOUBLEBUFFER 5 +#define GLX_STEREO 6 +#define GLX_AUX_BUFFERS 7 +#define GLX_RED_SIZE 8 +#define GLX_GREEN_SIZE 9 +#define GLX_BLUE_SIZE 10 +#define GLX_ALPHA_SIZE 11 +#define GLX_DEPTH_SIZE 12 +#define GLX_STENCIL_SIZE 13 +#define GLX_ACCUM_RED_SIZE 14 +#define GLX_ACCUM_GREEN_SIZE 15 +#define GLX_ACCUM_BLUE_SIZE 16 +#define GLX_ACCUM_ALPHA_SIZE 17 + +#define GLX_BAD_SCREEN 1 +#define GLX_BAD_ATTRIBUTE 2 +#define GLX_NO_EXTENSION 3 +#define GLX_BAD_VISUAL 4 +#define GLX_BAD_CONTEXT 5 +#define GLX_BAD_VALUE 6 +#define GLX_BAD_ENUM 7 + +// GLX 1.1 +#define GLX_VENDOR 1 +#define GLX_VERSION 2 +#define GLX_EXTENSIONS 3 + +// GLX 1.3 +#define GLX_CONFIG_CAVEAT 0x20 +#define GLX_DONT_CARE 0xFFFFFFFF +#define GLX_X_VISUAL_TYPE 0x22 +#define GLX_TRANSPARENT_TYPE 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE 0x24 +#define GLX_TRANSPARENT_RED_VALUE 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE 0x28 +#define GLX_WINDOW_BIT 0x00000001 +#define GLX_PIXMAP_BIT 0x00000002 +#define GLX_PBUFFER_BIT 0x00000004 +#define GLX_AUX_BUFFERS_BIT 0x00000010 +#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 +#define GLX_DEPTH_BUFFER_BIT 0x00000020 +#define GLX_STENCIL_BUFFER_BIT 0x00000040 +#define GLX_ACCUM_BUFFER_BIT 0x00000080 +#define GLX_NONE 0x8000 +#define GLX_SLOW_CONFIG 0x8001 +#define GLX_TRUE_COLOR 0x8002 +#define GLX_DIRECT_COLOR 0x8003 +#define GLX_PSEUDO_COLOR 0x8004 +#define GLX_STATIC_COLOR 0x8005 +#define GLX_GRAY_SCALE 0x8006 +#define GLX_STATIC_GRAY 0x8007 +#define GLX_TRANSPARENT_RGB 0x8008 +#define GLX_TRANSPARENT_INDEX 0x8009 +#define GLX_VISUAL_ID 0x800B +#define GLX_SCREEN 0x800C +#define GLX_NON_CONFORMANT_CONFIG 0x800D +#define GLX_DRAWABLE_TYPE 0x8010 +#define GLX_RENDER_TYPE 0x8011 +#define GLX_X_RENDERABLE 0x8012 +#define GLX_FBCONFIG_ID 0x8013 +#define GLX_RGBA_TYPE 0x8014 +#define GLX_COLOR_INDEX_TYPE 0x8015 +#define GLX_MAX_PBUFFER_WIDTH 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT 0x8017 +#define GLX_MAX_PBUFFER_PIXELS 0x8018 +#define GLX_PRESERVED_CONTENTS 0x801B +#define GLX_LARGEST_PBUFFER 0x801C +#define GLX_WIDTH 0x801D +#define GLX_HEIGHT 0x801E +#define GLX_EVENT_MASK 0x801F +#define GLX_DAMAGED 0x8020 +#define GLX_SAVED 0x8021 +#define GLX_WINDOW 0x8022 +#define GLX_PBUFFER 0x8023 +#define GLX_PBUFFER_HEIGHT 0x8040 +#define GLX_PBUFFER_WIDTH 0x8041 +#define GLX_RGBA_BIT 0x00000001 +#define GLX_COLOR_INDEX_BIT 0x00000002 +#define GLX_PBUFFER_CLOBBER_MASK 0x08000000 + +// GLX 1.4 +#define GLX_SAMPLE_BUFFERS 0x186a0 +#define GLX_SAMPLES 0x186a1 + +// GLX_ARB_create_context +#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001 +#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define GLX_CONTEXT_FLAGS_ARB 0x2094 + +// GLX_ARB_create_context_profile +#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 + +// GLX_ARB_create_context_robustness +#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261 + +// GLX_EXT_create_context_es2_profile +#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 + +// GLX_EXT_texture_from_pixmap +#define GLX_TEXTURE_1D_BIT_EXT 0x00000001 +#define GLX_TEXTURE_2D_BIT_EXT 0x00000002 +#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004 +#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0 +#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1 +#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2 +#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3 +#define GLX_Y_INVERTED_EXT 0x20D4 +#define GLX_TEXTURE_FORMAT_EXT 0x20D5 +#define GLX_TEXTURE_TARGET_EXT 0x20D6 +#define GLX_MIPMAP_TEXTURE_EXT 0x20D7 +#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8 +#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9 +#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA +#define GLX_TEXTURE_1D_EXT 0x20DB +#define GLX_TEXTURE_2D_EXT 0x20DC +#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD +#define GLX_FRONT_LEFT_EXT 0x20DE +#define GLX_FRONT_RIGHT_EXT 0x20DF +#define GLX_BACK_LEFT_EXT 0x20E0 +#define GLX_BACK_RIGHT_EXT 0x20E1 +#define GLX_FRONT_EXT 0x20DE +#define GLX_BACK_EXT 0x20E0 +#define GLX_AUX0_EXT 0x20E2 +#define GLX_AUX1_EXT 0x20E3 +#define GLX_AUX2_EXT 0x20E4 +#define GLX_AUX3_EXT 0x20E5 +#define GLX_AUX4_EXT 0x20E6 +#define GLX_AUX5_EXT 0x20E7 +#define GLX_AUX6_EXT 0x20E8 +#define GLX_AUX7_EXT 0x20E9 +#define GLX_AUX8_EXT 0x20EA +#define GLX_AUX9_EXT 0x20EB + +// GLX_EXT_swap_control +#define GLX_SWAP_INTERVAL_EXT 0x20F1 +#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2 +#endif // !defined(ANGLE_SKIP_GLX_DEFINES) + +// GLX typedefs depend on the X headers +#include <X11/Xlib.h> +#include <X11/Xresource.h> +#include <X11/Xutil.h> + +// GLX typedefs +namespace glx +{ + +typedef void *Context; +typedef void *FBConfig; +typedef XID FBConfigID; +typedef XID ContextID; +typedef XID Window; +typedef XID Pbuffer; +typedef XID Pixmap; +typedef XID Drawable; + +} + +typedef void* (*PFNGETPROCPROC) (const char *name); + +#endif // LIBANGLE_RENDERER_GL_GLX_PLATFORMGLX_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp b/gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp new file mode 100755 index 000000000..504a787f8 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp @@ -0,0 +1,1045 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// renderergl_utils.cpp: Conversion functions and other utility routines +// specific to the OpenGL renderer. + +#include "libANGLE/renderer/gl/renderergl_utils.h" + +#include <limits> + +#include "common/mathutil.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Caps.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/gl/FunctionsGL.h" +#include "libANGLE/renderer/gl/WorkaroundsGL.h" +#include "libANGLE/renderer/gl/formatutilsgl.h" + +#include <algorithm> +#include <sstream> + +using angle::CheckedNumeric; + +namespace rx +{ +VendorID GetVendorID(const FunctionsGL *functions) +{ + std::string nativeVendorString(reinterpret_cast<const char *>(functions->getString(GL_VENDOR))); + if (nativeVendorString.find("Intel") != std::string::npos) + { + return VENDOR_ID_INTEL; + } + else if (nativeVendorString.find("NVIDIA") != std::string::npos) + { + return VENDOR_ID_NVIDIA; + } + else if (nativeVendorString.find("ATI") != std::string::npos || + nativeVendorString.find("AMD") != std::string::npos) + { + return VENDOR_ID_AMD; + } + else if (nativeVendorString.find("Qualcomm") != std::string::npos) + { + return VENDOR_ID_QUALCOMM; + } + else + { + return VENDOR_ID_UNKNOWN; + } +} + +namespace nativegl_gl +{ + +static bool MeetsRequirements(const FunctionsGL *functions, const nativegl::SupportRequirement &requirements) +{ + for (const std::string &extension : requirements.requiredExtensions) + { + if (!functions->hasExtension(extension)) + { + return false; + } + } + + if (functions->version >= requirements.version) + { + return true; + } + else if (!requirements.versionExtensions.empty()) + { + for (const std::string &extension : requirements.versionExtensions) + { + if (!functions->hasExtension(extension)) + { + return false; + } + } + return true; + } + else + { + return false; + } +} + +static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions, GLenum internalFormat) +{ + gl::TextureCaps textureCaps; + + const nativegl::InternalFormat &formatInfo = nativegl::GetInternalFormatInfo(internalFormat, functions->standard); + textureCaps.texturable = MeetsRequirements(functions, formatInfo.texture); + textureCaps.filterable = textureCaps.texturable && MeetsRequirements(functions, formatInfo.filter); + textureCaps.renderable = MeetsRequirements(functions, formatInfo.framebufferAttachment); + + // glGetInternalformativ is not available until version 4.2 but may be available through the 3.0 + // extension GL_ARB_internalformat_query + if (textureCaps.renderable && functions->getInternalformativ) + { + GLint numSamples = 0; + functions->getInternalformativ(GL_RENDERBUFFER, internalFormat, GL_NUM_SAMPLE_COUNTS, 1, &numSamples); + + if (numSamples > 0) + { + std::vector<GLint> samples(numSamples); + functions->getInternalformativ(GL_RENDERBUFFER, internalFormat, GL_SAMPLES, + static_cast<GLsizei>(samples.size()), &samples[0]); + for (size_t sampleIndex = 0; sampleIndex < samples.size(); sampleIndex++) + { + textureCaps.sampleCounts.insert(samples[sampleIndex]); + } + } + } + + return textureCaps; +} + +static GLint QuerySingleGLInt(const FunctionsGL *functions, GLenum name) +{ + GLint result = 0; + functions->getIntegerv(name, &result); + return result; +} + +static GLint QuerySingleIndexGLInt(const FunctionsGL *functions, GLenum name, GLuint index) +{ + GLint result; + functions->getIntegeri_v(name, index, &result); + return result; +} + +static GLint QueryGLIntRange(const FunctionsGL *functions, GLenum name, size_t index) +{ + GLint result[2] = {}; + functions->getIntegerv(name, result); + return result[index]; +} + +static GLint64 QuerySingleGLInt64(const FunctionsGL *functions, GLenum name) +{ + GLint64 result = 0; + functions->getInteger64v(name, &result); + return result; +} + +static GLfloat QuerySingleGLFloat(const FunctionsGL *functions, GLenum name) +{ + GLfloat result = 0.0f; + functions->getFloatv(name, &result); + return result; +} + +static GLfloat QueryGLFloatRange(const FunctionsGL *functions, GLenum name, size_t index) +{ + GLfloat result[2] = {}; + functions->getFloatv(name, result); + return result[index]; +} + +static gl::TypePrecision QueryTypePrecision(const FunctionsGL *functions, GLenum shaderType, GLenum precisionType) +{ + gl::TypePrecision precision; + functions->getShaderPrecisionFormat(shaderType, precisionType, precision.range, &precision.precision); + return precision; +} + +static GLint QueryQueryValue(const FunctionsGL *functions, GLenum target, GLenum name) +{ + GLint result; + functions->getQueryiv(target, name, &result); + return result; +} + +static void LimitVersion(gl::Version *curVersion, const gl::Version &maxVersion) +{ + if (*curVersion >= maxVersion) + { + *curVersion = maxVersion; + } +} + +void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, + gl::Extensions *extensions, gl::Version *maxSupportedESVersion) +{ + // Texture format support checks + const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); + for (GLenum internalFormat : allFormats) + { + gl::TextureCaps textureCaps = GenerateTextureFormatCaps(functions, internalFormat); + textureCapsMap->insert(internalFormat, textureCaps); + + if (gl::GetInternalFormatInfo(internalFormat).compressed) + { + caps->compressedTextureFormats.push_back(internalFormat); + } + } + + // Start by assuming ES3.1 support and work down + *maxSupportedESVersion = gl::Version(3, 1); + + // Table 6.28, implementation dependent values + if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->hasGLExtension("GL_ARB_ES3_compatibility") || + functions->isAtLeastGLES(gl::Version(3, 0))) + { + caps->maxElementIndex = QuerySingleGLInt64(functions, GL_MAX_ELEMENT_INDEX); + } + else + { + // Doesn't affect ES3 support, can use a pre-defined limit + caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max()); + } + + if (functions->isAtLeastGL(gl::Version(1, 2)) || + functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_OES_texture_3D")) + { + caps->max3DTextureSize = QuerySingleGLInt(functions, GL_MAX_3D_TEXTURE_SIZE); + } + else + { + // Can't support ES3 without 3D textures + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + caps->max2DTextureSize = QuerySingleGLInt(functions, GL_MAX_TEXTURE_SIZE); // GL 1.0 / ES 2.0 + caps->maxCubeMapTextureSize = QuerySingleGLInt(functions, GL_MAX_CUBE_MAP_TEXTURE_SIZE); // GL 1.3 / ES 2.0 + + if (functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_EXT_texture_array") || + functions->isAtLeastGLES(gl::Version(3, 0))) + { + caps->maxArrayTextureLayers = QuerySingleGLInt(functions, GL_MAX_ARRAY_TEXTURE_LAYERS); + } + else + { + // Can't support ES3 without array textures + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + if (functions->isAtLeastGL(gl::Version(1, 5)) || functions->hasGLExtension("GL_EXT_texture_lod_bias") || + functions->isAtLeastGLES(gl::Version(3, 0))) + { + caps->maxLODBias = QuerySingleGLFloat(functions, GL_MAX_TEXTURE_LOD_BIAS); + } + else + { + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + if (functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_EXT_framebuffer_object") || + functions->isAtLeastGLES(gl::Version(2, 0))) + { + caps->maxRenderbufferSize = QuerySingleGLInt(functions, GL_MAX_RENDERBUFFER_SIZE); + caps->maxColorAttachments = QuerySingleGLInt(functions, GL_MAX_COLOR_ATTACHMENTS); + } + else + { + // Can't support ES2 without framebuffers and renderbuffers + LimitVersion(maxSupportedESVersion, gl::Version(0, 0)); + } + + if (functions->isAtLeastGL(gl::Version(2, 0)) || functions->hasGLExtension("ARB_draw_buffers") || + functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_draw_buffers")) + { + caps->maxDrawBuffers = QuerySingleGLInt(functions, GL_MAX_DRAW_BUFFERS); + } + else + { + // Framebuffer is required to have at least one drawbuffer even if the extension is not + // supported + caps->maxDrawBuffers = 1; + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + caps->maxViewportWidth = QueryGLIntRange(functions, GL_MAX_VIEWPORT_DIMS, 0); // GL 1.0 / ES 2.0 + caps->maxViewportHeight = QueryGLIntRange(functions, GL_MAX_VIEWPORT_DIMS, 1); // GL 1.0 / ES 2.0 + + if (functions->standard == STANDARD_GL_DESKTOP && + (functions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0) + { + // Desktop GL core profile deprecated the GL_ALIASED_POINT_SIZE_RANGE query. Use + // GL_POINT_SIZE_RANGE instead. + caps->minAliasedPointSize = QueryGLFloatRange(functions, GL_POINT_SIZE_RANGE, 0); + caps->maxAliasedPointSize = QueryGLFloatRange(functions, GL_POINT_SIZE_RANGE, 1); + } + else + { + caps->minAliasedPointSize = QueryGLFloatRange(functions, GL_ALIASED_POINT_SIZE_RANGE, 0); + caps->maxAliasedPointSize = QueryGLFloatRange(functions, GL_ALIASED_POINT_SIZE_RANGE, 1); + } + + caps->minAliasedLineWidth = QueryGLFloatRange(functions, GL_ALIASED_LINE_WIDTH_RANGE, 0); // GL 1.2 / ES 2.0 + caps->maxAliasedLineWidth = QueryGLFloatRange(functions, GL_ALIASED_LINE_WIDTH_RANGE, 1); // GL 1.2 / ES 2.0 + + // Table 6.29, implementation dependent values (cont.) + if (functions->isAtLeastGL(gl::Version(1, 2)) || + functions->isAtLeastGLES(gl::Version(3, 0))) + { + caps->maxElementsIndices = QuerySingleGLInt(functions, GL_MAX_ELEMENTS_INDICES); + caps->maxElementsVertices = QuerySingleGLInt(functions, GL_MAX_ELEMENTS_VERTICES); + } + else + { + // Doesn't impact supported version + } + + if (functions->isAtLeastGL(gl::Version(4, 1)) || + functions->hasGLExtension("GL_ARB_get_program_binary") || + functions->isAtLeastGLES(gl::Version(3, 0)) || + functions->hasGLExtension("GL_OES_get_program_binary")) + { + // Able to support the GL_PROGRAM_BINARY_ANGLE format as long as another program binary + // format is available. + GLint numBinaryFormats = QuerySingleGLInt(functions, GL_NUM_PROGRAM_BINARY_FORMATS_OES); + if (numBinaryFormats > 0) + { + caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE); + } + } + else + { + // Doesn't impact supported version + } + + // glGetShaderPrecisionFormat is not available until desktop GL version 4.1 or GL_ARB_ES2_compatibility exists + if (functions->isAtLeastGL(gl::Version(4, 1)) || functions->hasGLExtension("GL_ARB_ES2_compatibility") || + functions->isAtLeastGLES(gl::Version(2, 0))) + { + caps->vertexHighpFloat = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_HIGH_FLOAT); + caps->vertexMediumpFloat = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_MEDIUM_FLOAT); + caps->vertexLowpFloat = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_LOW_FLOAT); + caps->fragmentHighpFloat = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_HIGH_FLOAT); + caps->fragmentMediumpFloat = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT); + caps->fragmentLowpFloat = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_LOW_FLOAT); + caps->vertexHighpInt = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_HIGH_INT); + caps->vertexMediumpInt = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_MEDIUM_INT); + caps->vertexLowpInt = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_LOW_INT); + caps->fragmentHighpInt = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_HIGH_INT); + caps->fragmentMediumpInt = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_MEDIUM_INT); + caps->fragmentLowpInt = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_LOW_INT); + } + else + { + // Doesn't impact supported version, set some default values + caps->vertexHighpFloat.setIEEEFloat(); + caps->vertexMediumpFloat.setIEEEFloat(); + caps->vertexLowpFloat.setIEEEFloat(); + caps->fragmentHighpFloat.setIEEEFloat(); + caps->fragmentMediumpFloat.setIEEEFloat(); + caps->fragmentLowpFloat.setIEEEFloat(); + caps->vertexHighpInt.setTwosComplementInt(32); + caps->vertexMediumpInt.setTwosComplementInt(32); + caps->vertexLowpInt.setTwosComplementInt(32); + caps->fragmentHighpInt.setTwosComplementInt(32); + caps->fragmentMediumpInt.setTwosComplementInt(32); + caps->fragmentLowpInt.setTwosComplementInt(32); + } + + if (functions->isAtLeastGL(gl::Version(3, 2)) || functions->hasGLExtension("GL_ARB_sync") || + functions->isAtLeastGLES(gl::Version(3, 0))) + { + caps->maxServerWaitTimeout = QuerySingleGLInt64(functions, GL_MAX_SERVER_WAIT_TIMEOUT); + } + else + { + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + // Table 6.31, implementation dependent vertex shader limits + if (functions->isAtLeastGL(gl::Version(2, 0)) || + functions->isAtLeastGLES(gl::Version(2, 0))) + { + caps->maxVertexAttributes = QuerySingleGLInt(functions, GL_MAX_VERTEX_ATTRIBS); + caps->maxVertexUniformComponents = QuerySingleGLInt(functions, GL_MAX_VERTEX_UNIFORM_COMPONENTS); + caps->maxVertexTextureImageUnits = QuerySingleGLInt(functions, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS); + } + else + { + // Can't support ES2 version without these caps + LimitVersion(maxSupportedESVersion, gl::Version(0, 0)); + } + + if (functions->isAtLeastGL(gl::Version(4, 1)) || functions->hasGLExtension("GL_ARB_ES2_compatibility") || + functions->isAtLeastGLES(gl::Version(2, 0))) + { + caps->maxVertexUniformVectors = QuerySingleGLInt(functions, GL_MAX_VERTEX_UNIFORM_VECTORS); + } + else + { + // Doesn't limit ES version, GL_MAX_VERTEX_UNIFORM_COMPONENTS / 4 is acceptable. + caps->maxVertexUniformVectors = caps->maxVertexUniformComponents / 4; + } + + if (functions->isAtLeastGL(gl::Version(3, 1)) || functions->hasGLExtension("GL_ARB_uniform_buffer_object") || + functions->isAtLeastGLES(gl::Version(3, 0))) + { + caps->maxVertexUniformBlocks = QuerySingleGLInt(functions, GL_MAX_VERTEX_UNIFORM_BLOCKS); + } + else + { + // Can't support ES3 without uniform blocks + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + if (functions->isAtLeastGL(gl::Version(3, 2)) || + functions->isAtLeastGLES(gl::Version(3, 0))) + { + caps->maxVertexOutputComponents = QuerySingleGLInt(functions, GL_MAX_VERTEX_OUTPUT_COMPONENTS); + } + else + { + // There doesn't seem, to be a desktop extension to add this cap, maybe it could be given a safe limit + // instead of limiting the supported ES version. + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + // Table 6.32, implementation dependent fragment shader limits + if (functions->isAtLeastGL(gl::Version(2, 0)) || + functions->isAtLeastGLES(gl::Version(2, 0))) + { + caps->maxFragmentUniformComponents = QuerySingleGLInt(functions, GL_MAX_FRAGMENT_UNIFORM_COMPONENTS); + caps->maxTextureImageUnits = QuerySingleGLInt(functions, GL_MAX_TEXTURE_IMAGE_UNITS); + } + else + { + // Can't support ES2 version without these caps + LimitVersion(maxSupportedESVersion, gl::Version(0, 0)); + } + + if (functions->isAtLeastGL(gl::Version(4, 1)) || functions->hasGLExtension("GL_ARB_ES2_compatibility") || + functions->isAtLeastGLES(gl::Version(2, 0))) + { + caps->maxFragmentUniformVectors = QuerySingleGLInt(functions, GL_MAX_FRAGMENT_UNIFORM_VECTORS); + } + else + { + // Doesn't limit ES version, GL_MAX_FRAGMENT_UNIFORM_COMPONENTS / 4 is acceptable. + caps->maxFragmentUniformVectors = caps->maxFragmentUniformComponents / 4; + } + + if (functions->isAtLeastGL(gl::Version(3, 1)) || functions->hasGLExtension("GL_ARB_uniform_buffer_object") || + functions->isAtLeastGLES(gl::Version(3, 0))) + { + caps->maxFragmentUniformBlocks = QuerySingleGLInt(functions, GL_MAX_FRAGMENT_UNIFORM_BLOCKS); + } + else + { + // Can't support ES3 without uniform blocks + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + if (functions->isAtLeastGL(gl::Version(3, 2)) || + functions->isAtLeastGLES(gl::Version(3, 0))) + { + caps->maxFragmentInputComponents = QuerySingleGLInt(functions, GL_MAX_FRAGMENT_INPUT_COMPONENTS); + } + else + { + // There doesn't seem, to be a desktop extension to add this cap, maybe it could be given a safe limit + // instead of limiting the supported ES version. + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + if (functions->isAtLeastGL(gl::Version(3, 0)) || + functions->isAtLeastGLES(gl::Version(3, 0))) + { + caps->minProgramTexelOffset = QuerySingleGLInt(functions, GL_MIN_PROGRAM_TEXEL_OFFSET); + caps->maxProgramTexelOffset = QuerySingleGLInt(functions, GL_MAX_PROGRAM_TEXEL_OFFSET); + } + else + { + // Can't support ES3 without texel offset, could possibly be emulated in the shader + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + // Table 6.33, implementation dependent aggregate shader limits + if (functions->isAtLeastGL(gl::Version(3, 1)) || functions->hasGLExtension("GL_ARB_uniform_buffer_object") || + functions->isAtLeastGLES(gl::Version(3, 0))) + { + caps->maxUniformBufferBindings = QuerySingleGLInt(functions, GL_MAX_UNIFORM_BUFFER_BINDINGS); + caps->maxUniformBlockSize = QuerySingleGLInt64(functions, GL_MAX_UNIFORM_BLOCK_SIZE); + caps->uniformBufferOffsetAlignment = QuerySingleGLInt(functions, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT); + caps->maxCombinedUniformBlocks = caps->maxVertexUniformBlocks + caps->maxFragmentInputComponents; + caps->maxCombinedVertexUniformComponents = QuerySingleGLInt64(functions, GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS); + caps->maxCombinedFragmentUniformComponents = QuerySingleGLInt64(functions, GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS); + } + else + { + // Can't support ES3 without uniform blocks + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + if (functions->isAtLeastGL(gl::Version(3, 0)) || + functions->hasGLExtension("GL_ARB_ES2_compatibility") || + functions->isAtLeastGLES(gl::Version(2, 0))) + { + caps->maxVaryingComponents = QuerySingleGLInt(functions, GL_MAX_VARYING_COMPONENTS); + } + else if (functions->isAtLeastGL(gl::Version(2, 0))) + { + caps->maxVaryingComponents = QuerySingleGLInt(functions, GL_MAX_VARYING_FLOATS); + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + else + { + LimitVersion(maxSupportedESVersion, gl::Version(0, 0)); + } + + if (functions->isAtLeastGL(gl::Version(4, 1)) || functions->hasGLExtension("GL_ARB_ES2_compatibility") || + functions->isAtLeastGLES(gl::Version(2, 0))) + { + caps->maxVaryingVectors = QuerySingleGLInt(functions, GL_MAX_VARYING_VECTORS); + } + else + { + // Doesn't limit ES version, GL_MAX_VARYING_COMPONENTS / 4 is acceptable. + caps->maxVaryingVectors = caps->maxVaryingComponents / 4; + } + + // Determine the max combined texture image units by adding the vertex and fragment limits. If + // the real cap is queried, it would contain the limits for shader types that are not available to ES. + caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits; + + // Table 6.34, implementation dependent transform feedback limits + if (functions->isAtLeastGL(gl::Version(4, 0)) || + functions->hasGLExtension("GL_ARB_transform_feedback2") || + functions->isAtLeastGLES(gl::Version(3, 0))) + { + caps->maxTransformFeedbackInterleavedComponents = QuerySingleGLInt(functions, GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS); + caps->maxTransformFeedbackSeparateAttributes = QuerySingleGLInt(functions, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS); + caps->maxTransformFeedbackSeparateComponents = QuerySingleGLInt(functions, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS); + } + else + { + // Can't support ES3 without transform feedback + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + // Table 6.35, Framebuffer Dependent Values + if (functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_EXT_framebuffer_multisample") || + functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_multisampled_render_to_texture")) + { + caps->maxSamples = QuerySingleGLInt(functions, GL_MAX_SAMPLES); + } + else + { + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + // Check if index constant sampler array indexing is supported + if (!functions->isAtLeastGL(gl::Version(4, 0)) && + !functions->isAtLeastGLES(gl::Version(2, 0)) && + !functions->hasExtension("GL_ARB_gpu_shader5")) + { + // This should also be required for ES2 but there are some driver support index constant + // sampler array indexing without meeting the requirements above. Don't limit their ES + // version as it would break WebGL for some users. + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + // Check if sampler objects are supported + if (!functions->isAtLeastGL(gl::Version(3, 3)) && + !functions->hasGLExtension("GL_ARB_sampler_objects") && + !functions->isAtLeastGLES(gl::Version(3, 0))) + { + // Can't support ES3 without sampler objects + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + // Can't support ES3 without texture swizzling + if (!functions->isAtLeastGL(gl::Version(3, 3)) && + !functions->hasGLExtension("GL_ARB_texture_swizzle") && + !functions->hasGLExtension("GL_EXT_texture_swizzle") && + !functions->isAtLeastGLES(gl::Version(3, 0))) + { + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + + // Texture swizzling is required to work around the luminance texture format not being + // present in the core profile + if (functions->profile & GL_CONTEXT_CORE_PROFILE_BIT) + { + LimitVersion(maxSupportedESVersion, gl::Version(0, 0)); + } + } + + // Can't support ES3 without the GLSL packing builtins. We have a workaround for all + // desktop OpenGL versions starting from 3.3 with the bit packing extension. + if (!functions->isAtLeastGL(gl::Version(4, 2)) && + !(functions->isAtLeastGL(gl::Version(3, 2)) && + functions->hasGLExtension("GL_ARB_shader_bit_encoding")) && + !functions->hasGLExtension("GL_ARB_shading_language_packing") && + !functions->isAtLeastGLES(gl::Version(3, 0))) + { + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + // ES3 needs to support explicit layout location qualifiers, while it might be possible to + // fake them in our side, we currently don't support that. + if (!functions->isAtLeastGL(gl::Version(3, 3)) && + !functions->hasGLExtension("GL_ARB_explicit_attrib_location") && + !functions->isAtLeastGLES(gl::Version(3, 0))) + { + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 1)) || + functions->hasGLExtension("GL_ARB_texture_multisample")) + { + caps->maxFramebufferWidth = QuerySingleGLInt(functions, GL_MAX_FRAMEBUFFER_WIDTH); + caps->maxFramebufferHeight = QuerySingleGLInt(functions, GL_MAX_FRAMEBUFFER_HEIGHT); + caps->maxFramebufferSamples = QuerySingleGLInt(functions, GL_MAX_FRAMEBUFFER_SAMPLES); + } + else + { + LimitVersion(maxSupportedESVersion, gl::Version(3, 0)); + } + + if (functions->isAtLeastGL(gl::Version(3, 2)) || functions->isAtLeastGLES(gl::Version(3, 1)) || + functions->hasGLExtension("GL_ARB_texture_multisample")) + { + caps->maxSampleMaskWords = QuerySingleGLInt(functions, GL_MAX_SAMPLE_MASK_WORDS); + caps->maxColorTextureSamples = QuerySingleGLInt(functions, GL_MAX_COLOR_TEXTURE_SAMPLES); + caps->maxDepthTextureSamples = QuerySingleGLInt(functions, GL_MAX_DEPTH_TEXTURE_SAMPLES); + caps->maxIntegerSamples = QuerySingleGLInt(functions, GL_MAX_INTEGER_SAMPLES); + } + else + { + LimitVersion(maxSupportedESVersion, gl::Version(3, 0)); + } + + if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 1)) || + functions->hasGLExtension("GL_ARB_vertex_attrib_binding")) + { + caps->maxVertexAttribRelativeOffset = + QuerySingleGLInt(functions, GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET); + caps->maxVertexAttribBindings = QuerySingleGLInt(functions, GL_MAX_VERTEX_ATTRIB_BINDINGS); + caps->maxVertexAttribStride = QuerySingleGLInt(functions, GL_MAX_VERTEX_ATTRIB_STRIDE); + } + else + { + LimitVersion(maxSupportedESVersion, gl::Version(3, 0)); + } + + if (functions->isAtLeastGL(gl::Version(4, 2)) || functions->isAtLeastGLES(gl::Version(3, 1)) || + functions->hasGLExtension("GL_ARB_shader_storage_buffer_object")) + { + caps->maxCombinedShaderOutputResources = + QuerySingleGLInt(functions, GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES); + caps->maxFragmentShaderStorageBlocks = + QuerySingleGLInt(functions, GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS); + caps->maxVertexShaderStorageBlocks = + QuerySingleGLInt(functions, GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS); + caps->maxShaderStorageBufferBindings = + QuerySingleGLInt(functions, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS); + caps->maxShaderStorageBlockSize = + QuerySingleGLInt64(functions, GL_MAX_SHADER_STORAGE_BLOCK_SIZE); + caps->maxCombinedShaderStorageBlocks = + QuerySingleGLInt(functions, GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS); + caps->shaderStorageBufferOffsetAlignment = + QuerySingleGLInt(functions, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT); + } + else + { + LimitVersion(maxSupportedESVersion, gl::Version(3, 0)); + } + + if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 1)) || + functions->hasGLExtension("GL_ARB_compute_shader")) + { + for (GLuint index = 0u; index < 3u; ++index) + { + caps->maxComputeWorkGroupCount[index] = + QuerySingleIndexGLInt(functions, GL_MAX_COMPUTE_WORK_GROUP_COUNT, index); + + caps->maxComputeWorkGroupSize[index] = + QuerySingleIndexGLInt(functions, GL_MAX_COMPUTE_WORK_GROUP_SIZE, index); + } + caps->maxComputeWorkGroupInvocations = + QuerySingleGLInt(functions, GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS); + caps->maxComputeUniformBlocks = QuerySingleGLInt(functions, GL_MAX_COMPUTE_UNIFORM_BLOCKS); + caps->maxComputeTextureImageUnits = + QuerySingleGLInt(functions, GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS); + caps->maxComputeSharedMemorySize = + QuerySingleGLInt(functions, GL_MAX_COMPUTE_SHARED_MEMORY_SIZE); + caps->maxComputeUniformComponents = + QuerySingleGLInt(functions, GL_MAX_COMPUTE_UNIFORM_COMPONENTS); + caps->maxComputeAtomicCounterBuffers = + QuerySingleGLInt(functions, GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS); + caps->maxComputeAtomicCounters = + QuerySingleGLInt(functions, GL_MAX_COMPUTE_ATOMIC_COUNTERS); + caps->maxComputeImageUniforms = QuerySingleGLInt(functions, GL_MAX_COMPUTE_IMAGE_UNIFORMS); + caps->maxCombinedComputeUniformComponents = + QuerySingleGLInt(functions, GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS); + caps->maxComputeShaderStorageBlocks = + QuerySingleGLInt(functions, GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS); + } + else + { + LimitVersion(maxSupportedESVersion, gl::Version(3, 0)); + } + + if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 1)) || + functions->hasGLExtension("GL_ARB_explicit_uniform_location")) + { + caps->maxUniformLocations = QuerySingleGLInt(functions, GL_MAX_UNIFORM_LOCATIONS); + } + else + { + LimitVersion(maxSupportedESVersion, gl::Version(3, 0)); + } + + if (functions->isAtLeastGL(gl::Version(4, 0)) || functions->isAtLeastGLES(gl::Version(3, 1)) || + functions->hasGLExtension("GL_ARB_texture_gather")) + { + caps->minProgramTextureGatherOffset = + QuerySingleGLInt(functions, GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET); + caps->maxProgramTextureGatherOffset = + QuerySingleGLInt(functions, GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET); + } + else + { + LimitVersion(maxSupportedESVersion, gl::Version(3, 0)); + } + + if (functions->isAtLeastGL(gl::Version(4, 2)) || functions->isAtLeastGLES(gl::Version(3, 1)) || + functions->hasGLExtension("GL_ARB_shader_image_load_store")) + { + caps->maxVertexImageUniforms = QuerySingleGLInt(functions, GL_MAX_VERTEX_IMAGE_UNIFORMS); + caps->maxFragmentImageUniforms = + QuerySingleGLInt(functions, GL_MAX_FRAGMENT_IMAGE_UNIFORMS); + caps->maxImageUnits = QuerySingleGLInt(functions, GL_MAX_IMAGE_UNITS); + caps->maxCombinedImageUniforms = + QuerySingleGLInt(functions, GL_MAX_COMBINED_IMAGE_UNIFORMS); + } + else + { + LimitVersion(maxSupportedESVersion, gl::Version(3, 0)); + } + + if (functions->isAtLeastGL(gl::Version(4, 2)) || functions->isAtLeastGLES(gl::Version(3, 1)) || + functions->hasGLExtension("GL_ARB_shader_atomic_counters")) + { + caps->maxVertexAtomicCounterBuffers = + QuerySingleGLInt(functions, GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS); + caps->maxVertexAtomicCounters = QuerySingleGLInt(functions, GL_MAX_VERTEX_ATOMIC_COUNTERS); + caps->maxFragmentAtomicCounterBuffers = + QuerySingleGLInt(functions, GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS); + caps->maxFragmentAtomicCounters = + QuerySingleGLInt(functions, GL_MAX_FRAGMENT_ATOMIC_COUNTERS); + caps->maxAtomicCounterBufferBindings = + QuerySingleGLInt(functions, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS); + caps->maxAtomicCounterBufferSize = + QuerySingleGLInt(functions, GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE); + caps->maxCombinedAtomicCounterBuffers = + QuerySingleGLInt(functions, GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS); + caps->maxCombinedAtomicCounters = + QuerySingleGLInt(functions, GL_MAX_COMBINED_ATOMIC_COUNTERS); + } + else + { + LimitVersion(maxSupportedESVersion, gl::Version(3, 0)); + } + + // TODO(geofflang): The gl-uniform-arrays WebGL conformance test struggles to complete on time + // if the max uniform vectors is too large. Artificially limit the maximum until the test is + // updated. + caps->maxVertexUniformVectors = std::min(1024u, caps->maxVertexUniformVectors); + caps->maxVertexUniformComponents = + std::min(caps->maxVertexUniformVectors * 4, caps->maxVertexUniformComponents); + caps->maxFragmentUniformVectors = std::min(1024u, caps->maxFragmentUniformVectors); + caps->maxFragmentUniformComponents = + std::min(caps->maxFragmentUniformVectors * 4, caps->maxFragmentUniformComponents); + + // If it is not possible to support reading buffer data back, a shadow copy of the buffers must + // be held. This disallows writing to buffers indirectly through transform feedback, thus + // disallowing ES3. + if (!CanMapBufferForRead(functions)) + { + LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); + } + + // Extension support + extensions->setTextureExtensionSupport(*textureCapsMap); + extensions->elementIndexUint = functions->standard == STANDARD_GL_DESKTOP || + functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_OES_element_index_uint"); + extensions->getProgramBinary = caps->programBinaryFormats.size() > 0; + extensions->readFormatBGRA = functions->isAtLeastGL(gl::Version(1, 2)) || functions->hasGLExtension("GL_EXT_bgra") || + functions->hasGLESExtension("GL_EXT_read_format_bgra"); + extensions->mapBuffer = functions->isAtLeastGL(gl::Version(1, 5)) || + functions->hasGLESExtension("GL_OES_mapbuffer"); + extensions->mapBufferRange = functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_ARB_map_buffer_range") || + functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_map_buffer_range"); + extensions->textureNPOT = functions->standard == STANDARD_GL_DESKTOP || + functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_OES_texture_npot"); + extensions->drawBuffers = functions->isAtLeastGL(gl::Version(2, 0)) || functions->hasGLExtension("ARB_draw_buffers") || + functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_draw_buffers"); + extensions->textureStorage = true; + extensions->textureFilterAnisotropic = functions->hasGLExtension("GL_EXT_texture_filter_anisotropic") || functions->hasGLESExtension("GL_EXT_texture_filter_anisotropic"); + extensions->occlusionQueryBoolean = + functions->isAtLeastGL(gl::Version(1, 5)) || + functions->hasGLExtension("GL_ARB_occlusion_query2") || + functions->isAtLeastGLES(gl::Version(3, 0)) || + functions->hasGLESExtension("GL_EXT_occlusion_query_boolean"); + extensions->maxTextureAnisotropy = extensions->textureFilterAnisotropic ? QuerySingleGLFloat(functions, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 0.0f; + extensions->fence = functions->hasGLExtension("GL_NV_fence") || functions->hasGLESExtension("GL_NV_fence"); + extensions->blendMinMax = functions->isAtLeastGL(gl::Version(1, 5)) || functions->hasGLExtension("GL_EXT_blend_minmax") || + functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_blend_minmax"); + extensions->framebufferBlit = (functions->blitFramebuffer != nullptr); + extensions->framebufferMultisample = caps->maxSamples > 0; + extensions->standardDerivatives = functions->isAtLeastGL(gl::Version(2, 0)) || functions->hasGLExtension("GL_ARB_fragment_shader") || + functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_OES_standard_derivatives"); + extensions->shaderTextureLOD = functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_ARB_shader_texture_lod") || + functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_shader_texture_lod"); + extensions->fragDepth = functions->standard == STANDARD_GL_DESKTOP || + functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_frag_depth"); + extensions->fboRenderMipmap = functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_EXT_framebuffer_object") || + functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_OES_fbo_render_mipmap"); + extensions->instancedArrays = functions->isAtLeastGL(gl::Version(3, 1)) || + (functions->hasGLExtension("GL_ARB_instanced_arrays") && + (functions->hasGLExtension("GL_ARB_draw_instanced") || + functions->hasGLExtension("GL_EXT_draw_instanced"))) || + functions->isAtLeastGLES(gl::Version(3, 0)) || + functions->hasGLESExtension("GL_EXT_instanced_arrays"); + extensions->unpackSubimage = functions->standard == STANDARD_GL_DESKTOP || + functions->isAtLeastGLES(gl::Version(3, 0)) || + functions->hasGLESExtension("GL_EXT_unpack_subimage"); + extensions->packSubimage = functions->standard == STANDARD_GL_DESKTOP || + functions->isAtLeastGLES(gl::Version(3, 0)) || + functions->hasGLESExtension("GL_NV_pack_subimage"); + extensions->debugMarker = + functions->isAtLeastGL(gl::Version(4, 3)) || functions->hasGLExtension("GL_KHR_debug") || + functions->isAtLeastGLES(gl::Version(3, 2)) || functions->hasGLESExtension("GL_KHR_debug"); + if (functions->isAtLeastGL(gl::Version(3, 3)) || + functions->hasGLExtension("GL_ARB_timer_query") || + functions->hasGLESExtension("GL_EXT_disjoint_timer_query")) + { + extensions->disjointTimerQuery = true; + extensions->queryCounterBitsTimeElapsed = + QueryQueryValue(functions, GL_TIME_ELAPSED, GL_QUERY_COUNTER_BITS); + extensions->queryCounterBitsTimestamp = + QueryQueryValue(functions, GL_TIMESTAMP, GL_QUERY_COUNTER_BITS); + } + + // the EXT_multisample_compatibility is written against ES3.1 but can apply + // to earlier versions so therefore we're only checking for the extension string + // and not the specific GLES version. + extensions->multisampleCompatibility = functions->isAtLeastGL(gl::Version(1, 3)) || + functions->hasGLESExtension("GL_EXT_multisample_compatibility"); + + extensions->framebufferMixedSamples = + functions->hasGLExtension("GL_NV_framebuffer_mixed_samples") || + functions->hasGLESExtension("GL_NV_framebuffer_mixed_samples"); + + extensions->robustness = functions->isAtLeastGL(gl::Version(4, 5)) || + functions->hasGLExtension("GL_KHR_robustness") || + functions->hasGLExtension("GL_ARB_robustness") || + functions->isAtLeastGLES(gl::Version(3, 2)) || + functions->hasGLESExtension("GL_KHR_robustness") || + functions->hasGLESExtension("GL_EXT_robustness"); + + // NV_path_rendering + // We also need interface query which is available in + // >= 4.3 core or ARB_interface_query or >= GLES 3.1 + const bool canEnableGLPathRendering = + functions->hasGLExtension("GL_NV_path_rendering") && + (functions->hasGLExtension("GL_ARB_program_interface_query") || + functions->isAtLeastGL(gl::Version(4, 3))); + + const bool canEnableESPathRendering = + functions->hasGLESExtension("GL_NV_path_rendering") && + functions->isAtLeastGLES(gl::Version(3, 1)); + + extensions->pathRendering = canEnableGLPathRendering || canEnableESPathRendering; + + extensions->textureSRGBDecode = functions->hasGLExtension("GL_EXT_texture_sRGB_decode") || + functions->hasGLESExtension("GL_EXT_texture_sRGB_decode"); + +#if defined(ANGLE_PLATFORM_APPLE) + VendorID vendor = GetVendorID(functions); + if ((IsAMD(vendor) || IsIntel(vendor)) && *maxSupportedESVersion >= gl::Version(3, 0)) + { + // Apple Intel/AMD drivers do not correctly use the TEXTURE_SRGB_DECODE property of sampler + // states. Disable this extension when we would advertise any ES version that has samplers. + extensions->textureSRGBDecode = false; + } +#endif + + extensions->sRGBWriteControl = functions->isAtLeastGL(gl::Version(3, 0)) || + functions->hasGLExtension("GL_EXT_framebuffer_sRGB") || + functions->hasGLExtension("GL_ARB_framebuffer_sRGB") || + functions->hasGLESExtension("GL_EXT_sRGB_write_control"); + +#if defined(ANGLE_PLATFORM_ANDROID) + // SRGB blending does not appear to work correctly on the Nexus 5. Writing to an SRGB + // framebuffer with GL_FRAMEBUFFER_SRGB enabled and then reading back returns the same value. + // Disabling GL_FRAMEBUFFER_SRGB will then convert in the wrong direction. + extensions->sRGBWriteControl = false; +#endif +} + +void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds) +{ + VendorID vendor = GetVendorID(functions); + + workarounds->dontRemoveInvariantForFragmentInput = + functions->standard == STANDARD_GL_DESKTOP && IsAMD(vendor); + + // Don't use 1-bit alpha formats on desktop GL with AMD or Intel drivers. + workarounds->avoid1BitAlphaTextureFormats = + functions->standard == STANDARD_GL_DESKTOP && (IsAMD(vendor) || IsIntel(vendor)); + + workarounds->rgba4IsNotSupportedForColorRendering = + functions->standard == STANDARD_GL_DESKTOP && IsIntel(vendor); + + workarounds->emulateAbsIntFunction = IsIntel(vendor); + + workarounds->addAndTrueToLoopCondition = IsIntel(vendor); + + workarounds->emulateIsnanFloat = IsIntel(vendor); + + workarounds->doesSRGBClearsOnLinearFramebufferAttachments = + functions->standard == STANDARD_GL_DESKTOP && (IsIntel(vendor) || IsAMD(vendor)); + +#if defined(ANGLE_PLATFORM_APPLE) + workarounds->doWhileGLSLCausesGPUHang = true; + workarounds->useUnusedBlocksWithStandardOrSharedLayout = true; +#endif + + workarounds->finishDoesNotCauseQueriesToBeAvailable = + functions->standard == STANDARD_GL_DESKTOP && IsNvidia(vendor); + + // TODO(cwallez): Disable this workaround for MacOSX versions 10.9 or later. + workarounds->alwaysCallUseProgramAfterLink = true; + + workarounds->unpackOverlappingRowsSeparatelyUnpackBuffer = IsNvidia(vendor); + workarounds->packOverlappingRowsSeparatelyPackBuffer = IsNvidia(vendor); + + workarounds->initializeCurrentVertexAttributes = IsNvidia(vendor); + +#if defined(ANGLE_PLATFORM_APPLE) + workarounds->unpackLastRowSeparatelyForPaddingInclusion = true; + workarounds->packLastRowSeparatelyForPaddingInclusion = true; +#else + workarounds->unpackLastRowSeparatelyForPaddingInclusion = IsNvidia(vendor); + workarounds->packLastRowSeparatelyForPaddingInclusion = IsNvidia(vendor); +#endif + + workarounds->removeInvariantAndCentroidForESSL3 = functions->isAtMostGL(gl::Version(4, 1)); +} + +} + +bool CanMapBufferForRead(const FunctionsGL *functions) +{ + return (functions->mapBufferRange != nullptr) || + (functions->mapBuffer != nullptr && functions->standard == STANDARD_GL_DESKTOP); +} + +uint8_t *MapBufferRangeWithFallback(const FunctionsGL *functions, + GLenum target, + size_t offset, + size_t length, + GLbitfield access) +{ + if (functions->mapBufferRange != nullptr) + { + return reinterpret_cast<uint8_t *>( + functions->mapBufferRange(target, offset, length, access)); + } + else if (functions->mapBuffer != nullptr && + (functions->standard == STANDARD_GL_DESKTOP || access == GL_MAP_WRITE_BIT)) + { + // Only the read and write bits are supported + ASSERT((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) != 0); + + GLenum accessEnum = 0; + if (access == (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) + { + accessEnum = GL_READ_WRITE; + } + else if (access == GL_MAP_READ_BIT) + { + accessEnum = GL_READ_ONLY; + } + else if (access == GL_MAP_WRITE_BIT) + { + accessEnum = GL_WRITE_ONLY; + } + else + { + UNREACHABLE(); + return nullptr; + } + + return reinterpret_cast<uint8_t *>(functions->mapBuffer(target, accessEnum)) + offset; + } + else + { + // No options available + UNREACHABLE(); + return nullptr; + } +} + +gl::ErrorOrResult<bool> ShouldApplyLastRowPaddingWorkaround(const gl::Extents &size, + const gl::PixelStoreStateBase &state, + GLenum format, + GLenum type, + bool is3D, + const void *pixels) +{ + if (state.pixelBuffer.get() == nullptr) + { + return false; + } + + // We are using an pack or unpack buffer, compute what the driver thinks is going to be the + // last byte read or written. If it is past the end of the buffer, we will need to use the + // workaround otherwise the driver will generate INVALID_OPERATION and not do the operation. + CheckedNumeric<size_t> checkedEndByte; + CheckedNumeric<size_t> pixelBytes; + size_t rowPitch; + + const gl::InternalFormat &glFormat = + gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type)); + ANGLE_TRY_RESULT(glFormat.computePackUnpackEndByte(size, state, is3D), checkedEndByte); + ANGLE_TRY_RESULT(glFormat.computeRowPitch(size.width, state.alignment, state.rowLength), + rowPitch); + pixelBytes = glFormat.pixelBytes; + + checkedEndByte += reinterpret_cast<intptr_t>(pixels); + + // At this point checkedEndByte is the actual last byte read. + // The driver adds an extra row padding (if any), mimic it. + ANGLE_TRY_CHECKED_MATH(pixelBytes); + if (pixelBytes.ValueOrDie() * size.width < rowPitch) + { + checkedEndByte += rowPitch - pixelBytes * size.width; + } + + ANGLE_TRY_CHECKED_MATH(checkedEndByte); + + return checkedEndByte.ValueOrDie() > static_cast<size_t>(state.pixelBuffer->getSize()); +} +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.h b/gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.h new file mode 100755 index 000000000..1e9338fb5 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.h @@ -0,0 +1,61 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// renderergl_utils.h: Conversion functions and other utility routines +// specific to the OpenGL renderer. + +#ifndef LIBANGLE_RENDERER_GL_RENDERERGLUTILS_H_ +#define LIBANGLE_RENDERER_GL_RENDERERGLUTILS_H_ + +#include "libANGLE/angletypes.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/driver_utils.h" +#include "libANGLE/renderer/gl/functionsgl_typedefs.h" + +#include <string> +#include <vector> + +namespace gl +{ +struct Caps; +class TextureCapsMap; +struct Extensions; +struct Version; +} + +namespace rx +{ +class FunctionsGL; +struct WorkaroundsGL; + +VendorID GetVendorID(const FunctionsGL *functions); +std::string GetDriverVersion(const FunctionsGL *functions); + +namespace nativegl_gl +{ + +void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, + gl::Extensions *extensions, gl::Version *maxSupportedESVersion); + +void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds); +} + +bool CanMapBufferForRead(const FunctionsGL *functions); +uint8_t *MapBufferRangeWithFallback(const FunctionsGL *functions, + GLenum target, + size_t offset, + size_t length, + GLbitfield access); + +gl::ErrorOrResult<bool> ShouldApplyLastRowPaddingWorkaround(const gl::Extents &size, + const gl::PixelStoreStateBase &state, + GLenum format, + GLenum type, + bool is3D, + const void *pixels); +} + +#endif // LIBANGLE_RENDERER_GL_RENDERERGLUTILS_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp new file mode 100644 index 000000000..f19e8fdf3 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp @@ -0,0 +1,384 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// D3DTextureSurfaceWGL.cpp: WGL implementation of egl::Surface for D3D texture interop. + +#include "libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h" + +#include "libANGLE/renderer/gl/FramebufferGL.h" +#include "libANGLE/renderer/gl/TextureGL.h" +#include "libANGLE/renderer/gl/RendererGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" +#include "libANGLE/renderer/gl/wgl/DisplayWGL.h" +#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h" + +namespace rx +{ + +namespace +{ + +egl::Error GetD3DTextureInfo(EGLClientBuffer clientBuffer, + size_t *width, + size_t *height, + IUnknown **object, + IUnknown **device) +{ + IUnknown *buffer = static_cast<IUnknown *>(clientBuffer); + + IDirect3DTexture9 *texture9 = nullptr; + ID3D11Texture2D *texture11 = nullptr; + if (SUCCEEDED(buffer->QueryInterface<ID3D11Texture2D>(&texture11))) + { + D3D11_TEXTURE2D_DESC textureDesc; + texture11->GetDesc(&textureDesc); + + // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer. + switch (textureDesc.Format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + break; + + default: + SafeRelease(texture11); + return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.", + textureDesc.Format); + } + + ID3D11Device *d3d11Device = nullptr; + texture11->GetDevice(&d3d11Device); + if (d3d11Device == nullptr) + { + SafeRelease(texture11); + return egl::Error(EGL_BAD_PARAMETER, + "Could not query the D3D11 device from the client buffer."); + } + + if (width) + { + *width = textureDesc.Width; + } + if (height) + { + *height = textureDesc.Height; + } + + if (device) + { + *device = d3d11Device; + } + else + { + SafeRelease(d3d11Device); + } + + if (object) + { + *object = texture11; + } + else + { + SafeRelease(texture11); + } + + return egl::Error(EGL_SUCCESS); + } + else if (SUCCEEDED(buffer->QueryInterface<IDirect3DTexture9>(&texture9))) + { + D3DSURFACE_DESC surfaceDesc; + if (FAILED(texture9->GetLevelDesc(0, &surfaceDesc))) + { + SafeRelease(texture9); + return egl::Error(EGL_BAD_PARAMETER, + "Could not query description of the D3D9 surface."); + } + + // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer. + switch (surfaceDesc.Format) + { + case D3DFMT_R8G8B8: + case D3DFMT_A8R8G8B8: + case D3DFMT_A16B16G16R16F: + case D3DFMT_A32B32G32R32F: + break; + + default: + SafeRelease(texture9); + return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.", + surfaceDesc.Format); + } + + if (width) + { + *width = surfaceDesc.Width; + } + if (height) + { + *height = surfaceDesc.Height; + } + + IDirect3DDevice9 *d3d9Device = nullptr; + HRESULT result = texture9->GetDevice(&d3d9Device); + if (FAILED(result)) + { + SafeRelease(texture9); + return egl::Error(EGL_BAD_PARAMETER, + "Could not query the D3D9 device from the client buffer."); + } + + if (device) + { + *device = d3d9Device; + } + else + { + SafeRelease(d3d9Device); + } + + if (object) + { + *object = texture9; + } + else + { + SafeRelease(texture9); + } + + return egl::Error(EGL_SUCCESS); + } + else + { + return egl::Error(EGL_BAD_PARAMETER, + "Provided buffer is not a IDirect3DTexture9 or ID3D11Texture2D."); + } +} + +} // anonymous namespace + +D3DTextureSurfaceWGL::D3DTextureSurfaceWGL(const egl::SurfaceState &state, + RendererGL *renderer, + EGLClientBuffer clientBuffer, + DisplayWGL *display, + HGLRC wglContext, + HDC deviceContext, + const FunctionsGL *functionsGL, + const FunctionsWGL *functionsWGL) + : SurfaceGL(state, renderer), + mClientBuffer(clientBuffer), + mRenderer(renderer), + mDisplay(display), + mStateManager(renderer->getStateManager()), + mWorkarounds(renderer->getWorkarounds()), + mFunctionsGL(functionsGL), + mFunctionsWGL(functionsWGL), + mWGLContext(wglContext), + mDeviceContext(deviceContext), + mWidth(0), + mHeight(0), + mDeviceHandle(nullptr), + mObject(nullptr), + mBoundObjectTextureHandle(nullptr), + mBoundObjectRenderbufferHandle(nullptr), + mRenderbufferID(0), + mFramebufferID(0) +{ +} + +D3DTextureSurfaceWGL::~D3DTextureSurfaceWGL() +{ + ASSERT(mBoundObjectTextureHandle == nullptr); + + SafeRelease(mObject); + + if (mDeviceHandle) + { + if (mBoundObjectRenderbufferHandle) + { + mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mBoundObjectRenderbufferHandle); + mBoundObjectRenderbufferHandle = nullptr; + } + mStateManager->deleteRenderbuffer(mRenderbufferID); + + if (mBoundObjectTextureHandle) + { + mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mBoundObjectTextureHandle); + mBoundObjectTextureHandle = nullptr; + } + + // GL framebuffer is deleted by the default framebuffer object + mFramebufferID = 0; + + mDisplay->releaseD3DDevice(mDeviceHandle); + mDeviceHandle = nullptr; + } +} + +egl::Error D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(EGLClientBuffer clientBuffer) +{ + return GetD3DTextureInfo(clientBuffer, nullptr, nullptr, nullptr, nullptr); +} + +egl::Error D3DTextureSurfaceWGL::initialize() +{ + IUnknown *device = nullptr; + ANGLE_TRY(GetD3DTextureInfo(mClientBuffer, &mWidth, &mHeight, &mObject, &device)); + + ASSERT(device != nullptr); + egl::Error error = mDisplay->registerD3DDevice(device, &mDeviceHandle); + SafeRelease(device); + if (error.isError()) + { + return error; + } + + mFunctionsGL->genRenderbuffers(1, &mRenderbufferID); + mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID); + mBoundObjectRenderbufferHandle = mFunctionsWGL->dxRegisterObjectNV( + mDeviceHandle, mObject, mRenderbufferID, GL_RENDERBUFFER, WGL_ACCESS_READ_WRITE_NV); + if (mBoundObjectRenderbufferHandle == nullptr) + { + return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%08x.", + HRESULT_CODE(GetLastError())); + } + + mFunctionsGL->genFramebuffers(1, &mFramebufferID); + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); + mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, + mRenderbufferID); + + return egl::Error(EGL_SUCCESS); +} + +egl::Error D3DTextureSurfaceWGL::makeCurrent() +{ + if (!mFunctionsWGL->makeCurrent(mDeviceContext, mWGLContext)) + { + // TODO(geofflang): What error type here? + return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current."); + } + + if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, 1, &mBoundObjectRenderbufferHandle)) + { + DWORD error = GetLastError(); + return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.", + HRESULT_CODE(error)); + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error D3DTextureSurfaceWGL::unMakeCurrent() +{ + if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mBoundObjectRenderbufferHandle)) + { + DWORD error = GetLastError(); + return egl::Error(EGL_BAD_ALLOC, "Failed to unlock object, error: 0x%08x.", + HRESULT_CODE(error)); + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error D3DTextureSurfaceWGL::swap() +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error D3DTextureSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error D3DTextureSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error D3DTextureSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer) +{ + ASSERT(mBoundObjectTextureHandle == nullptr); + + const TextureGL *textureGL = GetImplAs<TextureGL>(texture); + GLuint textureID = textureGL->getTextureID(); + + mBoundObjectTextureHandle = mFunctionsWGL->dxRegisterObjectNV( + mDeviceHandle, mObject, textureID, GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV); + if (mBoundObjectTextureHandle == nullptr) + { + DWORD error = GetLastError(); + return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%08x.", + HRESULT_CODE(error)); + } + + if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, 1, &mBoundObjectTextureHandle)) + { + DWORD error = GetLastError(); + return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.", + HRESULT_CODE(error)); + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error D3DTextureSurfaceWGL::releaseTexImage(EGLint buffer) +{ + ASSERT(mBoundObjectTextureHandle != nullptr); + if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mBoundObjectTextureHandle)) + { + DWORD error = GetLastError(); + return egl::Error(EGL_BAD_ALLOC, "Failed to unlock object, error: 0x%08x.", + HRESULT_CODE(error)); + } + + if (!mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mBoundObjectTextureHandle)) + { + DWORD error = GetLastError(); + return egl::Error(EGL_BAD_ALLOC, "Failed to unregister D3D object, error: 0x%08x.", + HRESULT_CODE(error)); + } + mBoundObjectTextureHandle = nullptr; + + return egl::Error(EGL_SUCCESS); +} + +void D3DTextureSurfaceWGL::setSwapInterval(EGLint interval) +{ + UNIMPLEMENTED(); +} + +EGLint D3DTextureSurfaceWGL::getWidth() const +{ + return static_cast<EGLint>(mWidth); +} + +EGLint D3DTextureSurfaceWGL::getHeight() const +{ + return static_cast<EGLint>(mHeight); +} + +EGLint D3DTextureSurfaceWGL::isPostSubBufferSupported() const +{ + return EGL_FALSE; +} + +EGLint D3DTextureSurfaceWGL::getSwapBehavior() const +{ + return EGL_BUFFER_PRESERVED; +} + +FramebufferImpl *D3DTextureSurfaceWGL::createDefaultFramebuffer(const gl::FramebufferState &data) +{ + return new FramebufferGL(mFramebufferID, data, mFunctionsGL, mWorkarounds, + mRenderer->getBlitter(), mStateManager); +} +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h new file mode 100644 index 000000000..8fb1d4003 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h @@ -0,0 +1,86 @@ + +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// D3DTextureSurfaceWGL.h: WGL implementation of egl::Surface for D3D texture interop. + +#ifndef LIBANGLE_RENDERER_GL_WGL_D3DTEXTIRESURFACEWGL_H_ +#define LIBANGLE_RENDERER_GL_WGL_D3DTEXTIRESURFACEWGL_H_ + +#include "libANGLE/renderer/gl/SurfaceGL.h" + +#include <GL/wglext.h> + +namespace rx +{ + +class FunctionsGL; +class FunctionsWGL; +class DisplayWGL; +class StateManagerGL; +struct WorkaroundsGL; + +class D3DTextureSurfaceWGL : public SurfaceGL +{ + public: + D3DTextureSurfaceWGL(const egl::SurfaceState &state, + RendererGL *renderer, + EGLClientBuffer clientBuffer, + DisplayWGL *display, + HGLRC wglContext, + HDC deviceContext, + const FunctionsGL *functionsGL, + const FunctionsWGL *functionsWGL); + ~D3DTextureSurfaceWGL() override; + + static egl::Error ValidateD3DTextureClientBuffer(EGLClientBuffer clientBuffer); + + egl::Error initialize() override; + egl::Error makeCurrent() override; + egl::Error unMakeCurrent() override; + + egl::Error swap() override; + egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; + egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; + egl::Error releaseTexImage(EGLint buffer) override; + void setSwapInterval(EGLint interval) override; + + EGLint getWidth() const override; + EGLint getHeight() const override; + + EGLint isPostSubBufferSupported() const override; + EGLint getSwapBehavior() const override; + + FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override; + + private: + EGLClientBuffer mClientBuffer; + + RendererGL *mRenderer; + + DisplayWGL *mDisplay; + StateManagerGL *mStateManager; + const WorkaroundsGL &mWorkarounds; + const FunctionsGL *mFunctionsGL; + const FunctionsWGL *mFunctionsWGL; + + HGLRC mWGLContext; + HDC mDeviceContext; + + size_t mWidth; + size_t mHeight; + + HANDLE mDeviceHandle; + IUnknown *mObject; + HANDLE mBoundObjectTextureHandle; + HANDLE mBoundObjectRenderbufferHandle; + + GLuint mRenderbufferID; + GLuint mFramebufferID; +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_GL_WGL_D3DTEXTIRESURFACEWGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp new file mode 100755 index 000000000..7c5214e82 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp @@ -0,0 +1,553 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DXGISwapChainWindowSurfaceWGL.cpp: WGL implementation of egl::Surface for windows using a DXGI +// swapchain. + +#include "libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h" + +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/gl/FramebufferGL.h" +#include "libANGLE/renderer/gl/TextureGL.h" +#include "libANGLE/renderer/gl/RendererGL.h" +#include "libANGLE/renderer/gl/StateManagerGL.h" +#include "libANGLE/renderer/gl/wgl/DisplayWGL.h" +#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h" + +#include <EGL/eglext.h> + +namespace rx +{ + +DXGISwapChainWindowSurfaceWGL::DXGISwapChainWindowSurfaceWGL(const egl::SurfaceState &state, + RendererGL *renderer, + EGLNativeWindowType window, + ID3D11Device *device, + HANDLE deviceHandle, + HGLRC wglContext, + HDC deviceContext, + const FunctionsGL *functionsGL, + const FunctionsWGL *functionsWGL, + EGLint orientation) + : SurfaceGL(state, renderer), + mWindow(window), + mStateManager(renderer->getStateManager()), + mWorkarounds(renderer->getWorkarounds()), + mRenderer(renderer), + mFunctionsGL(functionsGL), + mFunctionsWGL(functionsWGL), + mDevice(device), + mDeviceHandle(deviceHandle), + mWGLDevice(deviceContext), + mWGLContext(wglContext), + mSwapChainFormat(DXGI_FORMAT_UNKNOWN), + mSwapChainFlags(0), + mDepthBufferFormat(GL_NONE), + mFirstSwap(true), + mSwapChain(nullptr), + mSwapChain1(nullptr), + mColorRenderbufferID(0), + mRenderbufferBufferHandle(nullptr), + mDepthRenderbufferID(0), + mFramebufferID(0), + mTextureID(0), + mTextureHandle(nullptr), + mWidth(0), + mHeight(0), + mSwapInterval(1), + mOrientation(orientation) +{ +} + +DXGISwapChainWindowSurfaceWGL::~DXGISwapChainWindowSurfaceWGL() +{ + if (mRenderbufferBufferHandle != nullptr) + { + mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mRenderbufferBufferHandle); + mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mRenderbufferBufferHandle); + } + + if (mColorRenderbufferID != 0) + { + mStateManager->deleteRenderbuffer(mColorRenderbufferID); + mColorRenderbufferID = 0; + } + + if (mDepthRenderbufferID != 0) + { + mStateManager->deleteRenderbuffer(mDepthRenderbufferID); + mDepthRenderbufferID = 0; + } + + SafeRelease(mSwapChain); + SafeRelease(mSwapChain1); +} + +egl::Error DXGISwapChainWindowSurfaceWGL::initialize() +{ + if (mOrientation != EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE) + { + // TODO(geofflang): Support the orientation extensions fully. Currently only inverting Y is + // supported. To support all orientations, an intermediate framebuffer will be needed with + // a blit before swap. + return egl::Error(EGL_BAD_ATTRIBUTE, + "DXGISwapChainWindowSurfaceWGL requires an orientation of " + "EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE."); + } + + RECT rect; + if (!GetClientRect(mWindow, &rect)) + { + return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to query the window size."); + } + mWidth = rect.right - rect.left; + mHeight = rect.bottom - rect.top; + + mSwapChainFormat = DXGI_FORMAT_R8G8B8A8_UNORM; + mSwapChainFlags = 0; + mDepthBufferFormat = GL_DEPTH24_STENCIL8; + + mFunctionsGL->genFramebuffers(1, &mFramebufferID); + mFunctionsGL->genRenderbuffers(1, &mColorRenderbufferID); + mFunctionsGL->genRenderbuffers(1, &mDepthRenderbufferID); + + return createSwapChain(); +} + +egl::Error DXGISwapChainWindowSurfaceWGL::makeCurrent() +{ + if (!mFunctionsWGL->makeCurrent(mWGLDevice, mWGLContext)) + { + // TODO: What error type here? + return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current."); + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error DXGISwapChainWindowSurfaceWGL::swap() +{ + mFunctionsGL->flush(); + + egl::Error error = setObjectsLocked(false); + if (error.isError()) + { + return error; + } + + HRESULT result = mSwapChain->Present(mSwapInterval, 0); + mFirstSwap = false; + + error = setObjectsLocked(true); + if (error.isError()) + { + return error; + } + + if (FAILED(result)) + { + return egl::Error(EGL_BAD_ALLOC, "Failed to present swap chain, result: 0x%X", result); + } + + return checkForResize(); +} + +egl::Error DXGISwapChainWindowSurfaceWGL::postSubBuffer(EGLint x, + EGLint y, + EGLint width, + EGLint height) +{ + ASSERT(mSwapChain1 != nullptr); + + mFunctionsGL->flush(); + + egl::Error error = setObjectsLocked(false); + if (error.isError()) + { + return error; + } + + HRESULT result = S_OK; + if (mFirstSwap) + { + result = mSwapChain1->Present(mSwapInterval, 0); + mFirstSwap = false; + } + else + { + RECT rect = {static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height), + static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)}; + DXGI_PRESENT_PARAMETERS params = {1, &rect, nullptr, nullptr}; + result = mSwapChain1->Present1(mSwapInterval, 0, ¶ms); + } + + error = setObjectsLocked(true); + if (error.isError()) + { + return error; + } + + if (FAILED(result)) + { + return egl::Error(EGL_BAD_ALLOC, "Failed to present swap chain, result: 0x%X", result); + } + + return checkForResize(); +} + +egl::Error DXGISwapChainWindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value) +{ + UNREACHABLE(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error DXGISwapChainWindowSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer) +{ + ASSERT(mTextureHandle == nullptr); + + const TextureGL *textureGL = GetImplAs<TextureGL>(texture); + GLuint textureID = textureGL->getTextureID(); + + ID3D11Texture2D *colorBuffer = nullptr; + HRESULT result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), + reinterpret_cast<void **>(&colorBuffer)); + if (FAILED(result)) + { + return egl::Error(EGL_BAD_ALLOC, "Failed to query texture from swap chain, result: 0x%X", + result); + } + + mTextureHandle = mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, textureID, + GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV); + SafeRelease(colorBuffer); + if (mTextureHandle == nullptr) + { + return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%08x.", + HRESULT_CODE(GetLastError())); + } + + if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, 1, &mTextureHandle)) + { + mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mTextureHandle); + mTextureHandle = nullptr; + + return egl::Error(EGL_BAD_ALLOC, "Failed to lock D3D object, error: 0x%08x.", + HRESULT_CODE(GetLastError())); + } + + mTextureID = textureID; + + return egl::Error(EGL_SUCCESS); +} + +egl::Error DXGISwapChainWindowSurfaceWGL::releaseTexImage(EGLint buffer) +{ + ASSERT(mTextureHandle != nullptr); + + if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mTextureHandle)) + { + return egl::Error(EGL_BAD_ALLOC, "Failed to unlock D3D object, error: 0x%08x.", + HRESULT_CODE(GetLastError())); + } + + if (!mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mTextureHandle)) + { + return egl::Error(EGL_BAD_ALLOC, "Failed to unregister D3D object, error: 0x%08x.", + HRESULT_CODE(GetLastError())); + } + + mTextureID = 0; + mTextureHandle = nullptr; + + return egl::Error(EGL_SUCCESS); +} + +void DXGISwapChainWindowSurfaceWGL::setSwapInterval(EGLint interval) +{ + mSwapInterval = interval; +} + +EGLint DXGISwapChainWindowSurfaceWGL::getWidth() const +{ + return static_cast<EGLint>(mWidth); +} + +EGLint DXGISwapChainWindowSurfaceWGL::getHeight() const +{ + return static_cast<EGLint>(mHeight); +} + +EGLint DXGISwapChainWindowSurfaceWGL::isPostSubBufferSupported() const +{ + return mSwapChain1 != nullptr; +} + +EGLint DXGISwapChainWindowSurfaceWGL::getSwapBehavior() const +{ + return EGL_BUFFER_DESTROYED; +} + +FramebufferImpl *DXGISwapChainWindowSurfaceWGL::createDefaultFramebuffer( + const gl::FramebufferState &data) +{ + return new FramebufferGL(mFramebufferID, data, mFunctionsGL, mWorkarounds, + mRenderer->getBlitter(), mStateManager); +} + +egl::Error DXGISwapChainWindowSurfaceWGL::setObjectsLocked(bool locked) +{ + if (mRenderbufferBufferHandle == nullptr) + { + ASSERT(mTextureHandle == nullptr); + return egl::Error(EGL_SUCCESS); + } + + HANDLE resources[] = { + mRenderbufferBufferHandle, mTextureHandle, + }; + GLint count = (mTextureHandle != nullptr) ? 2 : 1; + + if (locked) + { + if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, count, resources)) + { + return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.", + HRESULT_CODE(GetLastError())); + } + } + else + { + if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, count, resources)) + { + return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.", + HRESULT_CODE(GetLastError())); + } + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error DXGISwapChainWindowSurfaceWGL::checkForResize() +{ + RECT rect; + if (!GetClientRect(mWindow, &rect)) + { + return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to query the window size."); + } + + size_t newWidth = rect.right - rect.left; + size_t newHeight = rect.bottom - rect.top; + if (newWidth != mWidth || newHeight != mHeight) + { + mWidth = newWidth; + mHeight = newHeight; + + // TODO(geofflang): Handle resize by resizing the swap chain instead of re-creating it. + egl::Error error = createSwapChain(); + if (error.isError()) + { + return error; + } + } + + return egl::Error(EGL_SUCCESS); +} + +static IDXGIFactory *GetDXGIFactoryFromDevice(ID3D11Device *device) +{ + IDXGIDevice *dxgiDevice = nullptr; + HRESULT result = + device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void **>(&dxgiDevice)); + if (FAILED(result)) + { + return nullptr; + } + + IDXGIAdapter *dxgiAdapter = nullptr; + result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void **>(&dxgiAdapter)); + SafeRelease(dxgiDevice); + if (FAILED(result)) + { + return nullptr; + } + + IDXGIFactory *dxgiFactory = nullptr; + result = + dxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void **>(&dxgiFactory)); + SafeRelease(dxgiAdapter); + if (FAILED(result)) + { + return nullptr; + } + + return dxgiFactory; +} + +egl::Error DXGISwapChainWindowSurfaceWGL::createSwapChain() +{ + egl::Error error = setObjectsLocked(false); + if (error.isError()) + { + return error; + } + + if (mRenderbufferBufferHandle) + { + mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mRenderbufferBufferHandle); + mRenderbufferBufferHandle = nullptr; + } + + // If this surface is bound to a texture, unregister it. + bool hadBoundSurface = (mTextureHandle != nullptr); + if (hadBoundSurface) + { + mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mTextureHandle); + mTextureHandle = nullptr; + } + + IDXGIFactory *dxgiFactory = GetDXGIFactoryFromDevice(mDevice); + if (dxgiFactory == nullptr) + { + return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to query the DXGIFactory."); + } + + IDXGIFactory2 *dxgiFactory2 = nullptr; + HRESULT result = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), + reinterpret_cast<void **>(&dxgiFactory2)); + if (SUCCEEDED(result)) + { + ASSERT(dxgiFactory2 != nullptr); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; + swapChainDesc.BufferCount = 1; + swapChainDesc.Format = mSwapChainFormat; + swapChainDesc.Width = static_cast<UINT>(mWidth); + swapChainDesc.Height = static_cast<UINT>(mHeight); + swapChainDesc.Format = mSwapChainFormat; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = + DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.BufferCount = 1; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; + swapChainDesc.Flags = mSwapChainFlags; + + result = dxgiFactory2->CreateSwapChainForHwnd(mDevice, mWindow, &swapChainDesc, nullptr, + nullptr, &mSwapChain1); + SafeRelease(dxgiFactory2); + SafeRelease(dxgiFactory); + if (FAILED(result)) + { + return egl::Error(EGL_BAD_ALLOC, "Failed to create swap chain for window, result: 0x%X", + result); + } + + mSwapChain = mSwapChain1; + mSwapChain->AddRef(); + } + else + { + DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; + swapChainDesc.BufferCount = 1; + swapChainDesc.BufferDesc.Format = mSwapChainFormat; + swapChainDesc.BufferDesc.Width = static_cast<UINT>(mWidth); + swapChainDesc.BufferDesc.Height = static_cast<UINT>(mHeight); + swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; + swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; + swapChainDesc.BufferUsage = + DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.Flags = mSwapChainFlags; + swapChainDesc.OutputWindow = mWindow; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Windowed = TRUE; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + + result = dxgiFactory->CreateSwapChain(mDevice, &swapChainDesc, &mSwapChain); + SafeRelease(dxgiFactory); + if (FAILED(result)) + { + return egl::Error(EGL_BAD_ALLOC, "Failed to create swap chain for window, result: 0x%X", + result); + } + } + + ID3D11Texture2D *colorBuffer = nullptr; + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), + reinterpret_cast<void **>(&colorBuffer)); + if (FAILED(result)) + { + return egl::Error(EGL_BAD_ALLOC, "Failed to query texture from swap chain, result: 0x%X", + result); + } + + mFunctionsGL->genRenderbuffers(1, &mColorRenderbufferID); + mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mColorRenderbufferID); + mRenderbufferBufferHandle = + mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, mColorRenderbufferID, + GL_RENDERBUFFER, WGL_ACCESS_READ_WRITE_NV); + SafeRelease(colorBuffer); + if (mRenderbufferBufferHandle == nullptr) + { + return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%X.", + HRESULT_CODE(GetLastError())); + } + + // Rebind the surface to the texture if needed. + if (hadBoundSurface) + { + mTextureHandle = mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, mTextureID, + GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV); + if (mTextureHandle == nullptr) + { + return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%X.", + HRESULT_CODE(GetLastError())); + } + } + + error = setObjectsLocked(true); + if (error.isError()) + { + return error; + } + + ASSERT(mFramebufferID != 0); + mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID); + mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, + mColorRenderbufferID); + + if (mDepthBufferFormat != GL_NONE) + { + ASSERT(mDepthRenderbufferID != 0); + mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDepthRenderbufferID); + mFunctionsGL->renderbufferStorage(GL_RENDERBUFFER, mDepthBufferFormat, + static_cast<GLsizei>(mWidth), + static_cast<GLsizei>(mHeight)); + + const gl::InternalFormat &depthStencilFormatInfo = + gl::GetInternalFormatInfo(mDepthBufferFormat); + if (depthStencilFormatInfo.depthBits > 0) + { + mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, mDepthRenderbufferID); + } + if (depthStencilFormatInfo.stencilBits > 0) + { + mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, mDepthRenderbufferID); + } + } + + mFirstSwap = true; + + return egl::Error(EGL_SUCCESS); +} +} // namespace rx diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h new file mode 100755 index 000000000..f516239c9 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h @@ -0,0 +1,106 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DXGISwapChainWindowSurfaceWGL.h: WGL implementation of egl::Surface for windows using a DXGI +// swapchain. + +#ifndef LIBANGLE_RENDERER_GL_WGL_DXGISWAPCHAINSURFACEWGL_H_ +#define LIBANGLE_RENDERER_GL_WGL_DXGISWAPCHAINSURFACEWGL_H_ + +#include "libANGLE/renderer/gl/SurfaceGL.h" + +#include <GL/wglext.h> + +namespace rx +{ + +class FunctionsGL; +class FunctionsWGL; +class DisplayWGL; +class StateManagerGL; +struct WorkaroundsGL; + +class DXGISwapChainWindowSurfaceWGL : public SurfaceGL +{ + public: + DXGISwapChainWindowSurfaceWGL(const egl::SurfaceState &state, + RendererGL *renderer, + EGLNativeWindowType window, + ID3D11Device *device, + HANDLE deviceHandle, + HGLRC wglContext, + HDC deviceContext, + const FunctionsGL *functionsGL, + const FunctionsWGL *functionsWGL, + EGLint orientation); + ~DXGISwapChainWindowSurfaceWGL() override; + + egl::Error initialize() override; + egl::Error makeCurrent() override; + + egl::Error swap() override; + egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; + egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; + egl::Error releaseTexImage(EGLint buffer) override; + void setSwapInterval(EGLint interval) override; + + EGLint getWidth() const override; + EGLint getHeight() const override; + + EGLint isPostSubBufferSupported() const override; + EGLint getSwapBehavior() const override; + + FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override; + + private: + egl::Error setObjectsLocked(bool locked); + egl::Error checkForResize(); + + egl::Error createSwapChain(); + + EGLNativeWindowType mWindow; + + StateManagerGL *mStateManager; + const WorkaroundsGL &mWorkarounds; + RendererGL *mRenderer; + const FunctionsGL *mFunctionsGL; + const FunctionsWGL *mFunctionsWGL; + + ID3D11Device *mDevice; + HANDLE mDeviceHandle; + + HDC mWGLDevice; + HGLRC mWGLContext; + + DXGI_FORMAT mSwapChainFormat; + UINT mSwapChainFlags; + GLenum mDepthBufferFormat; + + bool mFirstSwap; + IDXGISwapChain *mSwapChain; + IDXGISwapChain1 *mSwapChain1; + + GLuint mColorRenderbufferID; + HANDLE mRenderbufferBufferHandle; + + GLuint mDepthRenderbufferID; + + GLuint mFramebufferID; + + GLuint mTextureID; + HANDLE mTextureHandle; + + size_t mWidth; + size_t mHeight; + + EGLint mSwapInterval; + + EGLint mOrientation; +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_GL_WGL_DXGISWAPCHAINSURFACEWGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp new file mode 100755 index 000000000..188321115 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp @@ -0,0 +1,741 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayWGL.h: WGL implementation of egl::Display + +#include "libANGLE/renderer/gl/wgl/DisplayWGL.h" + +#include "common/debug.h" +#include "libANGLE/Config.h" +#include "libANGLE/Display.h" +#include "libANGLE/Surface.h" +#include "libANGLE/renderer/gl/RendererGL.h" +#include "libANGLE/renderer/gl/renderergl_utils.h" +#include "libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h" +#include "libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h" +#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h" +#include "libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h" +#include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h" +#include "libANGLE/renderer/gl/wgl/wgl_utils.h" + +#include "platform/Platform.h" + +#include <EGL/eglext.h> +#include <string> +#include <sstream> + +namespace rx +{ + +class FunctionsGLWindows : public FunctionsGL +{ + public: + FunctionsGLWindows(HMODULE openGLModule, PFNWGLGETPROCADDRESSPROC getProcAddressWGL) + : mOpenGLModule(openGLModule), + mGetProcAddressWGL(getProcAddressWGL) + { + ASSERT(mOpenGLModule); + ASSERT(mGetProcAddressWGL); + } + + ~FunctionsGLWindows() override {} + + private: + void *loadProcAddress(const std::string &function) override + { + void *proc = reinterpret_cast<void*>(mGetProcAddressWGL(function.c_str())); + if (!proc) + { + proc = reinterpret_cast<void*>(GetProcAddress(mOpenGLModule, function.c_str())); + } + return proc; + } + + HMODULE mOpenGLModule; + PFNWGLGETPROCADDRESSPROC mGetProcAddressWGL; +}; + +DisplayWGL::DisplayWGL() + : DisplayGL(), + mOpenGLModule(nullptr), + mFunctionsWGL(nullptr), + mFunctionsGL(nullptr), + mHasRobustness(false), + mWindowClass(0), + mWindow(nullptr), + mDeviceContext(nullptr), + mPixelFormat(0), + mWGLContext(nullptr), + mUseDXGISwapChains(false), + mDxgiModule(nullptr), + mD3d11Module(nullptr), + mD3D11DeviceHandle(nullptr), + mD3D11Device(nullptr), + mDisplay(nullptr) +{ +} + +DisplayWGL::~DisplayWGL() +{ +} + +egl::Error DisplayWGL::initialize(egl::Display *display) +{ + mDisplay = display; + + mOpenGLModule = LoadLibraryA("opengl32.dll"); + if (!mOpenGLModule) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to load OpenGL library."); + } + + mFunctionsWGL = new FunctionsWGL(); + mFunctionsWGL->initialize(mOpenGLModule, nullptr); + + // WGL can't grab extensions until it creates a context because it needs to load the driver's DLLs first. + // Create a dummy context to load the driver and determine which GL versions are available. + + // Work around compile error from not defining "UNICODE" while Chromium does + const LPSTR idcArrow = MAKEINTRESOURCEA(32512); + + std::string className = FormatString("ANGLE DisplayWGL 0x%0.8p Intermediate Window Class", mDisplay); + + WNDCLASSA intermediateClassDesc = { 0 }; + intermediateClassDesc.style = CS_OWNDC; + intermediateClassDesc.lpfnWndProc = DefWindowProc; + intermediateClassDesc.cbClsExtra = 0; + intermediateClassDesc.cbWndExtra = 0; + intermediateClassDesc.hInstance = GetModuleHandle(nullptr); + intermediateClassDesc.hIcon = nullptr; + intermediateClassDesc.hCursor = LoadCursorA(nullptr, idcArrow); + intermediateClassDesc.hbrBackground = 0; + intermediateClassDesc.lpszMenuName = nullptr; + intermediateClassDesc.lpszClassName = className.c_str(); + mWindowClass = RegisterClassA(&intermediateClassDesc); + if (!mWindowClass) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to register intermediate OpenGL window class."); + } + + HWND dummyWindow = CreateWindowExA(0, + reinterpret_cast<const char *>(mWindowClass), + "ANGLE Dummy Window", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + nullptr, + nullptr, + nullptr, + nullptr); + if (!dummyWindow) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to create dummy OpenGL window."); + } + + HDC dummyDeviceContext = GetDC(dummyWindow); + if (!dummyDeviceContext) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to get the device context of the dummy OpenGL window."); + } + + const PIXELFORMATDESCRIPTOR pixelFormatDescriptor = wgl::GetDefaultPixelFormatDescriptor(); + + int dummyPixelFormat = ChoosePixelFormat(dummyDeviceContext, &pixelFormatDescriptor); + if (dummyPixelFormat == 0) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not find a compatible pixel format for the dummy OpenGL window."); + } + + if (!SetPixelFormat(dummyDeviceContext, dummyPixelFormat, &pixelFormatDescriptor)) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to set the pixel format on the intermediate OpenGL window."); + } + + HGLRC dummyWGLContext = mFunctionsWGL->createContext(dummyDeviceContext); + if (!dummyDeviceContext) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to create a WGL context for the dummy OpenGL window."); + } + + if (!mFunctionsWGL->makeCurrent(dummyDeviceContext, dummyWGLContext)) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to make the dummy WGL context current."); + } + + // Grab the GL version from this context and use it as the maximum version available. + typedef const GLubyte* (GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name); + PFNGLGETSTRINGPROC getString = reinterpret_cast<PFNGLGETSTRINGPROC>(GetProcAddress(mOpenGLModule, "glGetString")); + if (!getString) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to get glGetString pointer."); + } + + // Reinitialize the wgl functions to grab the extensions + mFunctionsWGL->initialize(mOpenGLModule, dummyDeviceContext); + + bool hasWGLCreateContextRobustness = + mFunctionsWGL->hasExtension("WGL_ARB_create_context_robustness"); + + // Destroy the dummy window and context + mFunctionsWGL->makeCurrent(dummyDeviceContext, nullptr); + mFunctionsWGL->deleteContext(dummyWGLContext); + ReleaseDC(dummyWindow, dummyDeviceContext); + DestroyWindow(dummyWindow); + + const egl::AttributeMap &displayAttributes = display->getAttributeMap(); + EGLint requestedDisplayType = static_cast<EGLint>(displayAttributes.get( + EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)); + if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE && + !mFunctionsWGL->hasExtension("WGL_EXT_create_context_es2_profile") && + !mFunctionsWGL->hasExtension("WGL_EXT_create_context_es_profile")) + { + return egl::Error(EGL_NOT_INITIALIZED, + "Cannot create an OpenGL ES platform on Windows without " + "the WGL_EXT_create_context_es(2)_profile extension."); + } + + // Create the real intermediate context and windows + mWindow = CreateWindowExA(0, + reinterpret_cast<const char *>(mWindowClass), + "ANGLE Intermediate Window", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + nullptr, + nullptr, + nullptr, + nullptr); + if (!mWindow) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to create intermediate OpenGL window."); + } + + mDeviceContext = GetDC(mWindow); + if (!mDeviceContext) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to get the device context of the intermediate OpenGL window."); + } + + if (mFunctionsWGL->choosePixelFormatARB) + { + std::vector<int> attribs = wgl::GetDefaultPixelFormatAttributes(false); + + UINT matchingFormats = 0; + mFunctionsWGL->choosePixelFormatARB(mDeviceContext, &attribs[0], nullptr, 1u, &mPixelFormat, + &matchingFormats); + } + + if (mPixelFormat == 0) + { + mPixelFormat = ChoosePixelFormat(mDeviceContext, &pixelFormatDescriptor); + } + + if (mPixelFormat == 0) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not find a compatible pixel format for the intermediate OpenGL window."); + } + + if (!SetPixelFormat(mDeviceContext, mPixelFormat, &pixelFormatDescriptor)) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to set the pixel format on the intermediate OpenGL window."); + } + + if (mFunctionsWGL->createContextAttribsARB) + { + int flags = 0; + // TODO: allow debug contexts + // TODO: handle robustness + + int mask = 0; + + if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE) + { + mask |= WGL_CONTEXT_ES_PROFILE_BIT_EXT; + } + else + { + // Request core profile + mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB; + } + + std::vector<int> contextCreationAttributes; + + if (hasWGLCreateContextRobustness) + { + contextCreationAttributes.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB); + contextCreationAttributes.push_back(WGL_LOSE_CONTEXT_ON_RESET_ARB); + } + + // Don't request a specific version unless the user wants one. WGL will return the highest version + // that the driver supports if no version is requested. + EGLint requestedMajorVersion = static_cast<EGLint>( + displayAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE)); + EGLint requestedMinorVersion = static_cast<EGLint>( + displayAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE)); + if (requestedMajorVersion != EGL_DONT_CARE && requestedMinorVersion != EGL_DONT_CARE) + { + contextCreationAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB); + contextCreationAttributes.push_back(requestedMajorVersion); + + contextCreationAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB); + contextCreationAttributes.push_back(requestedMinorVersion); + } + else + { + // the ES profile will give us ES version 1.1 unless a higher version is requested. + // Requesting version 2.0 will give us the highest compatible version available (2.0, + // 3.0, 3.1, etc). + if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE) + { + contextCreationAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB); + contextCreationAttributes.push_back(2); + + contextCreationAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB); + contextCreationAttributes.push_back(0); + } + } + + // Set the flag attributes + if (flags != 0) + { + contextCreationAttributes.push_back(WGL_CONTEXT_FLAGS_ARB); + contextCreationAttributes.push_back(flags); + } + + // Set the mask attribute + if (mask != 0) + { + contextCreationAttributes.push_back(WGL_CONTEXT_PROFILE_MASK_ARB); + contextCreationAttributes.push_back(mask); + } + + // Signal the end of the attributes + contextCreationAttributes.push_back(0); + contextCreationAttributes.push_back(0); + + mWGLContext = mFunctionsWGL->createContextAttribsARB(mDeviceContext, NULL, &contextCreationAttributes[0]); + } + + // If wglCreateContextAttribsARB is unavailable or failed, try the standard wglCreateContext + if (!mWGLContext) + { + // Don't have control over GL versions + mWGLContext = mFunctionsWGL->createContext(mDeviceContext); + } + + if (!mWGLContext) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to create a WGL context for the intermediate OpenGL window."); + } + + if (!mFunctionsWGL->makeCurrent(mDeviceContext, mWGLContext)) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to make the intermediate WGL context current."); + } + + mFunctionsGL = new FunctionsGLWindows(mOpenGLModule, mFunctionsWGL->getProcAddress); + mFunctionsGL->initialize(); + + mHasRobustness = mFunctionsGL->getGraphicsResetStatus != nullptr; + if (hasWGLCreateContextRobustness != mHasRobustness) + { + ANGLEPlatformCurrent()->logWarning( + "WGL_ARB_create_context_robustness exists but unable to OpenGL context with " + "robustness."); + } + + // Intel OpenGL ES drivers are not currently supported due to bugs in the driver and ANGLE + VendorID vendor = GetVendorID(mFunctionsGL); + if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE && IsIntel(vendor)) + { + return egl::Error(EGL_NOT_INITIALIZED, "Intel OpenGL ES drivers are not supported."); + } + + // Create DXGI swap chains for windows that come from other processes. Windows is unable to + // SetPixelFormat on windows from other processes when a sandbox is enabled. + HDC nativeDisplay = display->getNativeDisplayId(); + HWND nativeWindow = WindowFromDC(nativeDisplay); + if (nativeWindow != nullptr) + { + DWORD currentProcessId = GetCurrentProcessId(); + DWORD windowProcessId; + GetWindowThreadProcessId(nativeWindow, &windowProcessId); + + // AMD drivers advertise the WGL_NV_DX_interop and WGL_NV_DX_interop2 extensions but fail + mUseDXGISwapChains = !IsAMD(vendor) && (currentProcessId != windowProcessId); + } + else + { + mUseDXGISwapChains = false; + } + + if (mUseDXGISwapChains) + { + egl::Error error = initializeD3DDevice(); + if (error.isError()) + { + return error; + } + } + + return DisplayGL::initialize(display); +} + +void DisplayWGL::terminate() +{ + DisplayGL::terminate(); + + releaseD3DDevice(mD3D11DeviceHandle); + + mFunctionsWGL->makeCurrent(mDeviceContext, NULL); + mFunctionsWGL->deleteContext(mWGLContext); + mWGLContext = NULL; + + ReleaseDC(mWindow, mDeviceContext); + mDeviceContext = NULL; + + DestroyWindow(mWindow); + mWindow = NULL; + + UnregisterClassA(reinterpret_cast<const char*>(mWindowClass), NULL); + mWindowClass = NULL; + + SafeDelete(mFunctionsWGL); + SafeDelete(mFunctionsGL); + + FreeLibrary(mOpenGLModule); + mOpenGLModule = nullptr; + + SafeRelease(mD3D11Device); + + if (mDxgiModule) + { + FreeLibrary(mDxgiModule); + mDxgiModule = nullptr; + } + + if (mD3d11Module) + { + FreeLibrary(mD3d11Module); + mD3d11Module = nullptr; + } + + ASSERT(mRegisteredD3DDevices.empty()); +} + +SurfaceImpl *DisplayWGL::createWindowSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) +{ + EGLint orientation = static_cast<EGLint>(attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0)); + if (mUseDXGISwapChains) + { + return new DXGISwapChainWindowSurfaceWGL(state, getRenderer(), window, mD3D11Device, + mD3D11DeviceHandle, mWGLContext, mDeviceContext, + mFunctionsGL, mFunctionsWGL, orientation); + } + else + { + return new WindowSurfaceWGL(state, getRenderer(), window, mPixelFormat, mWGLContext, + mFunctionsWGL, orientation); + } +} + +SurfaceImpl *DisplayWGL::createPbufferSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + const egl::AttributeMap &attribs) +{ + EGLint width = static_cast<EGLint>(attribs.get(EGL_WIDTH, 0)); + EGLint height = static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0)); + bool largest = (attribs.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE); + EGLenum textureFormat = static_cast<EGLenum>(attribs.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE)); + EGLenum textureTarget = static_cast<EGLenum>(attribs.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE)); + + return new PbufferSurfaceWGL(state, getRenderer(), width, height, textureFormat, textureTarget, + largest, mPixelFormat, mDeviceContext, mWGLContext, mFunctionsWGL); +} + +SurfaceImpl *DisplayWGL::createPbufferFromClientBuffer(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) +{ + ASSERT(buftype == EGL_D3D_TEXTURE_ANGLE); + return new D3DTextureSurfaceWGL(state, getRenderer(), clientBuffer, this, mWGLContext, + mDeviceContext, mFunctionsGL, mFunctionsWGL); +} + +SurfaceImpl *DisplayWGL::createPixmapSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) +{ + UNIMPLEMENTED(); + return nullptr; +} + +egl::Error DisplayWGL::getDevice(DeviceImpl **device) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_BAD_DISPLAY); +} + +egl::ConfigSet DisplayWGL::generateConfigs() +{ + egl::ConfigSet configs; + + int minSwapInterval = 1; + int maxSwapInterval = 1; + if (mFunctionsWGL->swapIntervalEXT) + { + // No defined maximum swap interval in WGL_EXT_swap_control, use a reasonable number + minSwapInterval = 0; + maxSwapInterval = 8; + } + + const gl::Version &maxVersion = getMaxSupportedESVersion(); + ASSERT(maxVersion >= gl::Version(2, 0)); + bool supportsES3 = maxVersion >= gl::Version(3, 0); + + PIXELFORMATDESCRIPTOR pixelFormatDescriptor; + DescribePixelFormat(mDeviceContext, mPixelFormat, sizeof(pixelFormatDescriptor), &pixelFormatDescriptor); + + auto getAttrib = [this](int attrib) + { + return wgl::QueryWGLFormatAttrib(mDeviceContext, mPixelFormat, attrib, mFunctionsWGL); + }; + + const EGLint optimalSurfaceOrientation = + mUseDXGISwapChains ? EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE : 0; + + egl::Config config; + config.renderTargetFormat = GL_RGBA8; // TODO: use the bit counts to determine the format + config.depthStencilFormat = GL_DEPTH24_STENCIL8; // TODO: use the bit counts to determine the format + config.bufferSize = pixelFormatDescriptor.cColorBits; + config.redSize = pixelFormatDescriptor.cRedBits; + config.greenSize = pixelFormatDescriptor.cGreenBits; + config.blueSize = pixelFormatDescriptor.cBlueBits; + config.luminanceSize = 0; + config.alphaSize = pixelFormatDescriptor.cAlphaBits; + config.alphaMaskSize = 0; + config.bindToTextureRGB = (getAttrib(WGL_BIND_TO_TEXTURE_RGB_ARB) == TRUE); + config.bindToTextureRGBA = (getAttrib(WGL_BIND_TO_TEXTURE_RGBA_ARB) == TRUE); + config.colorBufferType = EGL_RGB_BUFFER; + config.configCaveat = EGL_NONE; + config.conformant = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0); + config.depthSize = pixelFormatDescriptor.cDepthBits; + config.level = 0; + config.matchNativePixmap = EGL_NONE; + config.maxPBufferWidth = getAttrib(WGL_MAX_PBUFFER_WIDTH_ARB); + config.maxPBufferHeight = getAttrib(WGL_MAX_PBUFFER_HEIGHT_ARB); + config.maxPBufferPixels = getAttrib(WGL_MAX_PBUFFER_PIXELS_ARB); + config.maxSwapInterval = maxSwapInterval; + config.minSwapInterval = minSwapInterval; + config.nativeRenderable = EGL_TRUE; // Direct rendering + config.nativeVisualID = 0; + config.nativeVisualType = EGL_NONE; + config.renderableType = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0); + config.sampleBuffers = 0; // FIXME: enumerate multi-sampling + config.samples = 0; + config.stencilSize = pixelFormatDescriptor.cStencilBits; + config.surfaceType = + ((pixelFormatDescriptor.dwFlags & PFD_DRAW_TO_WINDOW) ? EGL_WINDOW_BIT : 0) | + ((getAttrib(WGL_DRAW_TO_PBUFFER_ARB) == TRUE) ? EGL_PBUFFER_BIT : 0) | + ((getAttrib(WGL_SWAP_METHOD_ARB) == WGL_SWAP_COPY_ARB) ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT + : 0); + config.optimalOrientation = optimalSurfaceOrientation; + + config.transparentType = EGL_NONE; + config.transparentRedValue = 0; + config.transparentGreenValue = 0; + config.transparentBlueValue = 0; + + configs.add(config); + + return configs; +} + +bool DisplayWGL::testDeviceLost() +{ + if (mHasRobustness) + { + return getRenderer()->getResetStatus() != GL_NO_ERROR; + } + + return false; +} + +egl::Error DisplayWGL::restoreLostDevice() +{ + return egl::Error(EGL_BAD_DISPLAY); +} + +bool DisplayWGL::isValidNativeWindow(EGLNativeWindowType window) const +{ + return (IsWindow(window) == TRUE); +} + +egl::Error DisplayWGL::validateClientBuffer(const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) const +{ + switch (buftype) + { + case EGL_D3D_TEXTURE_ANGLE: + return D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(clientBuffer); + + default: + return DisplayGL::validateClientBuffer(configuration, buftype, clientBuffer, attribs); + } +} + +std::string DisplayWGL::getVendorString() const +{ + //UNIMPLEMENTED(); + return ""; +} + +const FunctionsGL *DisplayWGL::getFunctionsGL() const +{ + return mFunctionsGL; +} + +egl::Error DisplayWGL::initializeD3DDevice() +{ + if (mD3D11Device != nullptr) + { + return egl::Error(EGL_SUCCESS); + } + + mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); + if (!mDxgiModule) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to load DXGI library."); + } + + mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); + if (!mD3d11Module) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to load d3d11 library."); + } + + PFN_D3D11_CREATE_DEVICE d3d11CreateDevice = nullptr; + d3d11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>( + GetProcAddress(mD3d11Module, "D3D11CreateDevice")); + if (d3d11CreateDevice == nullptr) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not retrieve D3D11CreateDevice address."); + } + + HRESULT result = d3d11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0, + D3D11_SDK_VERSION, &mD3D11Device, nullptr, nullptr); + if (FAILED(result)) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not create D3D11 device, error: 0x%X", + result); + } + + egl::Error error = registerD3DDevice(mD3D11Device, &mD3D11DeviceHandle); + if (error.isError()) + { + return error; + } + + return egl::Error(EGL_SUCCESS); +} + +void DisplayWGL::generateExtensions(egl::DisplayExtensions *outExtensions) const +{ + // Only enable the surface orientation and post sub buffer for DXGI swap chain surfaces, they + // prefer to swap with inverted Y. + outExtensions->postSubBuffer = mUseDXGISwapChains; + outExtensions->surfaceOrientation = mUseDXGISwapChains; + + outExtensions->createContextRobustness = mHasRobustness; + + outExtensions->d3dTextureClientBuffer = mFunctionsWGL->hasExtension("WGL_NV_DX_interop2"); +} + +void DisplayWGL::generateCaps(egl::Caps *outCaps) const +{ + outCaps->textureNPOT = true; +} + +egl::Error DisplayWGL::waitClient() const +{ + // Unimplemented as this is not needed for WGL + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayWGL::waitNative(EGLint engine, + egl::Surface *drawSurface, + egl::Surface *readSurface) const +{ + // Unimplemented as this is not needed for WGL + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayWGL::getDriverVersion(std::string *version) const +{ + *version = ""; + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayWGL::registerD3DDevice(IUnknown *device, HANDLE *outHandle) +{ + ASSERT(device != nullptr); + ASSERT(outHandle != nullptr); + + auto iter = mRegisteredD3DDevices.find(device); + if (iter != mRegisteredD3DDevices.end()) + { + iter->second.refCount++; + *outHandle = iter->second.handle; + return egl::Error(EGL_SUCCESS); + } + + HANDLE handle = mFunctionsWGL->dxOpenDeviceNV(device); + if (!handle) + { + return egl::Error(EGL_BAD_PARAMETER, "Failed to open D3D device."); + } + + device->AddRef(); + + D3DObjectHandle newDeviceInfo; + newDeviceInfo.handle = handle; + newDeviceInfo.refCount = 1; + mRegisteredD3DDevices[device] = newDeviceInfo; + + *outHandle = handle; + return egl::Error(EGL_SUCCESS); +} + +void DisplayWGL::releaseD3DDevice(HANDLE deviceHandle) +{ + for (auto iter = mRegisteredD3DDevices.begin(); iter != mRegisteredD3DDevices.end(); iter++) + { + if (iter->second.handle == deviceHandle) + { + iter->second.refCount--; + if (iter->second.refCount == 0) + { + mFunctionsWGL->dxCloseDeviceNV(iter->second.handle); + iter->first->Release(); + mRegisteredD3DDevices.erase(iter); + break; + } + } + } +} +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.h new file mode 100755 index 000000000..509ea9b39 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.h @@ -0,0 +1,112 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayWGL.h: WGL implementation of egl::Display + +#ifndef LIBANGLE_RENDERER_GL_WGL_DISPLAYWGL_H_ +#define LIBANGLE_RENDERER_GL_WGL_DISPLAYWGL_H_ + +#include "libANGLE/renderer/gl/DisplayGL.h" + +#include <GL/wglext.h> + +namespace rx +{ + +class FunctionsWGL; + +class DisplayWGL : public DisplayGL +{ + public: + DisplayWGL(); + ~DisplayWGL() override; + + egl::Error initialize(egl::Display *display) override; + void terminate() override; + + // Surface creation + SurfaceImpl *createWindowSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) override; + + egl::ConfigSet generateConfigs() override; + + bool testDeviceLost() override; + egl::Error restoreLostDevice() override; + + bool isValidNativeWindow(EGLNativeWindowType window) const override; + egl::Error validateClientBuffer(const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) const override; + + egl::Error getDevice(DeviceImpl **device) override; + + std::string getVendorString() const override; + + egl::Error waitClient() const override; + egl::Error waitNative(EGLint engine, + egl::Surface *drawSurface, + egl::Surface *readSurface) const override; + + egl::Error getDriverVersion(std::string *version) const override; + + egl::Error registerD3DDevice(IUnknown *device, HANDLE *outHandle); + void releaseD3DDevice(HANDLE handle); + + private: + const FunctionsGL *getFunctionsGL() const override; + + egl::Error initializeD3DDevice(); + + void generateExtensions(egl::DisplayExtensions *outExtensions) const override; + void generateCaps(egl::Caps *outCaps) const override; + + HMODULE mOpenGLModule; + + FunctionsWGL *mFunctionsWGL; + FunctionsGL *mFunctionsGL; + + bool mHasRobustness; + + ATOM mWindowClass; + HWND mWindow; + HDC mDeviceContext; + int mPixelFormat; + HGLRC mWGLContext; + + bool mUseDXGISwapChains; + HMODULE mDxgiModule; + HMODULE mD3d11Module; + HANDLE mD3D11DeviceHandle; + ID3D11Device *mD3D11Device; + + struct D3DObjectHandle + { + HANDLE handle; + size_t refCount; + }; + std::map<IUnknown *, D3DObjectHandle> mRegisteredD3DDevices; + + egl::Display *mDisplay; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_WGL_DISPLAYWGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp new file mode 100755 index 000000000..2cfe6e9eb --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp @@ -0,0 +1,181 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FunctionsWGL.h: Implements the FuntionsWGL class. + +#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h" + +#include <algorithm> + +#include "common/string_utils.h" + +namespace rx +{ + +template <typename T> +static void GetWGLProcAddress(HMODULE glModule, PFNWGLGETPROCADDRESSPROC getProcAddressWGL, + const std::string &procName, T *outProcAddress) +{ + T proc = nullptr; + if (getProcAddressWGL) + { + proc = reinterpret_cast<T>(getProcAddressWGL(procName.c_str())); + } + + if (!proc) + { + proc = reinterpret_cast<T>(GetProcAddress(glModule, procName.c_str())); + } + + *outProcAddress = proc; +} + +template <typename T> +static void GetWGLExtensionProcAddress(HMODULE glModule, + PFNWGLGETPROCADDRESSPROC getProcAddressWGL, + const std::vector<std::string> &extensions, + const std::string &extensionName, + const std::string &procName, + T *outProcAddress) +{ + T proc = nullptr; + if (std::find(extensions.begin(), extensions.end(), extensionName) != extensions.end()) + { + GetWGLProcAddress(glModule, getProcAddressWGL, procName, &proc); + } + + *outProcAddress = proc; +} + +FunctionsWGL::FunctionsWGL() + : copyContext(nullptr), + createContext(nullptr), + createLayerContext(nullptr), + deleteContext(nullptr), + getCurrentContext(nullptr), + getCurrentDC(nullptr), + getProcAddress(nullptr), + makeCurrent(nullptr), + shareLists(nullptr), + useFontBitmapsA(nullptr), + useFontBitmapsW(nullptr), + swapBuffers(nullptr), + useFontOutlinesA(nullptr), + useFontOutlinesW(nullptr), + describeLayerPlane(nullptr), + setLayerPaletteEntries(nullptr), + getLayerPaletteEntries(nullptr), + realizeLayerPalette(nullptr), + swapLayerBuffers(nullptr), + swapMultipleBuffers(nullptr), + getExtensionStringEXT(nullptr), + getExtensionStringARB(nullptr), + createContextAttribsARB(nullptr), + getPixelFormatAttribivARB(nullptr), + getPixelFormatAttribfvARB(nullptr), + choosePixelFormatARB(nullptr), + swapIntervalEXT(nullptr), + createPbufferARB(nullptr), + getPbufferDCARB(nullptr), + releasePbufferDCARB(nullptr), + destroyPbufferARB(nullptr), + queryPbufferARB(nullptr), + bindTexImageARB(nullptr), + releaseTexImageARB(nullptr), + setPbufferAttribARB(nullptr), + dxSetResourceShareHandleNV(nullptr), + dxOpenDeviceNV(nullptr), + dxCloseDeviceNV(nullptr), + dxRegisterObjectNV(nullptr), + dxUnregisterObjectNV(nullptr), + dxObjectAccessNV(nullptr), + dxLockObjectsNV(nullptr), + dxUnlockObjectsNV(nullptr) +{ +} + +void FunctionsWGL::initialize(HMODULE glModule, HDC context) +{ + // First grab the wglGetProcAddress function from the gl module + GetWGLProcAddress(glModule, nullptr, "wglGetProcAddress", &getProcAddress); + + // Load the core wgl functions + GetWGLProcAddress(glModule, getProcAddress, "wglCopyContext", ©Context); + GetWGLProcAddress(glModule, getProcAddress, "wglCreateContext", &createContext); + GetWGLProcAddress(glModule, getProcAddress, "wglCreateLayerContext", &createLayerContext); + GetWGLProcAddress(glModule, getProcAddress, "wglDeleteContext", &deleteContext); + GetWGLProcAddress(glModule, getProcAddress, "wglGetCurrentContext", &getCurrentContext); + GetWGLProcAddress(glModule, getProcAddress, "wglGetCurrentDC", &getCurrentDC); + GetWGLProcAddress(glModule, getProcAddress, "wglMakeCurrent", &makeCurrent); + GetWGLProcAddress(glModule, getProcAddress, "wglShareLists", &shareLists); + GetWGLProcAddress(glModule, getProcAddress, "wglUseFontBitmapsA", &useFontBitmapsA); + GetWGLProcAddress(glModule, getProcAddress, "wglUseFontBitmapsW", &useFontBitmapsW); + swapBuffers = SwapBuffers; // SwapBuffers is statically linked from GDI + GetWGLProcAddress(glModule, getProcAddress, "wglUseFontOutlinesA", &useFontOutlinesA); + GetWGLProcAddress(glModule, getProcAddress, "wglUseFontOutlinesW", &useFontOutlinesW); + GetWGLProcAddress(glModule, getProcAddress, "wglDescribeLayerPlane", &describeLayerPlane); + GetWGLProcAddress(glModule, getProcAddress, "wglSetLayerPaletteEntries", &setLayerPaletteEntries); + GetWGLProcAddress(glModule, getProcAddress, "wglGetLayerPaletteEntries", &getLayerPaletteEntries); + GetWGLProcAddress(glModule, getProcAddress, "wglRealizeLayerPalette", &realizeLayerPalette); + GetWGLProcAddress(glModule, getProcAddress, "wglSwapLayerBuffers", &swapLayerBuffers); + GetWGLProcAddress(glModule, getProcAddress, "wglSwapMultipleBuffers", &swapMultipleBuffers); + + // Load extension string getter functions + GetWGLProcAddress(glModule, getProcAddress, "wglGetExtensionsStringEXT", &getExtensionStringEXT); + GetWGLProcAddress(glModule, getProcAddress, "wglGetExtensionsStringARB", &getExtensionStringARB); + + std::string extensionString = ""; + if (getExtensionStringEXT) + { + extensionString = getExtensionStringEXT(); + } + else if (getExtensionStringARB && context) + { + extensionString = getExtensionStringARB(context); + } + angle::SplitStringAlongWhitespace(extensionString, &extensions); + + // Load the wgl extension functions by checking if the context supports the extension first + + // WGL_ARB_create_context + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_create_context", "wglCreateContextAttribsARB", &createContextAttribsARB); + + // WGL_ARB_pixel_format + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pixel_format", "wglGetPixelFormatAttribivARB", &getPixelFormatAttribivARB); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pixel_format", "wglGetPixelFormatAttribfvARB", &getPixelFormatAttribfvARB); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pixel_format", "wglChoosePixelFormatARB", &choosePixelFormatARB); + + // WGL_EXT_swap_control + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_EXT_swap_control", "wglSwapIntervalEXT", &swapIntervalEXT); + + // WGL_ARB_pbuffer + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglCreatePbufferARB", &createPbufferARB); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglGetPbufferDCARB", &getPbufferDCARB); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglReleasePbufferDCARB", &releasePbufferDCARB); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglDestroyPbufferARB", &destroyPbufferARB); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglQueryPbufferARB", &queryPbufferARB); + + // WGL_ARB_render_texture + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglBindTexImageARB", &bindTexImageARB); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglReleaseTexImageARB", &releaseTexImageARB); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglSetPbufferAttribARB", &setPbufferAttribARB); + + // WGL_NV_DX_interop + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXSetResourceShareHandleNV", &dxSetResourceShareHandleNV); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXOpenDeviceNV", &dxOpenDeviceNV); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXCloseDeviceNV", &dxCloseDeviceNV); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXRegisterObjectNV", &dxRegisterObjectNV); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXUnregisterObjectNV", &dxUnregisterObjectNV); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXObjectAccessNV", &dxObjectAccessNV); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXLockObjectsNV", &dxLockObjectsNV); + GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXUnlockObjectsNV", &dxUnlockObjectsNV); +} + +bool FunctionsWGL::hasExtension(const std::string &ext) const +{ + return std::find(extensions.begin(), extensions.end(), ext) != extensions.end(); +} +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h new file mode 100755 index 000000000..30cf9ebc0 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h @@ -0,0 +1,94 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FunctionsWGL.h: Defines the FuntionsWGL class to contain loaded WGL functions + +#ifndef LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL +#define LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL + +#include "common/angleutils.h" +#include "libANGLE/renderer/gl/wgl/functionswgl_typedefs.h" + +namespace rx +{ + +class FunctionsWGL : angle::NonCopyable +{ + public: + FunctionsWGL(); + + // Loads all available wgl functions, may be called multiple times + void initialize(HMODULE glModule, HDC context); + + // Extension information + std::vector<std::string> extensions; + bool hasExtension(const std::string &ext) const; + + // Base WGL functions + PFNWGLCOPYCONTEXTPROC copyContext; + PFNWGLCREATECONTEXTPROC createContext; + PFNWGLCREATELAYERCONTEXTPROC createLayerContext; + PFNWGLDELETECONTEXTPROC deleteContext; + PFNWGLGETCURRENTCONTEXTPROC getCurrentContext; + PFNWGLGETCURRENTDCPROC getCurrentDC; + PFNWGLGETPROCADDRESSPROC getProcAddress; + PFNWGLMAKECURRENTPROC makeCurrent; + PFNWGLSHARELISTSPROC shareLists; + PFNWGLUSEFONTBITMAPSAPROC useFontBitmapsA; + PFNWGLUSEFONTBITMAPSWPROC useFontBitmapsW; + PFNSWAPBUFFERSPROC swapBuffers; + PFNWGLUSEFONTOUTLINESAPROC useFontOutlinesA; + PFNWGLUSEFONTOUTLINESWPROC useFontOutlinesW; + PFNWGLDESCRIBELAYERPLANEPROC describeLayerPlane; + PFNWGLSETLAYERPALETTEENTRIESPROC setLayerPaletteEntries; + PFNWGLGETLAYERPALETTEENTRIESPROC getLayerPaletteEntries; + PFNWGLREALIZELAYERPALETTEPROC realizeLayerPalette; + PFNWGLSWAPLAYERBUFFERSPROC swapLayerBuffers; + PFNWGLSWAPMULTIPLEBUFFERSPROC swapMultipleBuffers; + + // WGL_EXT_extensions_string + PFNWGLGETEXTENSIONSSTRINGEXTPROC getExtensionStringEXT; + + // WGL_ARB_extensions_string + PFNWGLGETEXTENSIONSSTRINGARBPROC getExtensionStringARB; + + // WGL_ARB_create_context + PFNWGLCREATECONTEXTATTRIBSARBPROC createContextAttribsARB; + + // WGL_ARB_pixel_format + PFNWGLGETPIXELFORMATATTRIBIVARBPROC getPixelFormatAttribivARB; + PFNWGLGETPIXELFORMATATTRIBFVARBPROC getPixelFormatAttribfvARB; + PFNWGLCHOOSEPIXELFORMATARBPROC choosePixelFormatARB; + + // WGL_EXT_swap_control + PFNWGLSWAPINTERVALEXTPROC swapIntervalEXT; + + // WGL_ARB_pbuffer + PFNWGLCREATEPBUFFERARBPROC createPbufferARB; + PFNWGLGETPBUFFERDCARBPROC getPbufferDCARB; + PFNWGLRELEASEPBUFFERDCARBPROC releasePbufferDCARB; + PFNWGLDESTROYPBUFFERARBPROC destroyPbufferARB; + PFNWGLQUERYPBUFFERARBPROC queryPbufferARB; + + // WGL_ARB_render_texture + PFNWGLBINDTEXIMAGEARBPROC bindTexImageARB; + PFNWGLRELEASETEXIMAGEARBPROC releaseTexImageARB; + PFNWGLSETPBUFFERATTRIBARBPROC setPbufferAttribARB; + + // WGL_NV_DX_interop + PFNWGLDXSETRESOURCESHAREHANDLENVPROC dxSetResourceShareHandleNV; + PFNWGLDXOPENDEVICENVPROC dxOpenDeviceNV; + PFNWGLDXCLOSEDEVICENVPROC dxCloseDeviceNV; + PFNWGLDXREGISTEROBJECTNVPROC dxRegisterObjectNV; + PFNWGLDXUNREGISTEROBJECTNVPROC dxUnregisterObjectNV; + PFNWGLDXOBJECTACCESSNVPROC dxObjectAccessNV; + PFNWGLDXLOCKOBJECTSNVPROC dxLockObjectsNV; + PFNWGLDXUNLOCKOBJECTSNVPROC dxUnlockObjectsNV; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp new file mode 100755 index 000000000..f2c503616 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp @@ -0,0 +1,196 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SurfaceWGL.cpp: WGL implementation of egl::Surface + +#include "libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h" + +#include "common/debug.h" +#include "libANGLE/renderer/gl/RendererGL.h" +#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h" +#include "libANGLE/renderer/gl/wgl/wgl_utils.h" + +namespace rx +{ + +PbufferSurfaceWGL::PbufferSurfaceWGL(const egl::SurfaceState &state, + RendererGL *renderer, + EGLint width, + EGLint height, + EGLenum textureFormat, + EGLenum textureTarget, + bool largest, + int pixelFormat, + HDC deviceContext, + HGLRC wglContext, + const FunctionsWGL *functions) + : SurfaceGL(state, renderer), + mWidth(width), + mHeight(height), + mLargest(largest), + mTextureFormat(textureFormat), + mTextureTarget(textureTarget), + mPixelFormat(pixelFormat), + mShareWGLContext(wglContext), + mParentDeviceContext(deviceContext), + mPbuffer(nullptr), + mPbufferDeviceContext(nullptr), + mFunctionsWGL(functions) +{ +} + +PbufferSurfaceWGL::~PbufferSurfaceWGL() +{ + mFunctionsWGL->releasePbufferDCARB(mPbuffer, mPbufferDeviceContext); + mPbufferDeviceContext = nullptr; + + mFunctionsWGL->destroyPbufferARB(mPbuffer); + mPbuffer = nullptr; +} + +static int GetWGLTextureType(EGLenum eglTextureType) +{ + switch (eglTextureType) + { + case EGL_NO_TEXTURE: return WGL_NO_TEXTURE_ARB; + case EGL_TEXTURE_RGB: return WGL_TEXTURE_RGB_ARB; + case EGL_TEXTURE_RGBA: return WGL_TEXTURE_RGBA_ARB; + default: UNREACHABLE(); return 0; + } +} + +static int GetWGLTextureTarget(EGLenum eglTextureTarget) +{ + switch (eglTextureTarget) + { + case EGL_NO_TEXTURE: return WGL_NO_TEXTURE_ARB; + case EGL_TEXTURE_2D: return WGL_TEXTURE_2D_ARB; + default: UNREACHABLE(); return 0; + } +} + +egl::Error PbufferSurfaceWGL::initialize() +{ + const int pbufferCreationAttributes[] = + { + WGL_PBUFFER_LARGEST_ARB, mLargest ? 1 : 0, + WGL_TEXTURE_FORMAT_ARB, GetWGLTextureType(mTextureFormat), + WGL_TEXTURE_TARGET_ARB, GetWGLTextureTarget(mTextureTarget), + 0, 0, + }; + + mPbuffer = mFunctionsWGL->createPbufferARB(mParentDeviceContext, mPixelFormat, mWidth, mHeight, + pbufferCreationAttributes); + if (mPbuffer == nullptr) + { + DWORD error = GetLastError(); + return egl::Error(EGL_BAD_ALLOC, "Failed to create a native WGL pbuffer, error: 0x%08x.", HRESULT_CODE(error)); + } + + // The returned pbuffer may not be as large as requested, update the size members. + if (mFunctionsWGL->queryPbufferARB(mPbuffer, WGL_PBUFFER_WIDTH_ARB, &mWidth) != TRUE || + mFunctionsWGL->queryPbufferARB(mPbuffer, WGL_PBUFFER_HEIGHT_ARB, &mHeight) != TRUE) + { + DWORD error = GetLastError(); + return egl::Error(EGL_BAD_ALLOC, "Failed to query the WGL pbuffer's dimensions, error: 0x%08x.", HRESULT_CODE(error)); + } + + mPbufferDeviceContext = mFunctionsWGL->getPbufferDCARB(mPbuffer); + if (mPbufferDeviceContext == nullptr) + { + mFunctionsWGL->destroyPbufferARB(mPbuffer); + mPbuffer = nullptr; + + DWORD error = GetLastError(); + return egl::Error(EGL_BAD_ALLOC, "Failed to get the WGL pbuffer handle, error: 0x%08x.", HRESULT_CODE(error)); + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceWGL::makeCurrent() +{ + if (!mFunctionsWGL->makeCurrent(mPbufferDeviceContext, mShareWGLContext)) + { + // TODO: What error type here? + return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current."); + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceWGL::swap() +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +static int GetWGLBufferBindTarget(EGLint buffer) +{ + switch (buffer) + { + case EGL_BACK_BUFFER: return WGL_BACK_LEFT_ARB; + default: UNREACHABLE(); return 0; + } +} + +egl::Error PbufferSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer) +{ + if (!mFunctionsWGL->bindTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer))) + { + DWORD error = GetLastError(); + return egl::Error(EGL_BAD_SURFACE, "Failed to bind native wgl pbuffer, error: 0x%08x.", HRESULT_CODE(error)); + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error PbufferSurfaceWGL::releaseTexImage(EGLint buffer) +{ + if (!mFunctionsWGL->releaseTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer))) + { + DWORD error = GetLastError(); + return egl::Error(EGL_BAD_SURFACE, "Failed to unbind native wgl pbuffer, error: 0x%08x.", HRESULT_CODE(error)); + } + + return egl::Error(EGL_SUCCESS); +} + +void PbufferSurfaceWGL::setSwapInterval(EGLint interval) +{ +} + +EGLint PbufferSurfaceWGL::getWidth() const +{ + return mWidth; +} + +EGLint PbufferSurfaceWGL::getHeight() const +{ + return mHeight; +} + +EGLint PbufferSurfaceWGL::isPostSubBufferSupported() const +{ + return EGL_FALSE; +} + +EGLint PbufferSurfaceWGL::getSwapBehavior() const +{ + return EGL_BUFFER_PRESERVED; +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h new file mode 100755 index 000000000..56235293a --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h @@ -0,0 +1,74 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// PBufferSurfaceWGL.h: WGL implementation of egl::Surface for PBuffers + +#ifndef LIBANGLE_RENDERER_GL_WGL_PBUFFERSURFACEWGL_H_ +#define LIBANGLE_RENDERER_GL_WGL_PBUFFERSURFACEWGL_H_ + +#include "libANGLE/renderer/gl/SurfaceGL.h" + +#include <GL/wglext.h> + +namespace rx +{ + +class FunctionsWGL; + +class PbufferSurfaceWGL : public SurfaceGL +{ + public: + PbufferSurfaceWGL(const egl::SurfaceState &state, + RendererGL *renderer, + EGLint width, + EGLint height, + EGLenum textureFormat, + EGLenum textureTarget, + bool largest, + int pixelFormat, + HDC deviceContext, + HGLRC wglContext, + const FunctionsWGL *functions); + ~PbufferSurfaceWGL() override; + + egl::Error initialize() override; + egl::Error makeCurrent() override; + + egl::Error swap() override; + egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; + egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; + egl::Error releaseTexImage(EGLint buffer) override; + void setSwapInterval(EGLint interval) override; + + EGLint getWidth() const override; + EGLint getHeight() const override; + + EGLint isPostSubBufferSupported() const override; + EGLint getSwapBehavior() const override; + + private: + EGLint mWidth; + EGLint mHeight; + bool mLargest; + EGLenum mTextureFormat; + EGLenum mTextureTarget; + + int mPixelFormat; + + HGLRC mShareWGLContext; + + HDC mParentDeviceContext; + + HPBUFFERARB mPbuffer; + HDC mPbufferDeviceContext; + + const FunctionsWGL *mFunctionsWGL; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_WGL_PBUFFERSURFACEWGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp new file mode 100755 index 000000000..f22943acb --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp @@ -0,0 +1,178 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// WindowSurfaceWGL.cpp: WGL implementation of egl::Surface for windows + +#include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h" + +#include "common/debug.h" +#include "libANGLE/renderer/gl/RendererGL.h" +#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h" +#include "libANGLE/renderer/gl/wgl/wgl_utils.h" + +namespace rx +{ + +WindowSurfaceWGL::WindowSurfaceWGL(const egl::SurfaceState &state, + RendererGL *renderer, + EGLNativeWindowType window, + int pixelFormat, + HGLRC wglContext, + const FunctionsWGL *functions, + EGLint orientation) + : SurfaceGL(state, renderer), + mPixelFormat(pixelFormat), + mWGLContext(wglContext), + mWindow(window), + mDeviceContext(nullptr), + mFunctionsWGL(functions), + mSwapBehavior(0) +{ + // EGL_ANGLE_surface_orientation is not supported for regular WGL window surfaces + ASSERT(orientation == 0); +} + +WindowSurfaceWGL::~WindowSurfaceWGL() +{ + ReleaseDC(mWindow, mDeviceContext); + mDeviceContext = nullptr; +} + +egl::Error WindowSurfaceWGL::initialize() +{ + mDeviceContext = GetDC(mWindow); + if (!mDeviceContext) + { + return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the device context from the native window, " + "error: 0x%X.", GetLastError()); + } + + // Require that the pixel format for this window has not been set yet or is equal to the Display's pixel format. + int windowPixelFormat = GetPixelFormat(mDeviceContext); + if (windowPixelFormat == 0) + { + PIXELFORMATDESCRIPTOR pixelFormatDescriptor = { 0 }; + if (!DescribePixelFormat(mDeviceContext, mPixelFormat, sizeof(pixelFormatDescriptor), &pixelFormatDescriptor)) + { + return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to DescribePixelFormat, error: 0x%X.", GetLastError()); + } + + if (!SetPixelFormat(mDeviceContext, mPixelFormat, &pixelFormatDescriptor)) + { + return egl::Error(EGL_NOT_INITIALIZED, "Failed to set the pixel format on the device context, " + "error: 0x%X.", GetLastError()); + } + } + else if (windowPixelFormat != mPixelFormat) + { + return egl::Error(EGL_NOT_INITIALIZED, "Pixel format of the NativeWindow and NativeDisplayType must match."); + } + + // Check for the swap behavior of this pixel format + switch ( + wgl::QueryWGLFormatAttrib(mDeviceContext, mPixelFormat, WGL_SWAP_METHOD_ARB, mFunctionsWGL)) + { + case WGL_SWAP_COPY_ARB: + mSwapBehavior = EGL_BUFFER_PRESERVED; + break; + + case WGL_SWAP_EXCHANGE_ARB: + case WGL_SWAP_UNDEFINED_ARB: + default: + mSwapBehavior = EGL_BUFFER_DESTROYED; + break; + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceWGL::makeCurrent() +{ + if (!mFunctionsWGL->makeCurrent(mDeviceContext, mWGLContext)) + { + // TODO: What error type here? + return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current."); + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceWGL::swap() +{ + if (!mFunctionsWGL->swapBuffers(mDeviceContext)) + { + // TODO: What error type here? + return egl::Error(EGL_CONTEXT_LOST, "Failed to swap buffers on the child window."); + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +egl::Error WindowSurfaceWGL::releaseTexImage(EGLint buffer) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_SUCCESS); +} + +void WindowSurfaceWGL::setSwapInterval(EGLint interval) +{ + if (mFunctionsWGL->swapIntervalEXT) + { + mFunctionsWGL->swapIntervalEXT(interval); + } +} + +EGLint WindowSurfaceWGL::getWidth() const +{ + RECT rect; + if (!GetClientRect(mWindow, &rect)) + { + return 0; + } + return rect.right - rect.left; +} + +EGLint WindowSurfaceWGL::getHeight() const +{ + RECT rect; + if (!GetClientRect(mWindow, &rect)) + { + return 0; + } + return rect.bottom - rect.top; +} + +EGLint WindowSurfaceWGL::isPostSubBufferSupported() const +{ + // PostSubBuffer extension not exposed on WGL. + UNIMPLEMENTED(); + return EGL_FALSE; +} + +EGLint WindowSurfaceWGL::getSwapBehavior() const +{ + return mSwapBehavior; +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h new file mode 100755 index 000000000..eb95e4dc2 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h @@ -0,0 +1,64 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// WindowSurfaceWGL.h: WGL implementation of egl::Surface for windows + +#ifndef LIBANGLE_RENDERER_GL_WGL_WINDOWSURFACEWGL_H_ +#define LIBANGLE_RENDERER_GL_WGL_WINDOWSURFACEWGL_H_ + +#include "libANGLE/renderer/gl/SurfaceGL.h" + +#include <GL/wglext.h> + +namespace rx +{ + +class FunctionsWGL; + +class WindowSurfaceWGL : public SurfaceGL +{ + public: + WindowSurfaceWGL(const egl::SurfaceState &state, + RendererGL *renderer, + EGLNativeWindowType window, + int pixelFormat, + HGLRC wglContext, + const FunctionsWGL *functions, + EGLint orientation); + ~WindowSurfaceWGL() override; + + egl::Error initialize() override; + egl::Error makeCurrent() override; + + egl::Error swap() override; + egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; + egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; + egl::Error releaseTexImage(EGLint buffer) override; + void setSwapInterval(EGLint interval) override; + + EGLint getWidth() const override; + EGLint getHeight() const override; + + EGLint isPostSubBufferSupported() const override; + EGLint getSwapBehavior() const override; + + private: + int mPixelFormat; + + HGLRC mWGLContext; + + HWND mWindow; + HDC mDeviceContext; + + const FunctionsWGL *mFunctionsWGL; + + EGLint mSwapBehavior; +}; + +} + +#endif // LIBANGLE_RENDERER_GL_WGL_WINDOWSURFACEWGL_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/functionswgl_typedefs.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/functionswgl_typedefs.h new file mode 100755 index 000000000..c4b79ee02 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/functionswgl_typedefs.h @@ -0,0 +1,43 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// functionswgl_typedefs.h: Typedefs of WGL functions. + +#ifndef LIBANGLE_RENDERER_GL_WGL_FUNCTIONSWGLTYPEDEFS_H_ +#define LIBANGLE_RENDERER_GL_WGL_FUNCTIONSWGLTYPEDEFS_H_ + +#include "common/platform.h" + +#include <angle_gl.h> +#include <GL/wglext.h> + +namespace rx +{ + +typedef BOOL(WINAPI *PFNWGLCOPYCONTEXTPROC)(HGLRC, HGLRC, UINT); +typedef HGLRC(WINAPI *PFNWGLCREATECONTEXTPROC)(HDC); +typedef HGLRC(WINAPI *PFNWGLCREATELAYERCONTEXTPROC)(HDC, int); +typedef BOOL(WINAPI *PFNWGLDELETECONTEXTPROC)(HGLRC); +typedef HGLRC(WINAPI *PFNWGLGETCURRENTCONTEXTPROC)(VOID); +typedef HDC(WINAPI *PFNWGLGETCURRENTDCPROC)(VOID); +typedef PROC(WINAPI *PFNWGLGETPROCADDRESSPROC)(LPCSTR); +typedef BOOL(WINAPI *PFNWGLMAKECURRENTPROC)(HDC, HGLRC); +typedef BOOL(WINAPI *PFNWGLSHARELISTSPROC)(HGLRC, HGLRC); +typedef BOOL(WINAPI *PFNWGLUSEFONTBITMAPSAPROC)(HDC, DWORD, DWORD, DWORD); +typedef BOOL(WINAPI *PFNWGLUSEFONTBITMAPSWPROC)(HDC, DWORD, DWORD, DWORD); +typedef BOOL(WINAPI *PFNSWAPBUFFERSPROC)(HDC); +typedef BOOL(WINAPI *PFNWGLUSEFONTOUTLINESAPROC)(HDC, DWORD, DWORD, DWORD, FLOAT, FLOAT, int, LPGLYPHMETRICSFLOAT); +typedef BOOL(WINAPI *PFNWGLUSEFONTOUTLINESWPROC)(HDC, DWORD, DWORD, DWORD, FLOAT, FLOAT, int, LPGLYPHMETRICSFLOAT); +typedef BOOL(WINAPI *PFNWGLDESCRIBELAYERPLANEPROC)(HDC, int, int, UINT, LPLAYERPLANEDESCRIPTOR); +typedef int(WINAPI *PFNWGLSETLAYERPALETTEENTRIESPROC)(HDC, int, int, int, CONST COLORREF *); +typedef int(WINAPI *PFNWGLGETLAYERPALETTEENTRIESPROC)(HDC, int, int, int, COLORREF *); +typedef BOOL(WINAPI *PFNWGLREALIZELAYERPALETTEPROC)(HDC, int, BOOL); +typedef BOOL(WINAPI *PFNWGLSWAPLAYERBUFFERSPROC)(HDC, UINT); +typedef DWORD(WINAPI *PFNWGLSWAPMULTIPLEBUFFERSPROC)(UINT, CONST WGLSWAP *); + +} + +#endif // LIBANGLE_RENDERER_GL_WGL_FUNCTIONSWGLTYPEDEFS_H_ diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp new file mode 100755 index 000000000..641c3fbc4 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp @@ -0,0 +1,85 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// wgl_utils.cpp: Utility routines specific to the WGL->EGL implementation. + +#include "libANGLE/renderer/gl/wgl/wgl_utils.h" + +#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h" + +namespace rx +{ + +namespace wgl +{ + +PIXELFORMATDESCRIPTOR GetDefaultPixelFormatDescriptor() +{ + PIXELFORMATDESCRIPTOR pixelFormatDescriptor = { 0 }; + pixelFormatDescriptor.nSize = sizeof(pixelFormatDescriptor); + pixelFormatDescriptor.nVersion = 1; + pixelFormatDescriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_GENERIC_ACCELERATED | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pixelFormatDescriptor.iPixelType = PFD_TYPE_RGBA; + pixelFormatDescriptor.cColorBits = 24; + pixelFormatDescriptor.cAlphaBits = 8; + pixelFormatDescriptor.cDepthBits = 24; + pixelFormatDescriptor.cStencilBits = 8; + pixelFormatDescriptor.iLayerType = PFD_MAIN_PLANE; + + return pixelFormatDescriptor; +} + +std::vector<int> GetDefaultPixelFormatAttributes(bool preservedSwap) +{ + std::vector<int> attribs; + attribs.push_back(WGL_DRAW_TO_WINDOW_ARB); + attribs.push_back(TRUE); + + attribs.push_back(WGL_ACCELERATION_ARB); + attribs.push_back(WGL_FULL_ACCELERATION_ARB); + + attribs.push_back(WGL_SUPPORT_OPENGL_ARB); + attribs.push_back(TRUE); + + attribs.push_back(WGL_DOUBLE_BUFFER_ARB); + attribs.push_back(TRUE); + + attribs.push_back(WGL_PIXEL_TYPE_ARB); + attribs.push_back(WGL_TYPE_RGBA_ARB); + + attribs.push_back(WGL_COLOR_BITS_ARB); + attribs.push_back(24); + + attribs.push_back(WGL_ALPHA_BITS_ARB); + attribs.push_back(8); + + attribs.push_back(WGL_DEPTH_BITS_ARB); + attribs.push_back(24); + + attribs.push_back(WGL_STENCIL_BITS_ARB); + attribs.push_back(8); + + attribs.push_back(WGL_SWAP_METHOD_ARB); + attribs.push_back(preservedSwap ? WGL_SWAP_COPY_ARB : WGL_SWAP_UNDEFINED_ARB); + + attribs.push_back(0); + + return attribs; +} + +int QueryWGLFormatAttrib(HDC dc, int format, int attribName, const FunctionsWGL *functions) +{ + int result = 0; + if (functions->getPixelFormatAttribivARB == nullptr || + !functions->getPixelFormatAttribivARB(dc, format, 0, 1, &attribName, &result)) + { + return 0; + } + return result; +} +} + +} diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.h new file mode 100755 index 000000000..d4914b5d3 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// wgl_utils.h: Utility routines specific to the WGL->EGL implementation. + +#ifndef LIBANGLE_RENDERER_GL_WGL_WGLUTILS_H_ +#define LIBANGLE_RENDERER_GL_WGL_WGLUTILS_H_ + +#include <vector> + +#include "common/platform.h" + +namespace rx +{ + +class FunctionsWGL; + +namespace wgl +{ + +PIXELFORMATDESCRIPTOR GetDefaultPixelFormatDescriptor(); +std::vector<int> GetDefaultPixelFormatAttributes(bool preservedSwap); + +int QueryWGLFormatAttrib(HDC dc, int format, int attribName, const FunctionsWGL *functions); +} + +} + +#endif // LIBANGLE_RENDERER_GL_WGL_WGLUTILS_H_ |