| 1 | /**************************************************************************** |
| 2 | ** |
| 3 | ** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). |
| 4 | ** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). |
| 5 | ** Contact: https://www.qt.io/licensing/ |
| 6 | ** |
| 7 | ** This file is part of the Qt3D module of the Qt Toolkit. |
| 8 | ** |
| 9 | ** $QT_BEGIN_LICENSE:LGPL$ |
| 10 | ** Commercial License Usage |
| 11 | ** Licensees holding valid commercial Qt licenses may use this file in |
| 12 | ** accordance with the commercial license agreement provided with the |
| 13 | ** Software or, alternatively, in accordance with the terms contained in |
| 14 | ** a written agreement between you and The Qt Company. For licensing terms |
| 15 | ** and conditions see https://www.qt.io/terms-conditions. For further |
| 16 | ** information use the contact form at https://www.qt.io/contact-us. |
| 17 | ** |
| 18 | ** GNU Lesser General Public License Usage |
| 19 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
| 20 | ** General Public License version 3 as published by the Free Software |
| 21 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| 22 | ** packaging of this file. Please review the following information to |
| 23 | ** ensure the GNU Lesser General Public License version 3 requirements |
| 24 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| 25 | ** |
| 26 | ** GNU General Public License Usage |
| 27 | ** Alternatively, this file may be used under the terms of the GNU |
| 28 | ** General Public License version 2.0 or (at your option) the GNU General |
| 29 | ** Public license version 3 or any later version approved by the KDE Free |
| 30 | ** Qt Foundation. The licenses are as published by the Free Software |
| 31 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| 32 | ** included in the packaging of this file. Please review the following |
| 33 | ** information to ensure the GNU General Public License requirements will |
| 34 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| 35 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
| 36 | ** |
| 37 | ** $QT_END_LICENSE$ |
| 38 | ** |
| 39 | ****************************************************************************/ |
| 40 | |
| 41 | #ifndef QT3DRENDER_RENDER_OPENGL_GRAPHICSCONTEXT_H |
| 42 | #define QT3DRENDER_RENDER_OPENGL_GRAPHICSCONTEXT_H |
| 43 | |
| 44 | // |
| 45 | // W A R N I N G |
| 46 | // ------------- |
| 47 | // |
| 48 | // This file is not part of the Qt API. It exists for the convenience |
| 49 | // of other Qt classes. This header file may change from version to |
| 50 | // version without notice, or even be removed. |
| 51 | // |
| 52 | // We mean it. |
| 53 | // |
| 54 | |
| 55 | #include <QOpenGLContext> |
| 56 | #include <QOpenGLFunctions> |
| 57 | #include <QOpenGLVertexArrayObject> |
| 58 | #include <QHash> |
| 59 | #include <QColor> |
| 60 | #include <QMatrix4x4> |
| 61 | #include <QBitArray> |
| 62 | #include <QImage> |
| 63 | #include <Qt3DRender/qclearbuffers.h> |
| 64 | #include <Qt3DRender/private/shader_p.h> |
| 65 | #include <Qt3DRender/qattribute.h> |
| 66 | #include <Qt3DRender/qmemorybarrier.h> |
| 67 | #include <Qt3DRender/private/handle_types_p.h> |
| 68 | #include <Qt3DRender/private/qgraphicsapifilter_p.h> |
| 69 | #include <Qt3DRender/private/uniform_p.h> |
| 70 | #include <Qt3DRender/private/qblitframebuffer_p.h> |
| 71 | #include <gl_handle_types_p.h> |
| 72 | #include <glbuffer_p.h> |
| 73 | #include <shaderparameterpack_p.h> |
| 74 | #include <graphicshelperinterface_p.h> |
| 75 | #include <qmath.h> |
| 76 | |
| 77 | QT_BEGIN_NAMESPACE |
| 78 | |
| 79 | class QOpenGLShaderProgram; |
| 80 | class QAbstractOpenGLFunctions; |
| 81 | class QOpenGLDebugLogger; |
| 82 | |
| 83 | namespace Qt3DRender { |
| 84 | |
| 85 | namespace Render { |
| 86 | |
| 87 | class RenderTarget; |
| 88 | class AttachmentPack; |
| 89 | class ShaderManager; |
| 90 | |
| 91 | namespace OpenGL { |
| 92 | |
| 93 | class GraphicsHelperInterface; |
| 94 | class GLShader; |
| 95 | class GLShaderManager; |
| 96 | |
| 97 | typedef QPair<QString, int> NamedUniformLocation; |
| 98 | |
| 99 | class Q_AUTOTEST_EXPORT GraphicsContext |
| 100 | { |
| 101 | public: |
| 102 | GraphicsContext(); |
| 103 | ~GraphicsContext(); |
| 104 | |
| 105 | void setOpenGLContext(QOpenGLContext* ctx); |
| 106 | QOpenGLContext *openGLContext() { return m_gl; } |
| 107 | bool makeCurrent(QSurface *surface); |
| 108 | void doneCurrent(); |
| 109 | bool hasValidGLHelper() const; |
| 110 | bool isInitialized() const; |
| 111 | |
| 112 | // Shaders |
| 113 | struct ShaderCreationInfo |
| 114 | { |
| 115 | bool linkSucceeded = false; |
| 116 | QString logs; |
| 117 | }; |
| 118 | |
| 119 | ShaderCreationInfo createShaderProgram(GLShader *shaderNode); |
| 120 | void introspectShaderInterface(GLShader *shader); |
| 121 | void loadShader(Shader* shader, ShaderManager *shaderManager, GLShaderManager *glShaderManager); |
| 122 | |
| 123 | GLuint defaultFBO() const { return m_defaultFBO; } |
| 124 | |
| 125 | const GraphicsApiFilterData *contextInfo() const; |
| 126 | |
| 127 | // Wrapper methods |
| 128 | void clearBackBuffer(QClearBuffers::BufferTypeFlags buffers); |
| 129 | void alphaTest(GLenum mode1, GLenum mode2); |
| 130 | void bindFramebuffer(GLuint fbo, GraphicsHelperInterface::FBOBindMode mode); |
| 131 | void bindBufferBase(GLenum target, GLuint bindingIndex, GLuint buffer); |
| 132 | void bindFragOutputs(GLuint shader, const QHash<QString, int> &outputs); |
| 133 | void bindImageTexture(GLuint imageUnit, GLuint texture, GLint mipLevel, GLboolean layered, GLint layer, GLenum access, GLenum format); |
| 134 | void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding); |
| 135 | void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding); |
| 136 | void blendEquation(GLenum mode); |
| 137 | void blendFunci(GLuint buf, GLenum sfactor, GLenum dfactor); |
| 138 | void blendFuncSeparatei(GLuint buf, GLenum sRGB, GLenum dRGB, GLenum sAlpha, GLenum dAlpha); |
| 139 | GLuint boundFrameBufferObject(); |
| 140 | void buildUniformBuffer(const QVariant &v, const ShaderUniform &description, QByteArray &buffer); |
| 141 | void clearBufferf(GLint drawbuffer, const QVector4D &values); |
| 142 | void clearColor(const QColor &color); |
| 143 | void clearDepthValue(float depth); |
| 144 | void clearStencilValue(int stencil); |
| 145 | void depthRange(GLdouble nearValue, GLdouble farValue); |
| 146 | void depthMask(GLenum mode); |
| 147 | void depthTest(GLenum mode); |
| 148 | void disableClipPlane(int clipPlane); |
| 149 | void disablei(GLenum cap, GLuint index); |
| 150 | void disablePrimitiveRestart(); |
| 151 | void dispatchCompute(int x, int y, int z); |
| 152 | char * mapBuffer(GLenum target, GLsizeiptr size); |
| 153 | GLboolean unmapBuffer(GLenum target); |
| 154 | void drawArrays(GLenum primitiveType, GLint first, GLsizei count); |
| 155 | void drawArraysIndirect(GLenum mode,void *indirect); |
| 156 | void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances); |
| 157 | void drawArraysInstancedBaseInstance(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances, GLsizei baseinstance); |
| 158 | void drawElements(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void * indices, GLint baseVertex); |
| 159 | void drawElementsIndirect(GLenum mode, GLenum type, void *indirect); |
| 160 | void drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void * indices, GLsizei instances, GLint baseVertex, GLint baseInstance); |
| 161 | void enableClipPlane(int clipPlane); |
| 162 | void enablei(GLenum cap, GLuint index); |
| 163 | void enablePrimitiveRestart(int restartIndex); |
| 164 | void frontFace(GLenum mode); |
| 165 | GLint maxClipPlaneCount(); |
| 166 | GLint maxTextureUnitsCount() const; |
| 167 | GLint maxImageUnitsCount() const; |
| 168 | void pointSize(bool programmable, GLfloat value); |
| 169 | void readBuffer(GLenum mode); |
| 170 | void drawBuffer(GLenum mode); |
| 171 | void drawBuffers(GLsizei n, const int *bufs); |
| 172 | void setMSAAEnabled(bool enabled); |
| 173 | void setAlphaCoverageEnabled(bool enabled); |
| 174 | void setClipPlane(int clipPlane, const QVector3D &normal, float distance); |
| 175 | void setSeamlessCubemap(bool enable); |
| 176 | void setVerticesPerPatch(GLint verticesPerPatch); |
| 177 | void memoryBarrier(QMemoryBarrier::Operations barriers); |
| 178 | void activateDrawBuffers(const AttachmentPack &attachments); |
| 179 | void rasterMode(GLenum faceMode, GLenum rasterMode); |
| 180 | |
| 181 | // Helper methods |
| 182 | static GLint elementType(GLint type); |
| 183 | static GLint tupleSizeFromType(GLint type); |
| 184 | static GLuint byteSizeFromType(GLint type); |
| 185 | static GLint glDataTypeFromAttributeDataType(QAttribute::VertexBaseType dataType); |
| 186 | |
| 187 | bool supportsDrawBuffersBlend() const; |
| 188 | bool supportsVAO() const { return m_supportsVAO; } |
| 189 | |
| 190 | void initialize(); |
| 191 | void initializeHelpers(QSurface *surface); |
| 192 | GraphicsHelperInterface *resolveHighestOpenGLFunctions(); |
| 193 | |
| 194 | bool m_initialized; |
| 195 | bool m_supportsVAO; |
| 196 | GLint m_maxTextureUnits; |
| 197 | GLint m_maxImageUnits; |
| 198 | GLuint m_defaultFBO; |
| 199 | QOpenGLContext *m_gl; |
| 200 | GraphicsHelperInterface *m_glHelper; |
| 201 | |
| 202 | QHash<QSurface *, GraphicsHelperInterface*> m_glHelpers; |
| 203 | GraphicsApiFilterData m_contextInfo; |
| 204 | QScopedPointer<QOpenGLDebugLogger> m_debugLogger; |
| 205 | |
| 206 | friend class OpenGLVertexArrayObject; |
| 207 | OpenGLVertexArrayObject *m_currentVAO; |
| 208 | |
| 209 | void applyUniform(const ShaderUniform &description, const UniformValue &v); |
| 210 | |
| 211 | template<UniformType> |
| 212 | void applyUniformHelper(const ShaderUniform &, const UniformValue &) const |
| 213 | { |
| 214 | Q_ASSERT_X(false, Q_FUNC_INFO, "Uniform: Didn't provide specialized apply() implementation" ); |
| 215 | } |
| 216 | }; |
| 217 | |
| 218 | #define QT3D_UNIFORM_TYPE_PROTO(UniformTypeEnum, BaseType, Func) \ |
| 219 | template<> \ |
| 220 | void GraphicsContext::applyUniformHelper<UniformTypeEnum>(const ShaderUniform &description, const UniformValue &value) const; |
| 221 | |
| 222 | #define QT3D_UNIFORM_TYPE_IMPL(UniformTypeEnum, BaseType, Func) \ |
| 223 | template<> \ |
| 224 | void GraphicsContext::applyUniformHelper<UniformTypeEnum>(const ShaderUniform &description, const UniformValue &value) const \ |
| 225 | { \ |
| 226 | const int count = qMin(description.m_size, int(value.byteSize() / description.m_rawByteSize)); \ |
| 227 | m_glHelper->Func(description.m_location, count, value.constData<BaseType>()); \ |
| 228 | } |
| 229 | |
| 230 | |
| 231 | QT3D_UNIFORM_TYPE_PROTO(UniformType::Float, float, glUniform1fv) |
| 232 | QT3D_UNIFORM_TYPE_PROTO(UniformType::Vec2, float, glUniform2fv) |
| 233 | QT3D_UNIFORM_TYPE_PROTO(UniformType::Vec3, float, glUniform3fv) |
| 234 | QT3D_UNIFORM_TYPE_PROTO(UniformType::Vec4, float, glUniform4fv) |
| 235 | |
| 236 | // OpenGL expects int* as values for booleans |
| 237 | QT3D_UNIFORM_TYPE_PROTO(UniformType::Bool, int, glUniform1iv) |
| 238 | QT3D_UNIFORM_TYPE_PROTO(UniformType::BVec2, int, glUniform2iv) |
| 239 | QT3D_UNIFORM_TYPE_PROTO(UniformType::BVec3, int, glUniform3iv) |
| 240 | QT3D_UNIFORM_TYPE_PROTO(UniformType::BVec4, int, glUniform4iv) |
| 241 | |
| 242 | QT3D_UNIFORM_TYPE_PROTO(UniformType::Int, int, glUniform1iv) |
| 243 | QT3D_UNIFORM_TYPE_PROTO(UniformType::IVec2, int, glUniform2iv) |
| 244 | QT3D_UNIFORM_TYPE_PROTO(UniformType::IVec3, int, glUniform3iv) |
| 245 | QT3D_UNIFORM_TYPE_PROTO(UniformType::IVec4, int, glUniform4iv) |
| 246 | |
| 247 | QT3D_UNIFORM_TYPE_PROTO(UniformType::UInt, uint, glUniform1uiv) |
| 248 | QT3D_UNIFORM_TYPE_PROTO(UniformType::UIVec2, uint, glUniform2uiv) |
| 249 | QT3D_UNIFORM_TYPE_PROTO(UniformType::UIVec3, uint, glUniform3uiv) |
| 250 | QT3D_UNIFORM_TYPE_PROTO(UniformType::UIVec4, uint, glUniform4uiv) |
| 251 | |
| 252 | QT3D_UNIFORM_TYPE_PROTO(UniformType::Mat2, float, glUniformMatrix2fv) |
| 253 | QT3D_UNIFORM_TYPE_PROTO(UniformType::Mat3, float, glUniformMatrix3fv) |
| 254 | QT3D_UNIFORM_TYPE_PROTO(UniformType::Mat4, float, glUniformMatrix4fv) |
| 255 | QT3D_UNIFORM_TYPE_PROTO(UniformType::Mat2x3, float, glUniformMatrix2x3fv) |
| 256 | QT3D_UNIFORM_TYPE_PROTO(UniformType::Mat3x2, float, glUniformMatrix3x2fv) |
| 257 | QT3D_UNIFORM_TYPE_PROTO(UniformType::Mat2x4, float, glUniformMatrix2x4fv) |
| 258 | QT3D_UNIFORM_TYPE_PROTO(UniformType::Mat4x2, float, glUniformMatrix4x2fv) |
| 259 | QT3D_UNIFORM_TYPE_PROTO(UniformType::Mat3x4, float, glUniformMatrix3x4fv) |
| 260 | QT3D_UNIFORM_TYPE_PROTO(UniformType::Mat4x3, float, glUniformMatrix4x3fv) |
| 261 | |
| 262 | } // namespace OpenGL |
| 263 | } // namespace Render |
| 264 | } // namespace Qt3DRender |
| 265 | |
| 266 | QT_END_NAMESPACE |
| 267 | |
| 268 | #endif // QT3DRENDER_RENDER_OPENGL_GRAPHICSCONTEXT_H |
| 269 | |