OffScreenBrowser

This commit is contained in:
pypy
2020-11-08 16:28:07 +09:00
parent 7a1067e21c
commit a716f1b0e9
5 changed files with 198 additions and 222 deletions
-80
View File
@@ -1,80 +0,0 @@
// Copyright(c) 2019 pypy. All rights reserved.
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
using CefSharp;
using CefSharp.OffScreen;
using SharpDX.Direct3D11;
using System;
using System.Drawing;
using System.Threading;
namespace VRCX
{
public class Browser : ChromiumWebBrowser
{
private readonly ReaderWriterLockSlim m_Lock = new ReaderWriterLockSlim();
private Texture2D m_Texture;
public Browser(Texture2D texture, string address)
: base(address, new BrowserSettings()
{
DefaultEncoding = "UTF-8"
})
{
m_Texture = texture;
Size = new Size(texture.Description.Width, texture.Description.Height);
RenderHandler.Dispose();
RenderHandler = new RenderHandler(this, m_Lock);
Util.ApplyJavascriptBindings(JavascriptObjectRepository);
}
public new void Dispose()
{
RenderHandler.Dispose();
RenderHandler = null;
base.Dispose();
}
public void Render()
{
m_Lock.EnterReadLock();
try
{
var H = (RenderHandler)RenderHandler;
if (H.Buffer.IsAllocated)
{
var context = m_Texture.Device.ImmediateContext;
var box = context.MapSubresource(m_Texture, 0, MapMode.WriteDiscard, MapFlags.None);
if (box.DataPointer != IntPtr.Zero)
{
if (box.RowPitch == H.Width * 4)
{
WinApi.CopyMemory(box.DataPointer, H.Buffer.AddrOfPinnedObject(), (uint)H.BufferSize);
}
else
{
var dest = box.DataPointer;
var src = H.Buffer.AddrOfPinnedObject();
var pitch = box.RowPitch;
var length = H.Width * 4;
var height = H.Height;
for (var i = 0; i < height; ++i)
{
WinApi.CopyMemory(dest, src, (uint)length);
dest += pitch;
src += length;
}
}
}
context.UnmapSubresource(m_Texture, 0);
}
}
finally
{
m_Lock.ExitReadLock();
}
}
}
}
+193
View File
@@ -0,0 +1,193 @@
// Copyright(c) 2019 pypy. All rights reserved.
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
using CefSharp;
using CefSharp.Enums;
using CefSharp.OffScreen;
using CefSharp.Structs;
using SharpDX.Direct3D11;
using System;
namespace VRCX
{
public class OffScreenBrowser : ChromiumWebBrowser, IRenderHandler
{
private Texture2D _texture;
public OffScreenBrowser(Texture2D texture, string address)
: base(address, new BrowserSettings()
{
DefaultEncoding = "UTF-8"
})
{
_texture = texture;
Size = new System.Drawing.Size(texture.Description.Width, texture.Description.Height);
RenderHandler = this;
Util.ApplyJavascriptBindings(JavascriptObjectRepository);
}
public new void Dispose()
{
RenderHandler = null;
base.Dispose();
_texture = null;
}
//
ScreenInfo? IRenderHandler.GetScreenInfo()
{
return new ScreenInfo
{
DeviceScaleFactor = 1f
};
}
bool IRenderHandler.GetScreenPoint(int viewX, int viewY, out int screenX, out int screenY)
{
screenX = viewX;
screenY = viewY;
return false;
}
Rect IRenderHandler.GetViewRect()
{
return new Rect(0, 0, Size.Width, Size.Height);
}
void IRenderHandler.OnAcceleratedPaint(PaintElementType type, Rect dirtyRect, IntPtr sharedHandle)
{
// NOT USED
}
void IRenderHandler.OnCursorChange(IntPtr cursor, CursorType type, CursorInfo customCursorInfo)
{
}
void IRenderHandler.OnImeCompositionRangeChanged(Range selectedRange, Rect[] characterBounds)
{
}
void IRenderHandler.OnPaint(PaintElementType type, Rect dirtyRect, IntPtr buffer, int width, int height)
{
if (type == PaintElementType.View)
{
using (var device = _texture.Device)
using (var context = device.ImmediateContext)
{
var dataBox = context.MapSubresource(_texture, 0, MapMode.WriteDiscard, MapFlags.None);
if (dataBox.IsEmpty == false)
{
var sourcePtr = buffer;
var destinationPtr = dataBox.DataPointer;
var rowPitch = dataBox.RowPitch;
var pitch = width * 4;
if (rowPitch == pitch)
{
WinApi.CopyMemory(destinationPtr, sourcePtr, (uint)(width * height * 4));
}
else
{
for (var i = height; i > 0; --i)
{
WinApi.CopyMemory(destinationPtr, sourcePtr, (uint)pitch);
sourcePtr += pitch;
destinationPtr += rowPitch;
}
}
}
context.UnmapSubresource(_texture, 0);
}
/*_bufferAssignLock.EnterUpgradeableReadLock();
try
{
if (_buffer.IsAllocated == false ||
width != _width ||
height != _height)
{
_bufferAssignLock.EnterWriteLock();
try
{
_width = width;
_height = height;
_bufferSize = width * height * 4;
if (_buffer.IsAllocated == true)
{
_buffer.Free();
}
_buffer = GCHandle.Alloc(new byte[_bufferSize], GCHandleType.Pinned);
}
finally
{
_bufferAssignLock.ExitWriteLock();
}
}
WinApi.CopyMemory(_buffer.AddrOfPinnedObject(), buffer, (uint)_bufferSize);
}
finally
{
_bufferAssignLock.ExitUpgradeableReadLock();
}*/
}
/*_bufferAssignLock.EnterReadLock();
try
{
if (_buffer.IsAllocated == true)
{
var context = _texture.Device.ImmediateContext;
var box = context.MapSubresource(_texture, 0, MapMode.WriteDiscard, MapFlags.None);
var destinationPtr = box.DataPointer;
var sourcePtr = _buffer.AddrOfPinnedObject();
if (destinationPtr != IntPtr.Zero)
{
if (box.RowPitch == _width * 4)
{
WinApi.CopyMemory(destinationPtr, sourcePtr, (uint)_bufferSize);
}
else
{
var pitch = box.RowPitch;
var rowPitch = _width * 4;
for (var i = _height; i > 0; --i)
{
WinApi.CopyMemory(destinationPtr, sourcePtr, (uint)rowPitch);
destinationPtr += pitch;
sourcePtr += rowPitch;
}
}
}
context.UnmapSubresource(_texture, 0);
}
}
finally
{
_bufferAssignLock.ExitReadLock();
}*/
}
void IRenderHandler.OnPopupShow(bool show)
{
}
void IRenderHandler.OnPopupSize(Rect rect)
{
}
void IRenderHandler.OnVirtualKeyboardRequested(IBrowser browser, TextInputMode inputMode)
{
}
bool IRenderHandler.StartDragging(IDragData dragData, DragOperationsMask mask, int x, int y)
{
return false;
}
void IRenderHandler.UpdateDragCursor(DragOperationsMask operation)
{
}
}
}
-136
View File
@@ -1,136 +0,0 @@
// Copyright(c) 2019 pypy. All rights reserved.
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
using System;
using System.Runtime.InteropServices;
using System.Threading;
using CefSharp;
using CefSharp.Enums;
using CefSharp.OffScreen;
using CefSharp.Structs;
namespace VRCX
{
public class RenderHandler : IRenderHandler
{
private ChromiumWebBrowser m_Browser;
private ReaderWriterLockSlim m_Lock;
public int BufferSize { get; private set; }
public GCHandle Buffer { get; private set; }
public int Width { get; private set; }
public int Height { get; private set; }
public RenderHandler(ChromiumWebBrowser browser, ReaderWriterLockSlim @lock)
{
m_Browser = browser;
m_Lock = @lock;
}
public void Dispose()
{
m_Lock.EnterWriteLock();
try
{
if (Buffer.IsAllocated)
{
Buffer.Free();
}
}
finally
{
m_Lock.ExitWriteLock();
}
m_Browser = null;
}
public virtual ScreenInfo? GetScreenInfo()
{
return new ScreenInfo { DeviceScaleFactor = 1f };
}
public virtual Rect GetViewRect()
{
return new Rect(0, 0, m_Browser.Size.Width, m_Browser.Size.Height);
}
public virtual bool GetScreenPoint(int viewX, int viewY, out int screenX, out int screenY)
{
screenX = viewX;
screenY = viewY;
return false;
}
public virtual void OnAcceleratedPaint(PaintElementType type, Rect dirtyRect, IntPtr sharedHandle)
{
// NOT USED
}
public virtual void OnPaint(PaintElementType type, Rect dirtyRect, IntPtr buffer, int width, int height)
{
if (type == PaintElementType.View)
{
m_Lock.EnterUpgradeableReadLock();
try
{
if (!Buffer.IsAllocated ||
width != Width ||
height != Height)
{
m_Lock.EnterWriteLock();
try
{
Width = width;
Height = height;
BufferSize = width * height * 4;
if (Buffer.IsAllocated)
{
Buffer.Free();
}
Buffer = GCHandle.Alloc(new byte[BufferSize], GCHandleType.Pinned);
}
finally
{
m_Lock.ExitWriteLock();
}
}
WinApi.CopyMemory(Buffer.AddrOfPinnedObject(), buffer, (uint)BufferSize);
}
finally
{
m_Lock.ExitUpgradeableReadLock();
}
}
}
public virtual void OnCursorChange(IntPtr cursor, CursorType type, CursorInfo customCursorInfo)
{
}
public virtual bool StartDragging(IDragData dragData, DragOperationsMask mask, int x, int y)
{
return false;
}
public virtual void UpdateDragCursor(DragOperationsMask operation)
{
}
public virtual void OnPopupShow(bool show)
{
}
public virtual void OnPopupSize(Rect rect)
{
}
public virtual void OnImeCompositionRangeChanged(Range selectedRange, Rect[] characterBounds)
{
}
public virtual void OnVirtualKeyboardRequested(IBrowser browser, TextInputMode inputMode)
{
}
}
}
+1 -2
View File
@@ -128,9 +128,8 @@
<Compile Include="CefService.cs" />
<Compile Include="Discord.cs" />
<Compile Include="CpuMonitor.cs" />
<Compile Include="Browser.cs" />
<Compile Include="OffScreenBrowser.cs" />
<Compile Include="NoopDragHandler.cs" />
<Compile Include="RenderHandler.cs" />
<Compile Include="WebApi.cs" />
<Compile Include="SQLite.cs" />
<Compile Include="SharedVariable.cs" />
+4 -4
View File
@@ -27,8 +27,8 @@ namespace VRCX
private static Device m_Device;
private static Texture2D m_Texture1;
private static Texture2D m_Texture2;
private static Browser m_Browser1;
private static Browser m_Browser2;
private static OffScreenBrowser m_Browser1;
private static OffScreenBrowser m_Browser2;
private static bool m_Active;
private static float[] m_Rotation = { 0f, 0f, 0f };
private static float[] m_Translation = { 0f, 0f, 0f };
@@ -66,8 +66,8 @@ namespace VRCX
BindFlags = BindFlags.ShaderResource,
CpuAccessFlags = CpuAccessFlags.Write
});
m_Browser1 = new Browser(m_Texture1, Path.Combine(Program.BaseDirectory, "html/vr.html?1"));
m_Browser2 = new Browser(m_Texture2, Path.Combine(Program.BaseDirectory, "html/vr.html?2"));
m_Browser1 = new OffScreenBrowser(m_Texture1, Path.Combine(Program.BaseDirectory, "html/vr.html?1"));
m_Browser2 = new OffScreenBrowser(m_Texture2, Path.Combine(Program.BaseDirectory, "html/vr.html?2"));
m_Thread = new Thread(() =>
{
var active = false;