Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial EGL Support for X11 #2

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@


### VisualStudioCode ###
.vscode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
Expand Down
165 changes: 165 additions & 0 deletions SPB/Platform/EGL/EGL.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
using System;
using System.Runtime.InteropServices;

using Display = System.IntPtr;
using Config = System.IntPtr;
using Surface = System.IntPtr;
using Context = System.IntPtr;
using System.Runtime.Versioning;

namespace SPB.Platform.EGL
{
[SupportedOSPlatform("linux")]
internal sealed class EGL
{
private const string LibraryName = "libEGL.dll";

static EGL()
{
NativeLibrary.SetDllImportResolver(typeof(EGL).Assembly, (name, assembly, path) =>
{
if (name != LibraryName)
{
return IntPtr.Zero;
}

if (!NativeLibrary.TryLoad("libEGL.so.1", assembly, path, out IntPtr result))
{
if (!NativeLibrary.TryLoad("libEGL.so", assembly, path, out result))
{
return IntPtr.Zero;
}
}

return result;
});
}

[DllImport(LibraryName, EntryPoint = "eglChooseConfig")]
public unsafe extern static uint ChooseConfig(Display display, int* attributes, Config* configs, int config_size, int* num_config);

[DllImport(LibraryName, EntryPoint = "eglGetConfigAttrib")]
public unsafe extern static uint GetConfigAttrib(Display display, Config config, int attribute, out int value);

[DllImport(LibraryName, EntryPoint = "eglDestroyContext")]
public static extern uint DestroyContext(Display display, Context context);

[DllImport(LibraryName, EntryPoint = "eglGetCurrentContext")]
public static extern Context GetCurrentContext();

[DllImport(LibraryName, EntryPoint = "eglSwapBuffers")]
public static extern uint SwapBuffers(Display display, Surface drawable);

[DllImport(LibraryName, EntryPoint = "eglMakeCurrent")]
public static extern uint MakeCurrent(Display display, Surface drawable, Surface readable, Context context);

[DllImport(LibraryName, EntryPoint = "eglBindAPI")]
public static extern uint BindApi(int api);

[DllImport(LibraryName, EntryPoint = "eglInitialize")]
public static extern uint Initialize(Display display, IntPtr major, IntPtr minor);

[DllImport(LibraryName, EntryPoint = "eglGetPlatformDisplay")]
public unsafe static extern Display GetPlatformDisplay(int platform, IntPtr nativeDisplay, IntPtr* attribList);

[DllImport(LibraryName, EntryPoint = "eglCreateWindowSurface")]
public unsafe static extern Surface CreateWindowSurface(Display display, Config config, IntPtr nativeWindow, IntPtr* attribList);

[DllImport(LibraryName, EntryPoint = "eglDestroySurface")]
public unsafe static extern uint DestroySurface(Display display, Surface surface);

[DllImport(LibraryName, EntryPoint = "eglGetError")]
public static extern int GetError();

internal enum Attribute : int
{
OPENGL_API = 0x30A2,
COLOR_BUFFER_TYPE = 0x303F,
RGB_BUFFER = 0x308E,
CONFIG_CAVEAT = 0x3027,
RENDERABLE_TYPE = 0x3040,
NATIVE_VISUAL_ID = 0x302E,
PLATFORM_X11_KHR = 0x31D5,
OPENGL_BIT = 0x0008,
CONFORMANT = 0x3042,
RED_SIZE = 0x3024,
GREEN_SIZE = 0x3023,
BLUE_SIZE = 0x3022,
ALPHA_SIZE = 0x3021,
DEPTH_SIZE = 0x3025,
STENCIL_SIZE = 0x3026,
SAMPLE_BUFFERS = 0x3032,
SAMPLES = 0x3031,
SURFACE_TYPE = 0x3033,
WINDOW_BIT = 0x4,
PBUFFER_BIT = 0x0001,
NONE = 0x3038
}

internal enum RenderTypeMask : int
{
COLOR_INDEX_BIT_SGIX = 0x00000002,
RGBA_BIT = 0x00000001,
RGBA_FLOAT_BIT_ARB = 0x00000004,
RGBA_BIT_SGIX = 0x00000001,
COLOR_INDEX_BIT = 0x00000002,
}

public enum ErrorCode : int
{
EGL_SUCCESS = 0x3000,
EGL_NOT_INITIALIZED = 0x3001,
EGL_BAD_ACCESS = 0x3002,
EGL_BAD_ALLOC = 0x3003,
EGL_BAD_ATTRIBUTE = 0x3004,
EGL_BAD_CONFIG = 0x3005,
EGL_BAD_CONTEXT = 0x3006,
EGL_BAD_CURRENT_SURFACE = 0x3007,
EGL_BAD_DISPLAY = 0x3008,
EGL_BAD_MATCH = 0x3009,
EGL_BAD_NATIVE_PIXMAP = 0x300A,
EGL_BAD_NATIVE_WINDOW = 0x300B,
EGL_BAD_PARAMETER = 0x300C,
EGL_BAD_SURFACE = 0x300D,
EGL_CONTEXT_LOST = 0x300E
}


rupansh marked this conversation as resolved.
Show resolved Hide resolved

internal sealed class ARB
{
public enum ContextFlags : int
{
DEBUG = 0x31B0
}

public enum ContextProfileFlags : int
{
CORE_PROFILE = 0x1,
COMPATIBILITY_PROFILE = 0x2,
}

public enum CreateContextAttr : int
{
MAJOR_VERSION = 0x3098,
MINOR_VERSION = 0x30FB,
FLAGS = 0x30FC,
PROFILE_MASK = 0x30FD,
}

[DllImport(LibraryName, EntryPoint = "eglGetProcAddress")]
public static extern IntPtr GetProcAddress(string procName);


[DllImport(LibraryName, EntryPoint = "eglCreateContext")]
public static extern Context CreateContext(Display display, Config config, Context shareContext, int[] attributes);
}

internal sealed class Ext
{
[DllImport(LibraryName, EntryPoint = "eglSwapInterval")]
public static extern ErrorCode SwapInterval(Display display, int interval);
}

}
}
159 changes: 159 additions & 0 deletions SPB/Platform/EGL/EGLHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
using System;
rupansh marked this conversation as resolved.
Show resolved Hide resolved
using System.Collections.Generic;
using System.Runtime.Versioning;
using SPB.Graphics;
using SPB.Graphics.OpenGL;

namespace SPB.Platform.EGL
{
[SupportedOSPlatform("linux")]
public sealed class EGLHelper
{
public static IntPtr _eglDisplay;
private static bool init;

public IntPtr eglDisplay {
get {
return _eglDisplay;
}
}

public EGLHelper(IntPtr display) {
if (!init) {
unsafe {
_eglDisplay = EGL.GetPlatformDisplay((int)EGL.Attribute.PLATFORM_X11_KHR, display, (IntPtr *)IntPtr.Zero.ToPointer());
}
EGL.Initialize(eglDisplay, IntPtr.Zero, IntPtr.Zero);
init = true;
}
}

public static void BindApi() {
EGL.BindApi((int) EGL.Attribute.OPENGL_API);
}

public static List<int> FramebufferFormatToVisualAttribute(FramebufferFormat format)
{
List<int> result = new List<int>();

result.Add((int)EGL.Attribute.COLOR_BUFFER_TYPE);
result.Add((int)EGL.Attribute.RGB_BUFFER);

result.Add((int)EGL.Attribute.SURFACE_TYPE);
result.Add((int)EGL.Attribute.WINDOW_BIT);

result.Add((int)EGL.Attribute.RENDERABLE_TYPE);
result.Add((int)EGL.Attribute.OPENGL_BIT);
result.Add((int)EGL.Attribute.CONFORMANT);
result.Add((int)EGL.Attribute.OPENGL_BIT);

result.Add((int)EGL.Attribute.CONFIG_CAVEAT);
result.Add((int)EGL.Attribute.NONE);

if (format.Color.BitsPerPixel > 0)
{
result.Add((int)EGL.Attribute.RED_SIZE);
result.Add(format.Color.Red);

result.Add((int)EGL.Attribute.GREEN_SIZE);
result.Add(format.Color.Green);

result.Add((int)EGL.Attribute.BLUE_SIZE);
result.Add(format.Color.Blue);

result.Add((int)EGL.Attribute.ALPHA_SIZE);
result.Add(format.Color.Alpha);
}

if (format.DepthBits > 0)
{
result.Add((int)EGL.Attribute.DEPTH_SIZE);
result.Add(format.DepthBits);
}

if (format.StencilBits > 0)
{
result.Add((int)EGL.Attribute.STENCIL_SIZE);
result.Add(format.StencilBits);
}

if (format.Samples > 0)
{
result.Add((int)EGL.Attribute.SAMPLES);
result.Add((int)format.Samples);
}

result.Add((int)EGL.Attribute.NONE);

return result;
}

public unsafe IntPtr eglWindowSurface(IntPtr nativeWindowHandle, IntPtr fbConfig) {
return EGL.CreateWindowSurface(eglDisplay, fbConfig, nativeWindowHandle, (IntPtr *)IntPtr.Zero.ToPointer());
}

public IntPtr SelectFBConfig(FramebufferFormat format)
{
List<int> visualAttribute = FramebufferFormatToVisualAttribute(format);

IntPtr result = IntPtr.Zero;

unsafe
{
int configCnt = 0;
int[] attribs = visualAttribute.ToArray();

fixed (int* attr = &attribs[0]) {
uint res = EGL.ChooseConfig(eglDisplay, attr, (IntPtr *)IntPtr.Zero.ToPointer(), 0, &configCnt);

if (configCnt == 0 || res == 0)
{
return IntPtr.Zero;
}

fixed (IntPtr* fbConfig = new IntPtr[configCnt]) {
EGL.ChooseConfig(eglDisplay, attr, fbConfig, configCnt, &configCnt);
result = fbConfig[0];
}
}
}

return result;
}

public List<int> GetContextCreationARBAttribute(OpenGLContextBase context)
{
List<int> result = new List<int>();

result.Add((int)EGL.ARB.CreateContextAttr.MAJOR_VERSION);
result.Add(context.Major);

result.Add((int)EGL.ARB.CreateContextAttr.MINOR_VERSION);
result.Add(context.Minor);

if (context.Flags != 0)
{
if (context.Flags.HasFlag(OpenGLContextFlags.Debug))
{
result.Add((int)EGL.ARB.ContextFlags.DEBUG);
result.Add(1);
}

result.Add((int)EGL.ARB.CreateContextAttr.PROFILE_MASK);

if (context.Flags.HasFlag(OpenGLContextFlags.Compat))
{
result.Add((int)EGL.ARB.ContextProfileFlags.COMPATIBILITY_PROFILE);
}
else
{
result.Add((int)EGL.ARB.ContextProfileFlags.CORE_PROFILE);
}
}

result.Add((int)EGL.Attribute.NONE);

return result;
}
}
}
Loading