/usr/src/castle-game-engine-5.2.0/window/castlewindow_egl.inc is in castle-game-engine-src 5.2.0-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | {
Copyright 2013-2014 Michalis Kamburelis.
This file is part of "Castle Game Engine".
"Castle Game Engine" is free software; see the file COPYING.txt,
included in this distribution, for details about the copyright.
"Castle Game Engine" is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
----------------------------------------------------------------------------
}
{ Use this to make a CastleWindow backend using EGL
(initialize window with OpenGL ES context).
Written based on
http://www.khronos.org/registry/egl/sdk/docs/man/xhtml/eglIntro.html .
See http://www.khronos.org/registry/egl/sdk/docs/man/xhtml/
for an up-to-date reference of EGL.
FPC example in packages/opengles/examples/es2example1.pas was also useful. }
{$ifdef read_interface_uses}
{$endif}
{$ifdef read_window_interface}
private
Context: EGLContext;
Surface: EGLSurface;
Display: EGLDisplay;
{$ifdef CASTLE_WINDOW_XLIB}
{ GL context creation before creating native window. }
procedure ContextCreateBegin(var Attr: TXSetWindowAttributes;
var AttrValueMask: Cardinal);
{$endif}
{ GL context creation after creating native window. }
procedure ContextCreateEnd(WndPtr: EGLNativeWindowType);
{ Destroy context created by ContextCreateBegin + ContextCreateEnd. }
procedure ContextDestroy;
public
{ Query the EGL context what is current size. }
procedure QuerySize(out AWidth, AHeight: EGLint);
{$endif}
{$ifdef read_application_interface}
private
{$ifdef CASTLE_WINDOW_XLIB}
{ Check is context creation possible. XDisplay is available now. }
procedure ContextApplicationCheck;
{$endif}
{$endif}
{$ifdef read_implementation}
{$ifdef CASTLE_WINDOW_XLIB}
procedure TCastleWindowCustom.ContextCreateBegin(var Attr: TXSetWindowAttributes;
var AttrValueMask: Cardinal);
begin
end;
{$endif}
{ EGL error codes and descriptions from
http://www.khronos.org/registry/egl/sdk/docs/man/xhtml/eglGetError.html }
function EGLError: string;
var
ErrorCode: EGLint;
begin
ErrorCode := eglGetError();
case ErrorCode of
EGL_SUCCESS: Result := 'The last function succeeded without error.';
EGL_NOT_INITIALIZED: Result := 'EGL is not initialized, or could not be initialized, for the specified EGL display connection.';
EGL_BAD_ACCESS: Result := 'EGL cannot access a requested resource (for example a context is bound in another thread).';
EGL_BAD_ALLOC: Result := 'EGL failed to allocate resources for the requested operation.';
EGL_BAD_ATTRIBUTE: Result := 'An unrecognized attribute or attribute value was passed in the attribute list.';
EGL_BAD_CONTEXT: Result := 'An EGLContext argument does not name a valid EGL rendering context.';
EGL_BAD_CONFIG: Result := 'An EGLConfig argument does not name a valid EGL frame buffer configuration.';
EGL_BAD_CURRENT_SURFACE: Result := 'The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid.';
EGL_BAD_DISPLAY: Result := 'An EGLDisplay argument does not name a valid EGL display connection.';
EGL_BAD_SURFACE: Result := 'An EGLSurface argument does not name a valid surface (window, pixel buffer or pixmap) configured for GL rendering.';
EGL_BAD_MATCH: Result := 'Arguments are inconsistent (for example, a valid context requires buffers not supplied by a valid surface).';
EGL_BAD_PARAMETER: Result := 'One or more argument values are invalid.';
EGL_BAD_NATIVE_PIXMAP: Result := 'A NativePixmapType argument does not refer to a valid native pixmap.';
EGL_BAD_NATIVE_WINDOW: Result := 'A NativeWindowType argument does not refer to a valid native window.';
EGL_CONTEXT_LOST: Result := 'A power management event has occurred. The application must destroy all contexts and reinitialise OpenGL ES state and objects to continue rendering.';
else Result := Format('EGL error %d', [ErrorCode]);
end;
end;
procedure TCastleWindowCustom.ContextCreateEnd(WndPtr: EGLNativeWindowType);
var
Config: EGLConfig;
ShareContext: EGLContext;
NumConfig: EGLint;
Attribs: TLongIntList;
const
ContextAttribs: array [0..2] of EGLint =
( EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE);
begin
Display := eglGetDisplay(EGL_DEFAULT_DISPLAY);
if Display = EGL_NO_DISPLAY then
{ This does not set eglGetError, so we don't use EGLError in message below. }
raise EGLContextNotPossible.Create('EGL: Cannot get display');
if eglInitialize(Display, nil, nil) = EGL_FALSE then
raise EGLContextNotPossible.Create('EGL: Cannot initialize: ' + EGLError);
Attribs := TLongIntList.Create;
try
if StencilBits > 0 then
Attribs.AddArray([EGL_STENCIL_SIZE, StencilBits]);
if AlphaBits > 0 then
Attribs.AddArray([EGL_ALPHA_SIZE, AlphaBits]);
Attribs.AddArray([
EGL_DEPTH_SIZE, DepthBits,
EGL_RED_SIZE , Max(1, RedBits),
EGL_GREEN_SIZE, Max(1, GreenBits),
EGL_BLUE_SIZE , Max(1, BlueBits),
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
]);
if eglChooseConfig(Display, PEGLint(Attribs.List), @Config, 1, @NumConfig) = EGL_FALSE then
raise EGLContextNotPossible.Create('EGL: Cannot choose config: ' + EGLError);
finally FreeAndNil(Attribs) end;
if Application.FOpenWindows.Count <> 0 then
ShareContext := Application.FOpenWindows[0].Context else
ShareContext := EGL_NO_CONTEXT;
Context := eglCreateContext(Display, Config, ShareContext, @ContextAttribs);
if Context = EGL_NO_CONTEXT then
raise EGLContextNotPossible.Create('EGL: Cannot create context: ' + EGLError);
Surface := eglCreateWindowSurface(Display, Config, WndPtr, nil);
if Surface = EGL_NO_SURFACE then
raise EGLContextNotPossible.Create('EGL: Cannot create surface: ' + EGLError);
end;
procedure TCastleWindowCustom.ContextDestroy;
begin
if Surface <> EGL_NO_SURFACE { nil } then
begin
if eglDestroySurface(Display, Surface) = EGL_FALSE then
OnWarning(wtMinor, 'EGL', 'Cannot destroy surface: ' + EGLError);
Surface := EGL_NO_SURFACE;
end;
if Display <> EGL_NO_DISPLAY { nil } then
begin
{ Release the current context, to allow eglTerminate to release resources.
This allows on Android to reopen OpenGL context from the application
(like android_demo ReopenContextButton). }
if eglMakeCurrent(Display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) = EGL_FALSE then
OnWarning(wtMinor, 'EGL', 'Cannot release current context: ' + EGLError);
if eglTerminate(Display) = EGL_FALSE then
OnWarning(wtMinor, 'EGL', 'Cannot terminate display connection: ' + EGLError);
Display := EGL_NO_DISPLAY;
end;
end;
procedure TCastleWindowCustom.BackendMakeCurrent;
begin
Assert(not Closed);
if eglMakeCurrent(Display, Surface, Surface, Context) = EGL_FALSE then
OnWarning(wtMinor, 'EGL', 'Cannot make context current: ' + EGLError);
end;
procedure TCastleWindowCustom.SwapBuffers;
begin
if eglSwapBuffers(Display, Surface) = EGL_FALSE then
OnWarning(wtMinor, 'EGL', 'Cannot swap buffers: ' + EGLError);
end;
procedure TCastleWindowCustom.QuerySize(out AWidth, AHeight: EGLint);
begin
if eglQuerySurface(Display, Surface, EGL_WIDTH, @AWidth) = EGL_FALSE then
OnWarning(wtMinor, 'EGL', 'Cannot query surface width: ' + EGLError);
if eglQuerySurface(Display, Surface, EGL_HEIGHT, @AHeight) = EGL_FALSE then
OnWarning(wtMinor, 'EGL', 'Cannot query surface height: ' + EGLError);
end;
{$ifdef CASTLE_WINDOW_XLIB}
procedure TCastleApplication.ContextApplicationCheck;
begin
end;
{$endif}
{$endif read_implementation}
|