/* Copyright (c) 2010 - 2023 Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma once #ifdef _WIN32 #include #else //!_WIN32 #include #endif //!_WIN32 #include #include #include "CL/cl_gl.h" #ifndef _WIN32 #include #endif //!_WIN32 #include #include #include #include "platform/context.hpp" #include "platform/command.hpp" namespace amd { //! Class GLObject keeps all the info about the GL object //! from which the CL object is created class GLObject : public InteropObject { protected: cl_gl_object_type clGLType_; //!< CL GL object type GLenum glTarget_; GLuint gluiName_; GLint gliMipLevel_; GLenum glInternalFormat_; GLint gliWidth_; GLint gliHeight_; GLint gliDepth_; GLenum glCubemapFace_; GLsizei glNumSamples_; public: //! GLObject constructor initializes member variables GLObject( GLenum glTarget, GLuint gluiName, GLint gliMipLevel, GLenum glInternalFormat, GLint gliWidth, GLint gliHeight, GLint gliDepth, cl_gl_object_type clGLType, GLenum glCubemapFace, GLsizei glNumSamples ): // Initialization of member variables clGLType_(clGLType), glTarget_(glTarget), gluiName_(gluiName), gliMipLevel_(gliMipLevel), glInternalFormat_(glInternalFormat), gliWidth_(gliWidth), gliHeight_(gliHeight), gliDepth_(gliDepth), glCubemapFace_(glCubemapFace), glNumSamples_(glNumSamples) { } virtual ~GLObject() {} virtual GLObject* asGLObject() {return this;} //! GLObject query functions to get GL info from member variables GLenum getGLTarget() const {return glTarget_;} GLuint getGLName() const {return gluiName_;} GLint getGLMipLevel() const {return gliMipLevel_;} GLenum getGLInternalFormat() const {return glInternalFormat_;} GLint getGLSize() const {return gliWidth_;} GLint getGLWidth() const {return gliWidth_;} GLint getGLHeight() const {return gliHeight_;} GLint getGLDepth() const {return gliDepth_;} cl_gl_object_type getCLGLObjectType() const { return clGLType_; } GLenum getCubemapFace() const {return glCubemapFace_;} GLsizei getNumSamples() const { return glNumSamples_;} }; //! Class BufferGL is drived from classes Buffer and GLObject //! where the former keeps all data for CL object and //! the latter keeps all data for GL object class BufferGL : public Buffer, public GLObject { protected: //! Initializes the device memory array which is nested // after'BufferGL' object in memory layout. virtual void initDeviceMemory(); public: //! BufferGL constructor just calls constructors of base classes //! to pass down the parameters BufferGL( Context& amdContext, cl_mem_flags clFlags, size_t uiSizeInBytes, GLenum glTarget, GLuint gluiName) : // Call base classes constructors Buffer( amdContext, clFlags, uiSizeInBytes ), GLObject( glTarget, gluiName, 0, // Mipmap level default GL_ARRAY_BUFFER, // Just init to some value (GLint) uiSizeInBytes, 1, 1, CL_GL_OBJECT_BUFFER, 0, 0 ) { setInteropObj(this); } virtual ~BufferGL() {} virtual BufferGL* asBufferGL() { return this; } }; //! Class ImageGL is derived from classes Image and GLObject //! where the former keeps all data for CL object and //! the latter keeps all data for GL object class ImageGL : public Image, public GLObject { public: //! ImageGL constructor just calls constructors of base classes //! to pass down the parameters ImageGL( Context& amdContext, cl_mem_object_type clType, cl_mem_flags clFlags, const Format& format, size_t width, size_t height, size_t depth, GLenum glTarget, GLuint gluiName, GLint gliMipLevel, GLenum glInternalFormat, cl_gl_object_type clGLType, GLsizei numSamples, GLenum glCubemapFace = 0) : Image(amdContext, clType, clFlags, format, width, height, depth, Format(format).getElementSize() * width, Format(format).getElementSize() * width * height) , GLObject(glTarget, gluiName, gliMipLevel, glInternalFormat, static_cast(width), static_cast(height), static_cast(depth), clGLType, glCubemapFace,numSamples) { setInteropObj(this); } //! ImageGL constructor for mipmapped image, //! just calls constructors of base classes to pass down the parameters ImageGL( Context& amdContext, cl_mem_object_type clType, cl_mem_flags clFlags, const Format& format, size_t width, size_t height, size_t depth, GLenum glTarget, GLuint gluiName, GLint gliMipLevel, GLenum glInternalFormat, cl_gl_object_type clGLType, GLsizei numSamples, cl_int num_mip_levels, GLenum glCubemapFace = 0) : Image(amdContext, clType, clFlags, format, width, height, depth, Format(format).getElementSize() * width, Format(format).getElementSize() * width * depth, num_mip_levels) , GLObject(glTarget, gluiName, gliMipLevel, glInternalFormat, static_cast(width), static_cast(height), static_cast(depth), clGLType, glCubemapFace,numSamples) { setInteropObj(this); } virtual ~ImageGL() {} protected: //! Initializes the device memory array which is nested // after'BufferGL' object in memory layout. virtual void initDeviceMemory(); }; typedef EGLContext (*PFN_eglGetCurrentContext) (); #ifdef _WIN32 #define APICALL WINAPI #define GETPROCADDRESS GetProcAddress #define API_GETPROCADDR "wglGetProcAddress" #define FCN_STR_TYPE LPCSTR typedef PROC (WINAPI* PFN_xxxGetProcAddress) (LPCSTR fcnName); typedef HGLRC (APICALL* PFN_wglCreateContext) (HDC hdc); typedef HGLRC (APICALL* PFN_wglGetCurrentContext) (void); typedef HDC (APICALL* PFN_wglGetCurrentDC) (void); typedef BOOL (APICALL* PFN_wglDeleteContext) (HGLRC hglrc); typedef BOOL (APICALL* PFN_wglMakeCurrent) (HDC hdc, HGLRC hglrc); typedef BOOL (APICALL* PFN_wglShareLists) (HGLRC hglrc1, HGLRC hglrc2); #else //!_WIN32 #define APICALL // __stdcall //??? todo odintsov #define API_GETPROCADDR "glXGetProcAddress" #define GETPROCADDRESS dlsym #define FCN_STR_TYPE const GLubyte* #define WINAPI #define PROC void* typedef void* (*PFN_xxxGetProcAddress) (const GLubyte* procName); // X11 typedef typedef Display* (*PFNXOpenDisplay)(_Xconst char* display_name ); typedef int (*PFNXCloseDisplay)(Display* display ); //glx typedefs typedef GLXDrawable (*PFNglXGetCurrentDrawable)(); typedef Display* (*PFNglXGetCurrentDisplay)(); typedef GLXContext (*PFNglXGetCurrentContext)( void ); typedef XVisualInfo* (*PFNglXChooseVisual)(Display *dpy, int screen, int *attribList); typedef GLXContext(*PFNglXCreateContext)(Display* dpy,XVisualInfo* vis,GLXContext shareList,Bool direct); typedef void(*PFNglXDestroyContext)(Display* dpy, GLXContext ctx); typedef Bool(*PFNglXMakeCurrent)( Display* dpy, GLXDrawable drawable, GLXContext ctx); typedef void* HMODULE; #endif //!_WIN32 #define GLPREFIX(rtype, fcn, dclargs) \ typedef rtype (APICALL* PFN_##fcn) dclargs; // Declare prototypes for GL functions #include "gl_functions.hpp" class GLFunctions { public: //! Locks any access to the virtual GPUs class SetIntEnv : public amd::StackObject { public: //! Default constructor SetIntEnv(GLFunctions* env); //! Destructor ~SetIntEnv(); //! Checks if the environment setup was successful bool isValid() const { return isValid_; } private: GLFunctions* env_; //!< GL environment bool isValid_; //!< If TRUE, then it's a valid setup }; //! Locks any access to the virtual GPUs class Lock : public amd::StackObject { public: //! Default constructor Lock(GLFunctions* env); //! Destructor ~Lock(); private: GLFunctions* env_; //!< GL environment }; private: HMODULE libHandle_; int missed_; // Indicates how many GL functions not init'ed, if any amd::Monitor lock_; EGLDisplay eglDisplay_; EGLContext eglOriginalContext_; EGLContext eglInternalContext_; EGLContext eglTempContext_; bool isEGL_; PFN_eglGetCurrentContext eglGetCurrentContext_; #ifdef _WIN32 HGLRC hOrigGLRC_; HDC hDC_; HGLRC hIntGLRC_; // handle for internal GLRC to access shared context HDC tempDC_; HGLRC tempGLRC_; public: PFN_wglCreateContext wglCreateContext_; PFN_wglGetCurrentContext wglGetCurrentContext_; PFN_wglGetCurrentDC wglGetCurrentDC_; PFN_wglDeleteContext wglDeleteContext_; PFN_wglMakeCurrent wglMakeCurrent_; PFN_wglShareLists wglShareLists_; #else public: Display* Dpy_; GLXDrawable Drawable_; GLXContext origCtx_; Display* intDpy_; Window intDrawable_; GLXContext intCtx_; Display* tempDpy_; GLXDrawable tempDrawable_; GLXContext tempCtx_; //pointers to X11 functions PFNXOpenDisplay XOpenDisplay_; PFNXCloseDisplay XCloseDisplay_; //pointers to GLX functions PFNglXGetCurrentDrawable glXGetCurrentDrawable_; PFNglXGetCurrentDisplay glXGetCurrentDisplay_; PFNglXGetCurrentContext glXGetCurrentContext_; PFNglXChooseVisual glXChooseVisual_; PFNglXCreateContext glXCreateContext_; PFNglXDestroyContext glXDestroyContext_; PFNglXMakeCurrent glXMakeCurrent_; #endif public: GLFunctions(HMODULE h, bool isEGL); ~GLFunctions(); bool update(intptr_t hglrc); bool IsCurrentGlContext(const amd::Context::Info& info) const { if (isEGL_) { return ((info.hCtx_ != nullptr) && (eglGetCurrentContext_ != nullptr) && (info.hCtx_ == eglGetCurrentContext_())); } else { #ifdef _WIN32 return ((info.hCtx_ != nullptr) && (info.hCtx_ == wglGetCurrentContext_())); #else return ((info.hCtx_ != nullptr) && (info.hCtx_ == glXGetCurrentContext_())); #endif // _WIN32 } } void WaitCurrentGlContext(const amd::Context::Info& info) const; // Query CL-GL context association bool isAssociated() const { if (isEGL_ && eglDisplay_ && eglOriginalContext_) return true; #ifdef _WIN32 if(hDC_ && hOrigGLRC_) return true; #else //!_WIN32 if(Dpy_ && origCtx_) return true; #endif //!_WIN32 return false; } bool isEGL() const { return isEGL_; } // Accessor methods #ifdef _WIN32 HGLRC getOrigGLRC() const {return hOrigGLRC_;} HDC getDC() const {return hDC_;} HGLRC getIntGLRC() const {return hIntGLRC_;} #else //!_WIN32 Display* getDpy() const {return Dpy_;} GLXDrawable getDrawable() const {return Drawable_;} GLXContext getOrigCtx() const {return origCtx_;} Display* getIntDpy() const {return intDpy_;} GLXDrawable getIntDrawable() const {return intDrawable_;} GLXContext getIntCtx() const {return intCtx_;} EGLDisplay getEglDpy() const { return eglDisplay_; } EGLContext getEglOrigCtx() const { return eglOriginalContext_; } #endif //!_WIN32 // Initialize GL dynamic library and function pointers bool init(intptr_t hdc, intptr_t hglrc); // Return true if successful, false - if error occurred bool setIntEnv(); bool restoreEnv(); amd::Monitor& getLock() { return lock_; } PFN_xxxGetProcAddress GetProcAddress_; #define GLPREFIX(rtype, fcn, dclargs) \ PFN_##fcn fcn##_; // Declare pointers to GL functions #include "gl_functions.hpp" }; //! Functions for executing the GL related stuff cl_mem clCreateFromGLBufferAMD(Context& amdContext, cl_mem_flags flags, GLuint bufobj, cl_int* errcode_ret); cl_mem clCreateFromGLTextureAMD(Context& amdContext, cl_mem_flags flags, GLenum target, GLint miplevel, GLuint texture, int* errcode_ret); cl_mem clCreateFromGLRenderbufferAMD(Context& amdContext, cl_mem_flags flags, GLuint renderbuffer, int* errcode_ret); bool getCLFormatFromGL( const Context& amdContext, GLint gliInternalFormat, cl_image_format* pclImageFormat, int* piBytesPerPixel, cl_mem_flags flags ); } //namespace amd