| @@ -49,10 +49,14 @@ interface | |||||
| {$ENDIF} | {$ENDIF} | ||||
| //check if system is supported and set system dependent constants | //check if system is supported and set system dependent constants | ||||
| {$IFDEF DGL_LINUX} | |||||
| uses | uses | ||||
| dl; | |||||
| sysutils | |||||
| {$IFDEF DGL_LINUX} | |||||
| , dl | |||||
| {$ENDIF} | |||||
| ; | |||||
| {$IFDEF DGL_LINUX} | |||||
| const | const | ||||
| LIBNAME_OPENGLES = 'libGLESv2.so'; | LIBNAME_OPENGLES = 'libGLESv2.so'; | ||||
| LIBNAME_EGL = 'libEGL.so'; | LIBNAME_EGL = 'libEGL.so'; | ||||
| @@ -1550,7 +1554,7 @@ type | |||||
| EGLNativeDisplayType = Pointer; | EGLNativeDisplayType = Pointer; | ||||
| EGLNativePixmapType = Pointer; | EGLNativePixmapType = Pointer; | ||||
| EGLNativeWindowType = packed record | EGLNativeWindowType = packed record | ||||
| element: Cardinal { DispManXElementHandle }; | |||||
| element: Cardinal; | |||||
| width: Integer; | width: Integer; | ||||
| height: Integer; | height: Integer; | ||||
| end; | end; | ||||
| @@ -1816,7 +1820,30 @@ var | |||||
| eglGetProcAddress: TeglGetProcAddress; | eglGetProcAddress: TeglGetProcAddress; | ||||
| { =================================================== DelphiGL ======================================================= } | |||||
| type | |||||
| EdglOpenGLES = class(Exception); | |||||
| EeglError = class(EdglOpenGLES) | |||||
| public | |||||
| ErrorCode: EGLint; | |||||
| constructor Create(const msg: string; const aErrorCode: EGLint); | |||||
| end; | |||||
| TdglRenderContext = packed record | |||||
| Display: EGLDisplay; | |||||
| Surface: EGLSurface; | |||||
| Context: EGLContext; | |||||
| end; | |||||
| function InitOpenGLES(const aOpenGLESLibName: String = LIBNAME_OPENGLES; aEGLLibName: String = LIBNAME_EGL): Boolean; | function InitOpenGLES(const aOpenGLESLibName: String = LIBNAME_OPENGLES; aEGLLibName: String = LIBNAME_EGL): Boolean; | ||||
| function CreateRenderingContext(const aDisplayType: EGLNativeDisplayType; const aWindowType: PEGLNativeWindowType; const aAttributes: PEGLint): TdglRenderContext; | |||||
| procedure DestroyRenderingContext(const aContext: TdglRenderContext); | |||||
| function ActivateRenderingContext(const aContext: TdglRenderContext): Boolean; | |||||
| function DeactivateRenderingContext(const aContext: TdglRenderContext): Boolean; | |||||
| procedure SwapBuffers(const aContext: TdglRenderContext); | |||||
| procedure ReadExtensions; | procedure ReadExtensions; | ||||
| implementation | implementation | ||||
| @@ -1915,6 +1942,72 @@ begin | |||||
| result := false; | result := false; | ||||
| end; | end; | ||||
| procedure RaiseEglError(const aMsg: String); | |||||
| var err: EGLint; | |||||
| begin | |||||
| err := eglGetError(); | |||||
| raise EeglError.Create(aMsg + ' ErrorCode: 0x' + IntToHex(err, 8), err); | |||||
| end; | |||||
| function CreateRenderingContext(const aDisplayType: EGLNativeDisplayType; const aWindowType: PEGLNativeWindowType; const aAttributes: PEGLint): TdglRenderContext; | |||||
| var | |||||
| ConfigCount: EGLint; | |||||
| Config: EGLConfig; | |||||
| begin | |||||
| if (not Assigned(LibHandleOpenGLES) or not Assigned(LibHandleEGL)) and | |||||
| not InitOpenGLES then | |||||
| raise EdglOpenGLES.Create('unable to initialize OpenGL library'); | |||||
| result.Display := eglGetDisplay(aDisplayType); | |||||
| if (result.Display = EGL_NO_DISPLAY) then | |||||
| RaiseEglError('unable to get display.'); | |||||
| if (eglInitialize(result.Display, nil, nil) <> EGL_TRUE) then | |||||
| RaiseEglError('unable to initialize egl.'); | |||||
| if (eglChooseConfig(result.Display, aAttributes, @Config, 1, @ConfigCount) <> EGL_TRUE) or | |||||
| (ConfigCount <> 1) then | |||||
| RaiseEglError('unable to get suitable config.'); | |||||
| result.Surface := eglCreateWindowSurface(result.Display, Config, aWindowType, nil); | |||||
| if (result.Surface = EGL_NO_SURFACE) then | |||||
| RaiseEglError('unable to create window surface.'); | |||||
| result.Context := eglCreateContext(result.Display, Config, EGL_NO_CONTEXT, nil); | |||||
| if (result.Context = EGL_NO_CONTEXT) then begin | |||||
| eglDestroySurface(result.Display, result.Surface); | |||||
| RaiseEglError('unable to create context.'); | |||||
| end; | |||||
| end; | |||||
| procedure DestroyRenderingContext(const aContext: TdglRenderContext); | |||||
| begin | |||||
| if (eglGetCurrentContext = aContext.Context) and | |||||
| not DeactivateRenderingContext(aContext) then | |||||
| RaiseEglError('unable to unbind context.'); | |||||
| if (eglDestroyContext(aContext.Display, aContext.Context) <> EGL_TRUE) then | |||||
| RaiseEglError('unable to destory context.'); | |||||
| if (eglDestroySurface(aContext.Display, aContext.Surface) <> EGL_TRUE) then | |||||
| RaiseEglError('unable to destroy surface.'); | |||||
| end; | |||||
| function ActivateRenderingContext(const aContext: TdglRenderContext): Boolean; | |||||
| begin | |||||
| result := (eglMakeCurrent(aContext.Display, aContext.Surface, aContext.Surface, aContext.Context) = GL_TRUE); | |||||
| end; | |||||
| function DeactivateRenderingContext(const aContext: TdglRenderContext): Boolean; | |||||
| begin | |||||
| result := (eglMakeCurrent(aContext.Display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) = EGL_TRUE); | |||||
| end; | |||||
| procedure SwapBuffers(const aContext: TdglRenderContext); | |||||
| begin | |||||
| eglSwapBuffers(aContext.Display, aContext.Surface); | |||||
| end; | |||||
| procedure ReadExtensions; | procedure ReadExtensions; | ||||
| begin | begin | ||||
| glActiveTexture := dglGetProcAddress('glActiveTexture'); | glActiveTexture := dglGetProcAddress('glActiveTexture'); | ||||
| @@ -2237,5 +2330,11 @@ begin | |||||
| glVertexBindingDivisor := dglGetProcAddress('glVertexBindingDivisor'); | glVertexBindingDivisor := dglGetProcAddress('glVertexBindingDivisor'); | ||||
| end; | end; | ||||
| constructor EeglError.Create(const msg: string; const aErrorCode: EGLint); | |||||
| begin | |||||
| inherited Create(msg); | |||||
| ErrorCode := aErrorCode; | |||||
| end; | |||||
| end. | end. | ||||