Clean up initial OpenGL passes

This commit is contained in:
Yoshi Askharoun
2026-07-25 19:32:47 -05:00
parent 2bd15a4562
commit b20af287ea
11 changed files with 109 additions and 336 deletions
@@ -52,7 +52,7 @@ namespace Microsoft.Iris.Render.OpenGL
public override void Play() public override void Play()
{ {
base.Play(); base.Play();
foreach (GLAnimation a in m_members) foreach (var a in m_members)
a.Play(); a.Play();
} }
@@ -60,7 +60,7 @@ namespace Microsoft.Iris.Render.OpenGL
internal override void Advance(int advanceMs) internal override void Advance(int advanceMs)
{ {
foreach (GLAnimation a in m_members) foreach (var a in m_members)
a.Advance(advanceMs); a.Advance(advanceMs);
} }
} }
@@ -36,23 +36,18 @@ namespace Microsoft.Iris.Render.OpenGL
{ {
if (m_paused) if (m_paused)
return; return;
int scaled = (int)(nAdvanceMs * SpeedAdjustment);
foreach (GLAnimation a in m_animations) var scaled = (int)(nAdvanceMs * SpeedAdjustment);
{ StepAnimations(scaled);
if (a.IsPlaying)
a.Advance(scaled);
}
} }
public void PauseAnimations() => m_paused = true; public void PauseAnimations() => m_paused = true;
public void StepAnimations(int nAdvanceMs) public void StepAnimations(int nAdvanceMs)
{ {
foreach (GLAnimation a in m_animations) foreach (var a in m_animations)
{
if (a.IsPlaying) if (a.IsPlaying)
a.Advance(nAdvanceMs); a.Advance(nAdvanceMs);
}
} }
public void ResumeAnimations() => m_paused = false; public void ResumeAnimations() => m_paused = false;
+5 -7
View File
@@ -9,8 +9,6 @@ namespace Microsoft.Iris.Render.OpenGL
/// </summary> /// </summary>
public sealed class GLDisplay : IDisplay public sealed class GLDisplay : IDisplay
{ {
private readonly DisplayMode m_mode;
public GLDisplay(IMonitor monitor, bool isPrimary) public GLDisplay(IMonitor monitor, bool isPrimary)
{ {
DeviceName = monitor.Name ?? $"Monitor{monitor.Index}"; DeviceName = monitor.Name ?? $"Monitor{monitor.Index}";
@@ -21,7 +19,7 @@ namespace Microsoft.Iris.Render.OpenGL
var size = new Size(b.Size.X, b.Size.Y); var size = new Size(b.Size.X, b.Size.Y);
LogicalFullScreenResolution = size; LogicalFullScreenResolution = size;
m_mode = new DisplayMode CurrentMode = new DisplayMode
{ {
sizePhysicalPxl = size, sizePhysicalPxl = size,
sizeLogicalPxl = size, sizeLogicalPxl = size,
@@ -39,11 +37,11 @@ namespace Microsoft.Iris.Render.OpenGL
public bool TvMode => false; public bool TvMode => false;
public Size LogicalFullScreenResolution { get; } public Size LogicalFullScreenResolution { get; }
public DisplayMode[] SupportedModes => new[] { m_mode }; public DisplayMode[] SupportedModes => new[] { CurrentMode };
public DisplayMode[] ExtraModes => DisplayMode.EmptyModes; public DisplayMode[] ExtraModes => DisplayMode.EmptyModes;
public DisplayMode[] AllModes => SupportedModes; public DisplayMode[] AllModes => SupportedModes;
public DisplayMode CurrentMode => m_mode; public DisplayMode CurrentMode { get; }
public DisplayMode DesktopMode => m_mode; public DisplayMode DesktopMode => CurrentMode;
public string MonitorPnP => DeviceName; public string MonitorPnP => DeviceName;
public bool ValidateDisplayMode( public bool ValidateDisplayMode(
@@ -54,7 +52,7 @@ namespace Microsoft.Iris.Render.OpenGL
out DisplayModeFlags nCompleteCheck) out DisplayModeFlags nCompleteCheck)
{ {
// We only expose the desktop mode, so echo it back as the completed mode. // We only expose the desktop mode, so echo it back as the completed mode.
modeComplete = m_mode; modeComplete = CurrentMode;
nCompleteCheck = nCheck; nCompleteCheck = nCheck;
return true; return true;
} }
@@ -33,11 +33,10 @@ namespace Microsoft.Iris.Render.OpenGL
public IDisplay DisplayFromDeviceName(string stDeviceName) public IDisplay DisplayFromDeviceName(string stDeviceName)
{ {
foreach (GLDisplay d in m_displays) foreach (var d in m_displays)
{
if (d.DeviceName == stDeviceName) if (d.DeviceName == stDeviceName)
return d; return d;
}
return PrimaryDisplay; return PrimaryDisplay;
} }
} }
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Microsoft.Iris.Input; using Microsoft.Iris.Input;
using Silk.NET.Input; using Silk.NET.Input;
using SilkKey = Silk.NET.Input.Key; using SilkKey = Silk.NET.Input.Key;
@@ -37,9 +38,9 @@ namespace Microsoft.Iris.Render.OpenGL
m_input = input; m_input = input;
m_window = window; m_window = window;
foreach (IKeyboard keyboard in context.Keyboards) foreach (var keyboard in context.Keyboards)
Hook(keyboard); Hook(keyboard);
foreach (IMouse mouse in context.Mice) foreach (var mouse in context.Mice)
Hook(mouse); Hook(mouse);
context.ConnectionChanged += OnConnectionChanged; context.ConnectionChanged += OnConnectionChanged;
@@ -120,7 +121,14 @@ namespace Microsoft.Iris.Render.OpenGL
private void OnMouseDown(IMouse mouse, SilkMouseButton button) private void OnMouseDown(IMouse mouse, SilkMouseButton button)
{ {
(uint message, MouseButtons iris) = button switch var message = MapSilkMouseButton(button, out var iris);
if (message != 0)
DispatchMouse(mouse, message, iris, 0);
}
private static uint MapSilkMouseButton(SilkMouseButton button, out MouseButtons iris)
{
(var message, iris) = button switch
{ {
SilkMouseButton.Left => (WM_LBUTTONDOWN, MouseButtons.Left), SilkMouseButton.Left => (WM_LBUTTONDOWN, MouseButtons.Left),
SilkMouseButton.Right => (WM_RBUTTONDOWN, MouseButtons.Right), SilkMouseButton.Right => (WM_RBUTTONDOWN, MouseButtons.Right),
@@ -129,36 +137,19 @@ namespace Microsoft.Iris.Render.OpenGL
SilkMouseButton.Button5 => (WM_XBUTTONDOWN, MouseButtons.XButton2), SilkMouseButton.Button5 => (WM_XBUTTONDOWN, MouseButtons.XButton2),
_ => (0u, MouseButtons.None), _ => (0u, MouseButtons.None),
}; };
if (message != 0) return message;
DispatchMouse(mouse, message, iris, 0);
} }
private void OnMouseUp(IMouse mouse, SilkMouseButton button) private void OnMouseUp(IMouse mouse, SilkMouseButton button)
{ {
(uint message, MouseButtons iris) = button switch var message = MapSilkMouseButton(button, out var iris);
{
SilkMouseButton.Left => (WM_LBUTTONUP, MouseButtons.Left),
SilkMouseButton.Right => (WM_RBUTTONUP, MouseButtons.Right),
SilkMouseButton.Middle => (WM_MBUTTONUP, MouseButtons.Middle),
SilkMouseButton.Button4 => (WM_XBUTTONUP, MouseButtons.XButton1),
SilkMouseButton.Button5 => (WM_XBUTTONUP, MouseButtons.XButton2),
_ => (0u, MouseButtons.None),
};
if (message != 0) if (message != 0)
DispatchMouse(mouse, message, iris, 0); DispatchMouse(mouse, message, iris, 0);
} }
private void OnDoubleClick(IMouse mouse, SilkMouseButton button, System.Numerics.Vector2 position) private void OnDoubleClick(IMouse mouse, SilkMouseButton button, System.Numerics.Vector2 position)
{ {
(uint message, MouseButtons iris) = button switch var message = MapSilkMouseButton(button, out var iris);
{
SilkMouseButton.Left => (WM_LBUTTONDBLCLK, MouseButtons.Left),
SilkMouseButton.Right => (WM_RBUTTONDBLCLK, MouseButtons.Right),
SilkMouseButton.Middle => (WM_MBUTTONDBLCLK, MouseButtons.Middle),
SilkMouseButton.Button4 => (WM_XBUTTONDBLCLK, MouseButtons.XButton1),
SilkMouseButton.Button5 => (WM_XBUTTONDBLCLK, MouseButtons.XButton2),
_ => (0u, MouseButtons.None),
};
if (message != 0) if (message != 0)
DispatchMouse(mouse, message, iris, 0, doubleClick: true); DispatchMouse(mouse, message, iris, 0, doubleClick: true);
} }
@@ -216,41 +207,53 @@ namespace Microsoft.Iris.Render.OpenGL
InputModifiers m = InputModifiers.None; InputModifiers m = InputModifiers.None;
foreach (IKeyboard k in m_context.Keyboards) foreach (IKeyboard k in m_context.Keyboards)
{ {
if (k.IsKeyPressed(SilkKey.ControlLeft) || k.IsKeyPressed(SilkKey.ControlRight)) m |= InputModifiers.ControlKey; if (k.IsKeyPressed(SilkKey.ControlLeft) || k.IsKeyPressed(SilkKey.ControlRight))
if (k.IsKeyPressed(SilkKey.ShiftLeft) || k.IsKeyPressed(SilkKey.ShiftRight)) m |= InputModifiers.ShiftKey; m |= InputModifiers.ControlKey;
if (k.IsKeyPressed(SilkKey.AltLeft) || k.IsKeyPressed(SilkKey.AltRight)) m |= InputModifiers.AltKey;
if (k.IsKeyPressed(SilkKey.SuperLeft) || k.IsKeyPressed(SilkKey.SuperRight)) m |= InputModifiers.WindowsKey; if (k.IsKeyPressed(SilkKey.ShiftLeft) || k.IsKeyPressed(SilkKey.ShiftRight))
m |= InputModifiers.ShiftKey;
if (k.IsKeyPressed(SilkKey.AltLeft) || k.IsKeyPressed(SilkKey.AltRight))
m |= InputModifiers.AltKey;
if (k.IsKeyPressed(SilkKey.SuperLeft) || k.IsKeyPressed(SilkKey.SuperRight))
m |= InputModifiers.WindowsKey;
} }
mouse ??= FirstMouse(); mouse ??= FirstMouse();
if (mouse != null) if (mouse != null)
{ {
if (mouse.IsButtonPressed(SilkMouseButton.Left)) m |= InputModifiers.LeftMouse; if (mouse.IsButtonPressed(SilkMouseButton.Left))
if (mouse.IsButtonPressed(SilkMouseButton.Right)) m |= InputModifiers.RightMouse; m |= InputModifiers.LeftMouse;
if (mouse.IsButtonPressed(SilkMouseButton.Middle)) m |= InputModifiers.MiddleMouse;
if (mouse.IsButtonPressed(SilkMouseButton.Button4)) m |= InputModifiers.XMouse1; if (mouse.IsButtonPressed(SilkMouseButton.Right))
if (mouse.IsButtonPressed(SilkMouseButton.Button5)) m |= InputModifiers.XMouse2; m |= InputModifiers.RightMouse;
if (mouse.IsButtonPressed(SilkMouseButton.Middle))
m |= InputModifiers.MiddleMouse;
if (mouse.IsButtonPressed(SilkMouseButton.Button4))
m |= InputModifiers.XMouse1;
if (mouse.IsButtonPressed(SilkMouseButton.Button5))
m |= InputModifiers.XMouse2;
} }
return m; return m;
} }
private IMouse? FirstMouse() private IMouse? FirstMouse() => m_context.Mice.Count > 0 ? m_context.Mice[0] : null;
{
foreach (IMouse mouse in m_context.Mice)
return mouse;
return null;
}
public void Dispose() public void Dispose()
{ {
m_context.ConnectionChanged -= OnConnectionChanged; m_context.ConnectionChanged -= OnConnectionChanged;
foreach (IKeyboard keyboard in m_context.Keyboards) foreach (var keyboard in m_context.Keyboards)
{ {
keyboard.KeyDown -= OnKeyDown; keyboard.KeyDown -= OnKeyDown;
keyboard.KeyUp -= OnKeyUp; keyboard.KeyUp -= OnKeyUp;
keyboard.KeyChar -= OnKeyChar; keyboard.KeyChar -= OnKeyChar;
} }
foreach (IMouse mouse in m_context.Mice) foreach (var mouse in m_context.Mice)
{ {
mouse.MouseMove -= OnMouseMove; mouse.MouseMove -= OnMouseMove;
mouse.MouseDown -= OnMouseDown; mouse.MouseDown -= OnMouseDown;
+2 -13
View File
@@ -12,20 +12,9 @@ namespace Microsoft.Iris.Render.OpenGL
/// <summary>Create an OpenGL render engine for the given Iris engine info.</summary> /// <summary>Create an OpenGL render engine for the given Iris engine info.</summary>
public static IRenderEngine CreateEngine(IrisEngineInfo engineInfo, IRenderHost renderHost) public static IRenderEngine CreateEngine(IrisEngineInfo engineInfo, IRenderHost renderHost)
{ {
if (engineInfo == null) throw new ArgumentNullException(nameof(engineInfo)); ArgumentNullException.ThrowIfNull(engineInfo);
if (renderHost == null) throw new ArgumentNullException(nameof(renderHost)); ArgumentNullException.ThrowIfNull(renderHost);
return new GLRenderEngine(engineInfo, renderHost); return new GLRenderEngine(engineInfo, renderHost);
} }
/// <summary>
/// Convenience overload matching <c>RenderApi.CreateEngine</c>'s signature.
/// Only <see cref="IrisEngineInfo"/> is supported (the sole EngineType).
/// </summary>
public static IRenderEngine CreateEngine(EngineInfo engineInfo, IRenderHost renderHost)
{
if (engineInfo is not IrisEngineInfo iris)
throw new ArgumentException("Only IrisEngineInfo is supported.", nameof(engineInfo));
return CreateEngine(iris, renderHost);
}
} }
} }
+37 -31
View File
@@ -10,38 +10,44 @@ namespace Microsoft.Iris.Render.OpenGL
/// </summary> /// </summary>
internal sealed unsafe class SceneRenderer : IDisposable internal sealed unsafe class SceneRenderer : IDisposable
{ {
private const string VertexSource = @"#version 330 core private const string VertexSource =
layout(location = 0) in vec2 aPos; """
layout(location = 1) in vec2 aTex; #version 330 core
uniform mat4 uModel; layout(location = 0) in vec2 aPos;
uniform mat4 uProj; layout(location = 1) in vec2 aTex;
uniform vec2 uSize; uniform mat4 uModel;
out vec2 vTex; uniform mat4 uProj;
void main() uniform vec2 uSize;
{ out vec2 vTex;
vTex = aTex; void main()
gl_Position = uProj * uModel * vec4(aPos * uSize, 0.0, 1.0); {
}"; vTex = aTex;
gl_Position = uProj * uModel * vec4(aPos * uSize, 0.0, 1.0);
}
""";
private const string FragmentSource = @"#version 330 core private const string FragmentSource =
in vec2 vTex; """
out vec4 fragColor; #version 330 core
uniform sampler2D uTex; in vec2 vTex;
uniform int uUseTexture; out vec4 fragColor;
uniform vec4 uColor; uniform sampler2D uTex;
uniform float uAlpha; uniform int uUseTexture;
void main() uniform vec4 uColor;
{ uniform float uAlpha;
if (uUseTexture == 1) void main()
{ {
vec4 t = texture(uTex, vTex); if (uUseTexture == 1)
fragColor = vec4(t.rgb, t.a * uAlpha); {
} vec4 t = texture(uTex, vTex);
else fragColor = vec4(t.rgb, t.a * uAlpha);
{ }
fragColor = vec4(uColor.rgb, uColor.a * uAlpha); else
} {
}"; fragColor = vec4(uColor.rgb, uColor.a * uAlpha);
}
}
""";
private readonly GL m_gl; private readonly GL m_gl;
private readonly uint m_program; private readonly uint m_program;
+1 -1
View File
@@ -55,7 +55,7 @@ namespace Microsoft.Iris.Render.OpenGL
{ {
get get
{ {
foreach (object v in m_values.Values) foreach (var v in m_values.Values)
{ {
if (v is GLImage img) if (v is GLImage img)
return img; return img;
+5 -6
View File
@@ -77,16 +77,15 @@ namespace Microsoft.Iris.Render.OpenGL
public void AddGradient(IGradient gradient) public void AddGradient(IGradient gradient)
{ {
if (gradient is GLGradient g) if (gradient is not GLGradient g)
{ return;
g.RegisterUsage(this); g.RegisterUsage(this);
m_gradients.Add(g); m_gradients.Add(g);
}
} }
public void RemoveAllGradients() public void RemoveAllGradients()
{ {
foreach (GLGradient g in m_gradients) foreach (var g in m_gradients)
g.UnregisterUsage(this); g.UnregisterUsage(this);
m_gradients.Clear(); m_gradients.Clear();
} }
@@ -10,15 +10,14 @@ namespace Microsoft.Iris.Render.OpenGL
public sealed class GLVisualContainer : GLVisual, IVisualContainer public sealed class GLVisualContainer : GLVisual, IVisualContainer
{ {
private readonly List<GLVisual> m_children = new List<GLVisual>(); private readonly List<GLVisual> m_children = new List<GLVisual>();
private readonly bool m_isRoot;
public GLVisualContainer(GLRenderSession session, object ownerData, bool isRoot) public GLVisualContainer(GLRenderSession session, object ownerData, bool isRoot)
: base(session, ownerData) : base(session, ownerData)
{ {
m_isRoot = isRoot; IsRoot = isRoot;
} }
public bool IsRoot => m_isRoot; public bool IsRoot { get; }
public int ChildCount => m_children.Count; public int ChildCount => m_children.Count;
public ICamera? Camera { get; set; } public ICamera? Camera { get; set; }
@@ -52,11 +51,10 @@ namespace Microsoft.Iris.Render.OpenGL
public void RemoveChild(IVisual vChild) public void RemoveChild(IVisual vChild)
{ {
if (vChild is GLVisual child && m_children.Remove(child)) if (vChild is not GLVisual child || !m_children.Remove(child))
{ return;
child.ParentContainer = null; child.ParentContainer = null;
child.UnregisterUsage(this); child.UnregisterUsage(this);
}
} }
public void RemoveAllChildren() public void RemoveAllChildren()
@@ -77,7 +75,7 @@ namespace Microsoft.Iris.Render.OpenGL
// Draw children back-to-front by layer. OrderBy is stable, preserving // Draw children back-to-front by layer. OrderBy is stable, preserving
// insertion order within a layer. // insertion order within a layer.
m_children.Sort((a, b) => a.Layer.CompareTo(b.Layer)); m_children.Sort((a, b) => a.Layer.CompareTo(b.Layer));
foreach (GLVisual child in m_children) foreach (var child in m_children)
child.Render(renderer, matrix, alpha); child.Render(renderer, matrix, alpha);
} }
@@ -93,7 +91,7 @@ namespace Microsoft.Iris.Render.OpenGL
m_children.Sort((a, b) => a.Layer.CompareTo(b.Layer)); m_children.Sort((a, b) => a.Layer.CompareTo(b.Layer));
for (int i = m_children.Count - 1; i >= 0; i--) for (int i = m_children.Count - 1; i >= 0; i--)
{ {
GLVisual? hit = m_children[i].HitTest(screenPoint, world); var hit = m_children[i].HitTest(screenPoint, world);
if (hit != null) if (hit != null)
return hit; return hit;
} }
@@ -112,49 +112,6 @@ namespace Microsoft.Iris.Render.Protocol
} }
} }
#if !NETFRAMEWORK
public static HRESULT SpInit(ref InitArgs args) => new HRESULT(0);
public static HRESULT SpUninit() => new HRESULT(0);
public static unsafe HRESULT SpBufferOpen(
BufferInfo* phdrData,
void* pvData)
{
var src = new Iface.ContextID(ContextID.ToUInt32(phdrData->idContextSrc));
var dest = new Iface.ContextID(ContextID.ToUInt32(phdrData->idContextDest));
var bufferHandle = new Iface.RENDERHANDLE(RENDERHANDLE.ToUInt32(phdrData->idBuffer));
var flags = (Iface.BufferFlags)phdrData->nFlags;
var span = new ReadOnlySpan<byte>(pvData, (int)phdrData->cbSizeBuffer);
Iface.HRESULT result = EngineService.SendBuffer(src, dest, bufferHandle, flags, span);
return new HRESULT(result.hr);
}
public static unsafe HRESULT SpWrapBufferProc(
MessageBufferEventHandler pfnProcessBufferProc,
IntPtr* ppNativeProc)
{
if (ppNativeProc == null)
return new HRESULT(unchecked((int)0x80070057));
if (pfnProcessBufferProc == null)
{
*ppNativeProc = IntPtr.Zero;
return new HRESULT(0);
}
// Managed-direct: store the delegate itself instead of marshaling to a
// native function pointer -- SpRenderThreadInit resolves this straight back
// to the delegate object and invokes it directly, no calli anywhere on this
// path. See logs/UIXrender/EngineCore.md.
GCHandle handle = GCHandle.Alloc(pfnProcessBufferProc, GCHandleType.Normal);
*ppNativeProc = GCHandle.ToIntPtr(handle);
return new HRESULT(0);
}
#else
// net461 (EnableNetFXTarget): UIXrender's managed API isn't referenceable from
// .NET Framework, so this TFM keeps calling the real native UIXRender.dll.
[DllImport(s_stEhRenderDll)] [DllImport(s_stEhRenderDll)]
public static extern HRESULT SpInit(ref InitArgs args); public static extern HRESULT SpInit(ref InitArgs args);
@@ -170,41 +127,7 @@ namespace Microsoft.Iris.Render.Protocol
public static extern unsafe HRESULT SpWrapBufferProc( public static extern unsafe HRESULT SpWrapBufferProc(
MessageBufferEventHandler pfnProcessBufferProc, MessageBufferEventHandler pfnProcessBufferProc,
IntPtr* ppNativeProc); IntPtr* ppNativeProc);
#endif
#if !NETFRAMEWORK
// No Win32 message queue exists behind this reimplementation (see EngineService),
// and LocalChannel -- the path Zune uses -- never peeks. Reports "no message".
public static HRESULT SpPeekMessage(
out Win32Api.MSG msg,
HWND hwnd,
uint nMsgFilterMin,
uint nMsgFilterMax,
uint wRemoveMsg,
out WorkResult nResult)
{
msg = default;
nResult = (WorkResult)EngineService.PeekMessage(nMsgFilterMin, nMsgFilterMax, wRemoveMsg);
return new HRESULT(0);
}
public static HRESULT SpWaitMessage(uint nTimeOutMs, IntPtr _unused)
{
EngineService.WaitMessage(nTimeOutMs);
return new HRESULT(0);
}
public static HRESULT SpInvoke(
ContextID idContext,
IntPtr pfnInvoke,
IntPtr pvArgs,
bool synchronous)
{
Iface.HRESULT result = EngineService.Invoke(
new Iface.ContextID(ContextID.ToUInt32(idContext)), pfnInvoke, pvArgs, synchronous);
return new HRESULT(result.hr);
}
#else
[DllImport(s_stEhRenderDll, CharSet = CharSet.Auto)] [DllImport(s_stEhRenderDll, CharSet = CharSet.Auto)]
public static extern HRESULT SpPeekMessage( public static extern HRESULT SpPeekMessage(
out Win32Api.MSG msg, out Win32Api.MSG msg,
@@ -223,65 +146,7 @@ namespace Microsoft.Iris.Render.Protocol
IntPtr pfnInvoke, IntPtr pfnInvoke,
IntPtr pvArgs, IntPtr pvArgs,
bool synchronous); bool synchronous);
#endif
#if !NETFRAMEWORK
public static HRESULT SpRenderThreadInit(
ref InitArgs argsRender,
out IntPtr pThread)
{
var contextId = new Iface.ContextID(ContextID.ToUInt32(argsRender.idContext));
MessageBufferEventHandler managedCallback = argsRender.pfnProcessBuffer != IntPtr.Zero
? GCHandle.FromIntPtr(argsRender.pfnProcessBuffer).Target as MessageBufferEventHandler
: null;
BufferReceivedHandler handler = managedCallback != null
? AdaptCallback(managedCallback, argsRender.idContext)
: delegate { };
IRenderThreadHandle threadHandle = EngineService.StartRenderThread(contextId, handler);
pThread = GCHandle.ToIntPtr(GCHandle.Alloc(threadHandle, GCHandleType.Normal));
return new HRESULT(0);
}
// Adapts a stored MessageBufferEventHandler (already-decompiled, still
// pointer-shaped -- see logs/UIXrender/EngineCore.md) into the idiomatic
// BufferReceivedHandler shape EngineService deals in. Factored out of
// SpRenderThreadInit so that method reads as resolve -> adapt -> start -> wrap,
// and named to make clear it's the same kind of adaptation
// UIXrender/Interop/EngineApi.cs's own SpRenderThreadInit does for native
// callers (there: raw function pointer -> BufferReceivedHandler; here: managed
// delegate -> BufferReceivedHandler -- same shape, different invocation
// mechanism at the end).
private static unsafe BufferReceivedHandler AdaptCallback(MessageBufferEventHandler callback, ContextID destContext) =>
(source, bufferHandle, flags, data) =>
{
fixed (byte* pData = data)
{
var info = new BufferInfo
{
idContextSrc = ContextID.FromUInt32(source.value),
idContextDest = destContext,
idBuffer = RENDERHANDLE.FromUInt32(bufferHandle.value),
nFlags = (BufferFlags)flags,
cbSizeBuffer = (uint)data.Length,
};
callback(IntPtr.Zero, source.value, &info, pData);
}
};
public static HRESULT SpRenderThreadUninit(IntPtr pThread)
{
if (pThread == IntPtr.Zero)
return new HRESULT(unchecked((int)0x80070057));
GCHandle handle = GCHandle.FromIntPtr(pThread);
(handle.Target as IDisposable)?.Dispose();
handle.Free();
return new HRESULT(0);
}
#else
[DllImport(s_stEhRenderDll)] [DllImport(s_stEhRenderDll)]
public static extern HRESULT SpRenderThreadInit( public static extern HRESULT SpRenderThreadInit(
ref InitArgs argsRender, ref InitArgs argsRender,
@@ -289,86 +154,8 @@ namespace Microsoft.Iris.Render.Protocol
[DllImport(s_stEhRenderDll)] [DllImport(s_stEhRenderDll)]
public static extern HRESULT SpRenderThreadUninit(IntPtr pThread); public static extern HRESULT SpRenderThreadUninit(IntPtr pThread);
#endif
#if !NETFRAMEWORK
public static HRESULT SpRemoteCreateServerStreams(
string stSession,
TransportProtocol nProtocol,
out IntPtr pSendStream,
out IntPtr pReceiveStream)
{
Iface.HRESULT result = EngineService.RemoteCreateServerStreams(
stSession, (Iface.Protocol.TransportProtocol)(int)nProtocol, out pSendStream, out pReceiveStream);
return new HRESULT(result.hr);
}
public static HRESULT SpRemoteWaitServerStreamsConnected(
TransportProtocol nProtocol,
IntPtr pSendStream,
IntPtr pReceiveStream)
{
Iface.HRESULT result = EngineService.RemoteWaitServerStreamsConnected(
(Iface.Protocol.TransportProtocol)(int)nProtocol, pSendStream);
return new HRESULT(result.hr);
}
public static HRESULT SpRemoteServerInit(
IntPtr pSendStream,
IntPtr pReceiveStream,
InitArgs argsSend,
out IntPtr pSession)
{
var context = new Iface.ContextID(ContextID.ToUInt32(argsSend.idContext));
// Same delegate-behind-a-GCHandle representation SpRenderThreadInit resolves;
// RemoteChannel connects without a receive callback (pfnProcessBuffer == 0),
// so this is normally null.
MessageBufferEventHandler managedCallback = argsSend.pfnProcessBuffer != IntPtr.Zero
? GCHandle.FromIntPtr(argsSend.pfnProcessBuffer).Target as MessageBufferEventHandler
: null;
BufferReceivedHandler handler = managedCallback != null
? AdaptCallback(managedCallback, argsSend.idContext)
: null;
Iface.HRESULT result = EngineService.RemoteServerInit(pSendStream, context, handler, out pSession);
return new HRESULT(result.hr);
}
public static HRESULT SpRemoteServerUninit(
IntPtr pSession,
bool fForceShutdown,
out ShutdownReason nShutdownReason)
{
Iface.HRESULT result = EngineService.RemoteServerUninit(
pSession, fForceShutdown, out Iface.Protocol.ShutdownReason reason);
nShutdownReason = (ShutdownReason)(int)reason;
return new HRESULT(result.hr);
}
public static HRESULT SpDx9CompileEffect(
string stEffect,
string stDefines,
out IntPtr pErrorString,
out IntPtr pErrorBuffer,
out IntPtr pEffectBlob,
out uint EffectBlobSize,
out IntPtr pEffectBlobBuffer)
{
pErrorString = IntPtr.Zero;
pErrorBuffer = IntPtr.Zero;
pEffectBlob = IntPtr.Zero;
EffectBlobSize = 0U;
pEffectBlobBuffer = IntPtr.Zero;
return new HRESULT(EngineService.Dx9CompileEffect().hr);
}
// SpObjectRelease's only callers (RemoteChannel) release the stream handles from
// SpRemoteCreateServerStreams, which in the managed-direct path are UIXrender
// handles, not COM pointers -- so this drops the handle's reference rather than
// calling through a vtable.
public static void SpObjectRelease(IntPtr pUnknown) => EngineService.ReleaseRemoteStream(pUnknown);
#else
[DllImport(s_stEhRenderDll, CharSet = CharSet.Unicode)] [DllImport(s_stEhRenderDll, CharSet = CharSet.Unicode)]
public static extern HRESULT SpRemoteCreateServerStreams( public static extern HRESULT SpRemoteCreateServerStreams(
string stSession, string stSession,
@@ -407,7 +194,6 @@ namespace Microsoft.Iris.Render.Protocol
[DllImport(s_stEhRenderDll)] [DllImport(s_stEhRenderDll)]
public static extern void SpObjectRelease(IntPtr pUnknown); public static extern void SpObjectRelease(IntPtr pUnknown);
#endif
[Flags] [Flags]
public enum BufferFlags public enum BufferFlags