File indexing completed on 2024-12-22 04:12:48

0001 /*
0002  *  SPDX-FileCopyrightText: 2021 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "KisOpenGLSync.h"
0008 
0009 namespace Sync {
0010     //For checking sync status
0011     enum SyncStatus {
0012         Signaled,
0013         Unsignaled
0014     };
0015 
0016 #ifndef GL_SYNC_GPU_COMMANDS_COMPLETE
0017     #define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
0018 #endif
0019 #ifndef GL_UNSIGNALED
0020     #define GL_UNSIGNALED 0x9118
0021 #endif
0022 #ifndef GL_SIGNALED
0023     #define GL_SIGNALED 0x9119
0024 #endif
0025 #ifndef GL_SYNC_STATUS
0026     #define GL_SYNC_STATUS 0x9114
0027 #endif
0028 
0029     //Function pointers for glFenceSync and glGetSynciv
0030     typedef GLsync (*kis_glFenceSync)(GLenum, GLbitfield);
0031     static kis_glFenceSync k_glFenceSync = 0;
0032     typedef void (*kis_glGetSynciv)(GLsync, GLenum, GLsizei, GLsizei*, GLint*);
0033     static kis_glGetSynciv k_glGetSynciv = 0;
0034     typedef void (*kis_glDeleteSync)(GLsync);
0035     static kis_glDeleteSync k_glDeleteSync = 0;
0036     typedef GLenum (*kis_glClientWaitSync)(GLsync,GLbitfield,GLuint64);
0037     static kis_glClientWaitSync k_glClientWaitSync = 0;
0038 
0039     //Initialise the function pointers for glFenceSync and glGetSynciv
0040     //Note: Assumes a current OpenGL context.
0041     void init(QOpenGLContext* ctx) {
0042 #if defined Q_OS_WIN
0043         if (KisOpenGL::supportsFenceSync()) {
0044 #ifdef ENV64BIT
0045             k_glFenceSync  = (kis_glFenceSync)ctx->getProcAddress("glFenceSync");
0046             k_glGetSynciv  = (kis_glGetSynciv)ctx->getProcAddress("glGetSynciv");
0047             k_glDeleteSync = (kis_glDeleteSync)ctx->getProcAddress("glDeleteSync");
0048 #else
0049             k_glFenceSync  = (kis_glFenceSync)ctx->getProcAddress("glFenceSyncARB");
0050             k_glGetSynciv  = (kis_glGetSynciv)ctx->getProcAddress("glGetSyncivARB");
0051             k_glDeleteSync = (kis_glDeleteSync)ctx->getProcAddress("glDeleteSyncARB");
0052 #endif
0053             k_glClientWaitSync = (kis_glClientWaitSync)ctx->getProcAddress("glClientWaitSync");
0054         }
0055 #elif defined Q_OS_LINUX || defined Q_OS_MACOS
0056         if (KisOpenGL::supportsFenceSync()) {
0057             k_glFenceSync  = (kis_glFenceSync)ctx->getProcAddress("glFenceSync");
0058             k_glGetSynciv  = (kis_glGetSynciv)ctx->getProcAddress("glGetSynciv");
0059             k_glDeleteSync = (kis_glDeleteSync)ctx->getProcAddress("glDeleteSync");
0060             k_glClientWaitSync = (kis_glClientWaitSync)ctx->getProcAddress("glClientWaitSync");
0061         }
0062 #endif
0063         if (k_glFenceSync  == 0 || k_glGetSynciv      == 0 ||
0064             k_glDeleteSync == 0 || k_glClientWaitSync == 0) {
0065             warnUI << "Could not find sync functions, disabling sync notification.";
0066         }
0067     }
0068 
0069     //Get a fence sync object from OpenGL
0070     GLsync getSync() {
0071         if(k_glFenceSync) {
0072             GLsync sync = k_glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
0073             if (KisOpenGL::needsFenceWorkaround()) {
0074                 k_glClientWaitSync(sync, 0, 1);
0075             }
0076             return sync;
0077         }
0078         return 0;
0079     }
0080 
0081     //Check the status of a sync object
0082     SyncStatus syncStatus(GLsync syncObject) {
0083         if(syncObject && k_glGetSynciv) {
0084             GLint status = -1;
0085             k_glGetSynciv(syncObject, GL_SYNC_STATUS, 1, 0, &status);
0086             return status == GL_SIGNALED ? Sync::Signaled : Sync::Unsignaled;
0087         }
0088         return Sync::Signaled;
0089     }
0090 
0091     void deleteSync(GLsync syncObject) {
0092         if(syncObject && k_glDeleteSync) {
0093             k_glDeleteSync(syncObject);
0094         }
0095     }
0096 }
0097 
0098 KisOpenGLSync::KisOpenGLSync()
0099 {
0100     m_syncObject = Sync::getSync();
0101 }
0102 
0103 KisOpenGLSync::~KisOpenGLSync()
0104 {
0105     Sync::deleteSync(m_syncObject);
0106 }
0107 
0108 bool KisOpenGLSync::isSignaled()
0109 {
0110     return Sync::syncStatus(m_syncObject) == Sync::Signaled;
0111 }
0112 
0113 void KisOpenGLSync::init(QOpenGLContext *ctx)
0114 {
0115     Sync::init(ctx);
0116 }