[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 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, public GraphicsMode SelectGraphicsMode(EglWindowInfo window,
ColorFormat color, int depth, int stencil, ColorFormat color, int depth, int stencil,
int samples, ColorFormat accum, int buffers, bool stereo, int samples, ColorFormat accum, int buffers, bool stereo,

View file

@ -75,7 +75,7 @@ namespace OpenTK.Platform.Egl
#region Public Members #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; } } public IntPtr Display { get { return display; } private set { display = value; } }
@ -87,7 +87,7 @@ namespace OpenTK.Platform.Egl
if (Surface==IntPtr.Zero) if (Surface==IntPtr.Zero)
{ {
throw new GraphicsContextException(String.Format( 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 namespace OpenTK.Platform.Linux
{ {
using GbmDevice = IntPtr; // opaque pointer "struct gbm_device*"
class Gbm class Gbm
{ {
const string lib = "gbm"; const string lib = "gbm";
[DllImport(lib, EntryPoint = "gbm_create_device", CallingConvention = CallingConvention.Cdecl)] [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; BigEndian = 1 << 31,
public int fd; C8 = ((int)('C') | ((int)('8') << 8) | ((int)(' ') << 16) | ((int)(' ') << 24)),
public IntPtr name;
public int refcount; RGB332 = ((int)('R') | ((int)('G') << 8) | ((int)('B') << 16) | ((int)('8') << 24)),
public Stat stat; 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 int FD;
readonly GbmDevice Device;
readonly Dictionary<int, int> DisplayIds = readonly Dictionary<int, int> DisplayIds =
new Dictionary<int, int>(); new Dictionary<int, int>();
@ -203,19 +202,16 @@ namespace OpenTK.Platform.Linux
0, 0,
current.Width, current.Width,
current.Height); current.Height);
bool is_primary = AvailableDevices.Count == 0;
DisplayDevice device = new DisplayDevice( DisplayDevice device = new DisplayDevice(current, is_primary,
current, modes, bounds, display);
AvailableDevices.Count == 0,
modes,
bounds,
display);
if (AvailableDevices.Count == 0) if (AvailableDevices.Count == 0)
{ {
Primary = device; Primary = device;
} }
Debug.Print("[KMS] Detected display {0}", device);
AvailableDevices.Add(device); AvailableDevices.Add(device);
} }

View file

@ -42,7 +42,7 @@ namespace OpenTK.Platform.Linux
class LinuxFactory : PlatformFactoryBase class LinuxFactory : PlatformFactoryBase
{ {
int fd; int fd;
GbmDevice gbm_device; IntPtr gbm_device;
IntPtr display; IntPtr display;
IJoystickDriver2 JoystickDriver; IJoystickDriver2 JoystickDriver;
@ -66,15 +66,14 @@ namespace OpenTK.Platform.Linux
} }
Debug.Print("[KMS] GPU '{0}' opened as fd:{1}", gpu, fd); Debug.Print("[KMS] GPU '{0}' opened as fd:{1}", gpu, fd);
IntPtr dev = Gbm.CreateDevice(fd); gbm_device = Gbm.CreateDevice(fd);
if (dev == IntPtr.Zero) if (gbm_device == IntPtr.Zero)
{ {
throw new NotSupportedException("[KMS] Failed to create GBM device"); 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; ", gbm_device);
Debug.Print("[KMS] GBM {0:x} created successfully", dev);
display = Egl.GetDisplay(dev); display = Egl.GetDisplay(gbm_device);
if (display == IntPtr.Zero) if (display == IntPtr.Zero)
{ {
throw new NotSupportedException("[KMS] Failed to create EGL display"); 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) 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() public override IDisplayDeviceDriver CreateDisplayDeviceDriver()

View file

@ -28,7 +28,9 @@
#endregion #endregion
using System; using System;
using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.Runtime.InteropServices;
using OpenTK.Graphics; using OpenTK.Graphics;
using OpenTK.Platform.Egl; using OpenTK.Platform.Egl;
@ -38,27 +40,89 @@ namespace OpenTK.Platform.Linux
class LinuxNativeWindow : NativeWindowBase class LinuxNativeWindow : NativeWindowBase
{ {
LinuxWindowInfo window_info; LinuxWindowInfo window;
string title; string title;
Icon icon; Icon icon;
bool exists; bool exists;
Rectangle bounds; Rectangle bounds;
Size client_size; Size client_size;
public LinuxNativeWindow(IntPtr display, GbmDevice device, public LinuxNativeWindow(IntPtr display, IntPtr gbm,
int width, int height, string title, GraphicsMode mode, GameWindowFlags options, int x, int y, int width, int height, string title,
GraphicsMode mode, GameWindowFlags options,
DisplayDevice display_device) DisplayDevice display_device)
{ {
Debug.Print("[KMS] Creating window on display {0:x}", display);
Title = title; Title = title;
bounds = new Rectangle(0, 0, width, height); bounds = new Rectangle(0, 0, width, height);
client_size = bounds.Size; client_size = bounds.Size;
//window_info = new LinuxWindowInfo( window = new LinuxWindowInfo(display);
// Egl.CreateWindowSurface( 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; 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 #region INativeWindow Members
public override void Close() public override void Close()
@ -80,7 +144,11 @@ namespace OpenTK.Platform.Linux
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
// Todo if (disposing)
{
window.Dispose();
Gbm.DestroySurface(window.Handle);
}
} }
public override Icon Icon public override Icon Icon
@ -146,7 +214,7 @@ namespace OpenTK.Platform.Linux
{ {
get get
{ {
return window_info; return window;
} }
} }

View file

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