[KMS] Create window surface

This commit is contained in:
thefiddler 2014-06-25 09:01:35 +02:00
parent 6f6798de62
commit 6454822116
7 changed files with 197 additions and 33 deletions

View file

@ -34,6 +34,15 @@ namespace OpenTK.Platform.Egl
{
class EglGraphicsMode
{
public GraphicsMode SelectGraphicsMode(EglWindowInfo window,
GraphicsMode mode, RenderableFlags flags)
{
return SelectGraphicsMode(window,
mode.ColorFormat, mode.Depth, mode.Stencil,
mode.Samples, mode.AccumulatorFormat, mode.Buffers, mode.Stereo,
flags);
}
public GraphicsMode SelectGraphicsMode(EglWindowInfo window,
ColorFormat color, int depth, int stencil,
int samples, ColorFormat accum, int buffers, bool stereo,

View file

@ -75,7 +75,7 @@ namespace OpenTK.Platform.Egl
#region Public Members
public IntPtr Handle { get { return handle; } private set { handle = value; } }
public IntPtr Handle { get { return handle; } set { handle = value; } }
public IntPtr Display { get { return display; } private set { display = value; } }
@ -87,7 +87,7 @@ namespace OpenTK.Platform.Egl
if (Surface==IntPtr.Zero)
{
throw new GraphicsContextException(String.Format(
"[Error] Failed to create EGL window surface, error {0}.", Egl.GetError()));
"[EGL] Failed to create window surface, error {0}.", Egl.GetError()));
}
}

View file

@ -32,21 +32,111 @@ using System.Runtime.InteropServices;
namespace OpenTK.Platform.Linux
{
using GbmDevice = IntPtr; // opaque pointer "struct gbm_device*"
class Gbm
{
const string lib = "gbm";
[DllImport(lib, EntryPoint = "gbm_create_device", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr CreateDevice(int fd);
public static extern GbmDevice CreateDevice(int fd);
[DllImport(lib, EntryPoint = "gbm_surface_create", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr CreateSurface(GbmDevice gbm, int width, int height, SurfaceFormat format, SurfaceFlags flags);
[DllImport(lib, EntryPoint = "gbm_surface_destroy", CallingConvention = CallingConvention.Cdecl)]
public static extern void DestroySurface(IntPtr surface);
[DllImport(lib, EntryPoint = "gbm_device_is_format_supported", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsFormatSupported(GbmDevice gbm, SurfaceFormat format, SurfaceFlags usage);
}
struct GbmDevice
enum SurfaceFormat
{
public int id;
public int fd;
public IntPtr name;
public int refcount;
public Stat stat;
BigEndian = 1 << 31,
C8 = ((int)('C') | ((int)('8') << 8) | ((int)(' ') << 16) | ((int)(' ') << 24)),
RGB332 = ((int)('R') | ((int)('G') << 8) | ((int)('B') << 16) | ((int)('8') << 24)),
BGR233 = ((int)('B') | ((int)('G') << 8) | ((int)('R') << 16) | ((int)('8') << 24)),
XRGB4444 = ((int)('X') | ((int)('R') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
XBGR4444 = ((int)('X') | ((int)('B') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
RGBX4444 = ((int)('R') | ((int)('X') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
BGRX4444 = ((int)('B') | ((int)('X') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
ARGB4444 = ((int)('A') | ((int)('R') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
ABGR4444 = ((int)('A') | ((int)('B') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
RGBA4444 = ((int)('R') | ((int)('A') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
BGRA4444 = ((int)('B') | ((int)('A') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
XRGB1555 = ((int)('X') | ((int)('R') << 8) | ((int)('1') << 16) | ((int)('5') << 24)),
XBGR1555 = ((int)('X') | ((int)('B') << 8) | ((int)('1') << 16) | ((int)('5') << 24)),
RGBX5551 = ((int)('R') | ((int)('X') << 8) | ((int)('1') << 16) | ((int)('5') << 24)),
BGRX5551 = ((int)('B') | ((int)('X') << 8) | ((int)('1') << 16) | ((int)('5') << 24)),
ARGB1555 = ((int)('A') | ((int)('R') << 8) | ((int)('1') << 16) | ((int)('5') << 24)),
ABGR1555 = ((int)('A') | ((int)('B') << 8) | ((int)('1') << 16) | ((int)('5') << 24)),
RGBA5551 = ((int)('R') | ((int)('A') << 8) | ((int)('1') << 16) | ((int)('5') << 24)),
BGRA5551 = ((int)('B') | ((int)('A') << 8) | ((int)('1') << 16) | ((int)('5') << 24)),
RGB565 = ((int)('R') | ((int)('G') << 8) | ((int)('1') << 16) | ((int)('6') << 24)),
BGR565 = ((int)('B') | ((int)('G') << 8) | ((int)('1') << 16) | ((int)('6') << 24)),
RGB888 = ((int)('R') | ((int)('G') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
BGR888 = ((int)('B') | ((int)('G') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
XRGB8888 = ((int)('X') | ((int)('R') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
XBGR8888 = ((int)('X') | ((int)('B') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
RGBX8888 = ((int)('R') | ((int)('X') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
BGRX8888 = ((int)('B') | ((int)('X') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
ARGB8888 = ((int)('A') | ((int)('R') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
ABGR8888 = ((int)('A') | ((int)('B') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
RGBA8888 = ((int)('R') | ((int)('A') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
BGRA8888 = ((int)('B') | ((int)('A') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
XRGB2101010 = ((int)('X') | ((int)('R') << 8) | ((int)('3') << 16) | ((int)('0') << 24)),
XBGR2101010 = ((int)('X') | ((int)('B') << 8) | ((int)('3') << 16) | ((int)('0') << 24)),
RGBX1010102 = ((int)('R') | ((int)('X') << 8) | ((int)('3') << 16) | ((int)('0') << 24)),
BGRX1010102 = ((int)('B') | ((int)('X') << 8) | ((int)('3') << 16) | ((int)('0') << 24)),
ARGB2101010 = ((int)('A') | ((int)('R') << 8) | ((int)('3') << 16) | ((int)('0') << 24)),
ABGR2101010 = ((int)('A') | ((int)('B') << 8) | ((int)('3') << 16) | ((int)('0') << 24)),
RGBA1010102 = ((int)('R') | ((int)('A') << 8) | ((int)('3') << 16) | ((int)('0') << 24)),
BGRA1010102 = ((int)('B') | ((int)('A') << 8) | ((int)('3') << 16) | ((int)('0') << 24)),
YUYV = ((int)('Y') | ((int)('U') << 8) | ((int)('Y') << 16) | ((int)('V') << 24)),
YVYU = ((int)('Y') | ((int)('V') << 8) | ((int)('Y') << 16) | ((int)('U') << 24)),
UYVY = ((int)('U') | ((int)('Y') << 8) | ((int)('V') << 16) | ((int)('Y') << 24)),
VYUY = ((int)('V') | ((int)('Y') << 8) | ((int)('U') << 16) | ((int)('Y') << 24)),
AYUV = ((int)('A') | ((int)('Y') << 8) | ((int)('U') << 16) | ((int)('V') << 24)),
NV12 = ((int)('N') | ((int)('V') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
NV21 = ((int)('N') | ((int)('V') << 8) | ((int)('2') << 16) | ((int)('1') << 24)),
NV16 = ((int)('N') | ((int)('V') << 8) | ((int)('1') << 16) | ((int)('6') << 24)),
NV61 = ((int)('N') | ((int)('V') << 8) | ((int)('6') << 16) | ((int)('1') << 24)),
YUV410 = ((int)('Y') | ((int)('U') << 8) | ((int)('V') << 16) | ((int)('9') << 24)),
YVU410 = ((int)('Y') | ((int)('V') << 8) | ((int)('U') << 16) | ((int)('9') << 24)),
YUV411 = ((int)('Y') | ((int)('U') << 8) | ((int)('1') << 16) | ((int)('1') << 24)),
YVU411 = ((int)('Y') | ((int)('V') << 8) | ((int)('1') << 16) | ((int)('1') << 24)),
YUV420 = ((int)('Y') | ((int)('U') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
YVU420 = ((int)('Y') | ((int)('V') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
YUV422 = ((int)('Y') | ((int)('U') << 8) | ((int)('1') << 16) | ((int)('6') << 24)),
YVU422 = ((int)('Y') | ((int)('V') << 8) | ((int)('1') << 16) | ((int)('6') << 24)),
YUV444 = ((int)('Y') | ((int)('U') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
YVU444 = ((int)('Y') | ((int)('V') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
}
[Flags]
enum SurfaceFlags
{
Scanout = (1 << 0),
Cursor64x64 = (1 << 1),
Rendering = (1 << 2),
Write = (1 << 3),
}
}

View file

@ -75,7 +75,6 @@ namespace OpenTK.Platform.Linux
}
readonly int FD;
readonly GbmDevice Device;
readonly Dictionary<int, int> DisplayIds =
new Dictionary<int, int>();
@ -203,19 +202,16 @@ namespace OpenTK.Platform.Linux
0,
current.Width,
current.Height);
DisplayDevice device = new DisplayDevice(
current,
AvailableDevices.Count == 0,
modes,
bounds,
display);
bool is_primary = AvailableDevices.Count == 0;
DisplayDevice device = new DisplayDevice(current, is_primary,
modes, bounds, display);
if (AvailableDevices.Count == 0)
{
Primary = device;
}
Debug.Print("[KMS] Detected display {0}", device);
AvailableDevices.Add(device);
}

View file

@ -42,7 +42,7 @@ namespace OpenTK.Platform.Linux
class LinuxFactory : PlatformFactoryBase
{
int fd;
GbmDevice gbm_device;
IntPtr gbm_device;
IntPtr display;
IJoystickDriver2 JoystickDriver;
@ -66,15 +66,14 @@ namespace OpenTK.Platform.Linux
}
Debug.Print("[KMS] GPU '{0}' opened as fd:{1}", gpu, fd);
IntPtr dev = Gbm.CreateDevice(fd);
if (dev == IntPtr.Zero)
gbm_device = Gbm.CreateDevice(fd);
if (gbm_device == IntPtr.Zero)
{
throw new NotSupportedException("[KMS] Failed to create GBM device");
}
gbm_device = (GbmDevice)Marshal.PtrToStructure(dev, typeof(GbmDevice));
Debug.Print("[KMS] GBM {0:x} created successfully", dev);
Debug.Print("[KMS] GBM {0:x} created successfully; ", gbm_device);
display = Egl.GetDisplay(dev);
display = Egl.GetDisplay(gbm_device);
if (display == IntPtr.Zero)
{
throw new NotSupportedException("[KMS] Failed to create EGL display");
@ -96,7 +95,7 @@ namespace OpenTK.Platform.Linux
public override INativeWindow CreateNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice display_device)
{
return new LinuxNativeWindow(display, gbm_device, width, height, title, mode, options, display_device);
return new LinuxNativeWindow(display, gbm_device, x, y, width, height, title, mode, options, display_device);
}
public override IDisplayDeviceDriver CreateDisplayDeviceDriver()

View file

@ -28,7 +28,9 @@
#endregion
using System;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using OpenTK.Graphics;
using OpenTK.Platform.Egl;
@ -38,27 +40,89 @@ namespace OpenTK.Platform.Linux
class LinuxNativeWindow : NativeWindowBase
{
LinuxWindowInfo window_info;
LinuxWindowInfo window;
string title;
Icon icon;
bool exists;
Rectangle bounds;
Size client_size;
public LinuxNativeWindow(IntPtr display, GbmDevice device,
int width, int height, string title, GraphicsMode mode, GameWindowFlags options,
public LinuxNativeWindow(IntPtr display, IntPtr gbm,
int x, int y, int width, int height, string title,
GraphicsMode mode, GameWindowFlags options,
DisplayDevice display_device)
{
Debug.Print("[KMS] Creating window on display {0:x}", display);
Title = title;
bounds = new Rectangle(0, 0, width, height);
client_size = bounds.Size;
//window_info = new LinuxWindowInfo(
// Egl.CreateWindowSurface(
window = new LinuxWindowInfo(display);
if (!mode.Index.HasValue)
{
mode = new EglGraphicsMode().SelectGraphicsMode(window, mode, 0);
}
Debug.Print("[KMS] Selected EGL mode {0}", mode);
unsafe
{
SurfaceFormat format = GetSurfaceFormat(mode);
SurfaceFlags usage = SurfaceFlags.Rendering | SurfaceFlags.Scanout;
if (!Gbm.IsFormatSupported(gbm, format, usage))
{
format = SurfaceFormat.XBGR8888;
}
Debug.Print("[KMS] Creating GBM surface on {0:x} with {1}x{2} {3} {4}",
gbm, width, height, format, usage);
IntPtr gbm_surface = Gbm.CreateSurface(gbm,
width, height, format, usage);
if (gbm_surface == IntPtr.Zero)
{
throw new NotSupportedException("[KMS] Failed to create GBM surface for rendering");
}
window.Handle = gbm_surface;
Debug.Print("[KMS] Created GBM surface {0:x}", window.Handle);
}
window.CreateWindowSurface(mode.Index.Value);
Debug.Print("[KMS] Created EGL surface {0:x}", window.Surface);
// Todo: create mouse cursor
exists = true;
}
SurfaceFormat GetSurfaceFormat(GraphicsMode mode)
{
int r = mode.ColorFormat.Red;
int g = mode.ColorFormat.Green;
int b = mode.ColorFormat.Blue;
int a = mode.ColorFormat.Alpha;
if (mode.ColorFormat.IsIndexed)
return SurfaceFormat.C8;
if (r == 3 && g == 3 && b == 2 && a == 0)
return SurfaceFormat.RGB332;
if (r == 5 && g == 6 && b == 5 && a == 0)
return SurfaceFormat.RGB565;
if (r == 5 && g == 6 && b == 5 && a == 0)
return SurfaceFormat.RGB565;
if (r == 8 && g == 8 && b == 8 && a == 0)
return SurfaceFormat.RGB888;
if (r == 5 && g == 5 && b == 5 && a == 1)
return SurfaceFormat.RGBA5551;
if (r == 10 && g == 10 && b == 10 && a == 2)
return SurfaceFormat.RGBA1010102;
if (r == 4 && g == 4 && b == 4 && a == 4)
return SurfaceFormat.RGBA4444;
if (r == 8 && g == 8 && b == 8 && a == 8)
return SurfaceFormat.RGBA8888;
return SurfaceFormat.RGBA8888;
}
#region INativeWindow Members
public override void Close()
@ -80,7 +144,11 @@ namespace OpenTK.Platform.Linux
protected override void Dispose(bool disposing)
{
// Todo
if (disposing)
{
window.Dispose();
Gbm.DestroySurface(window.Handle);
}
}
public override Icon Icon
@ -146,7 +214,7 @@ namespace OpenTK.Platform.Linux
{
get
{
return window_info;
return window;
}
}

View file

@ -34,9 +34,11 @@ namespace OpenTK.Platform.Linux
{
class LinuxWindowInfo : EglWindowInfo
{
public LinuxWindowInfo(IntPtr handle, IntPtr display, IntPtr surface)
: base(handle, display, surface)
public LinuxWindowInfo(IntPtr display)
: base(IntPtr.Zero, display, IntPtr.Zero)
{
// The window handle and surface handle must
// be filled in manually once they are known.
}
}
}