| @@ -49,10 +49,14 @@ interface | |||
| {$ENDIF} | |||
| //check if system is supported and set system dependent constants | |||
| {$IFDEF DGL_LINUX} | |||
| uses | |||
| dl; | |||
| sysutils | |||
| {$IFDEF DGL_LINUX} | |||
| , dl | |||
| {$ENDIF} | |||
| ; | |||
| {$IFDEF DGL_LINUX} | |||
| const | |||
| LIBNAME_OPENGLES = 'libGLESv2.so'; | |||
| LIBNAME_EGL = 'libEGL.so'; | |||
| @@ -1550,7 +1554,7 @@ type | |||
| EGLNativeDisplayType = Pointer; | |||
| EGLNativePixmapType = Pointer; | |||
| EGLNativeWindowType = packed record | |||
| element: Cardinal { DispManXElementHandle }; | |||
| element: Cardinal; | |||
| width: Integer; | |||
| height: Integer; | |||
| end; | |||
| @@ -1816,7 +1820,30 @@ var | |||
| 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 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; | |||
| implementation | |||
| @@ -1915,6 +1942,72 @@ begin | |||
| result := false; | |||
| 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; | |||
| begin | |||
| glActiveTexture := dglGetProcAddress('glActiveTexture'); | |||
| @@ -2237,5 +2330,11 @@ begin | |||
| glVertexBindingDivisor := dglGetProcAddress('glVertexBindingDivisor'); | |||
| end; | |||
| constructor EeglError.Create(const msg: string; const aErrorCode: EGLint); | |||
| begin | |||
| inherited Create(msg); | |||
| ErrorCode := aErrorCode; | |||
| end; | |||
| end. | |||