Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7eba2434f | ||
|
|
ddbfad6e95 | ||
|
|
49aef432e7 | ||
|
|
fc81892917 |
Binary file not shown.
@@ -3,6 +3,8 @@ using MeshForwardDirection = uDesktopDuplication.Texture.MeshForwardDirection;
|
||||
|
||||
public class MultipleMonitorRoundLayouter : MultipleMonitorLayouter
|
||||
{
|
||||
[SerializeField] bool debugDraw = true;
|
||||
|
||||
public float radius = 10f;
|
||||
public Vector3 offsetAngle = Vector3.zero;
|
||||
|
||||
@@ -80,7 +82,7 @@ public class MultipleMonitorRoundLayouter : MultipleMonitorLayouter
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
DebugDraw();
|
||||
if (debugDraw) DebugDraw();
|
||||
}
|
||||
|
||||
void DebugDraw()
|
||||
|
||||
Binary file not shown.
@@ -1,6 +1,4 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Assertions;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace uDesktopDuplication
|
||||
{
|
||||
@@ -15,7 +13,6 @@ public class Cursor : MonoBehaviour
|
||||
|
||||
private Texture uddTexture_;
|
||||
private Monitor monitor { get { return uddTexture_.monitor; } }
|
||||
private Dictionary<int, Texture2D> textures_ = new Dictionary<int, Texture2D>();
|
||||
|
||||
void Start()
|
||||
{
|
||||
@@ -26,9 +23,8 @@ public class Cursor : MonoBehaviour
|
||||
{
|
||||
if (monitor.isCursorVisible) {
|
||||
UpdatePosition();
|
||||
UpdateTexture();
|
||||
}
|
||||
UpdateMaterial();
|
||||
UpdateCoords();
|
||||
}
|
||||
|
||||
void UpdatePosition()
|
||||
@@ -40,33 +36,10 @@ public class Cursor : MonoBehaviour
|
||||
worldPosition = transform.TransformPoint(localPos);
|
||||
}
|
||||
|
||||
void UpdateTexture()
|
||||
{
|
||||
var w = monitor.cursorShapeWidth;
|
||||
var h = monitor.cursorShapeHeight;
|
||||
if (w == 0 || h == 0) return;
|
||||
|
||||
var key = w + h * 100;
|
||||
if (!textures_.ContainsKey(key)) {
|
||||
var texture = new Texture2D(w, h, TextureFormat.BGRA32, false);
|
||||
texture.wrapMode = TextureWrapMode.Clamp;
|
||||
textures_.Add(key, texture);
|
||||
}
|
||||
|
||||
var cursorTexture = textures_[key];
|
||||
Assert.IsNotNull(cursorTexture);
|
||||
monitor.GetCursorTexture(cursorTexture.GetNativeTexturePtr());
|
||||
uddTexture_.material.SetTexture("_CursorTex", cursorTexture);
|
||||
}
|
||||
|
||||
void UpdateMaterial()
|
||||
void UpdateCoords()
|
||||
{
|
||||
var x = monitor.isCursorVisible ? (float)monitor.cursorX / monitor.width : -9999f;
|
||||
var y = monitor.isCursorVisible ? (float)monitor.cursorY / monitor.height : -9999f;
|
||||
var w = (float)monitor.cursorShapeWidth / monitor.width;
|
||||
var h = (float)monitor.cursorShapeHeight / monitor.height;
|
||||
uddTexture_.material.SetVector("_CursorPositionScale", new Vector4(x, y, w, h));
|
||||
|
||||
coord = new Vector2(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,15 +15,17 @@ public class Manager : MonoBehaviour
|
||||
|
||||
public static Manager CreateInstance()
|
||||
{
|
||||
if (instance_) {
|
||||
return instance_;
|
||||
}
|
||||
if (instance_ != null) return instance_;
|
||||
|
||||
var manager = FindObjectOfType<Manager>();
|
||||
if (manager) return manager;
|
||||
if (manager) {
|
||||
instance_ = manager;
|
||||
return manager;
|
||||
}
|
||||
|
||||
var go = new GameObject("uDesktopDuplicationManager");
|
||||
return go.AddComponent<Manager>();
|
||||
instance_ = go.AddComponent<Manager>();
|
||||
return instance_;
|
||||
}
|
||||
|
||||
private List<Monitor> monitors_ = new List<Monitor>();
|
||||
@@ -74,10 +76,16 @@ public class Manager : MonoBehaviour
|
||||
void Awake()
|
||||
{
|
||||
// for simple singleton
|
||||
if (instance_ != null) {
|
||||
|
||||
if (instance_ == this) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (instance_ != null && instance_ != this) {
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
instance_ = this;
|
||||
|
||||
Lib.SetDebugMode(debugMode);
|
||||
@@ -134,11 +142,12 @@ public class Manager : MonoBehaviour
|
||||
|
||||
for (int i = 0; i < monitors.Count; ++i) {
|
||||
var monitor = monitors[i];
|
||||
var state = monitor.state;
|
||||
if (
|
||||
monitor.state == MonitorState.NotSet ||
|
||||
monitor.state == MonitorState.AccessLost ||
|
||||
monitor.state == MonitorState.AccessDenied ||
|
||||
monitor.state == MonitorState.SessionDisconnected
|
||||
state == MonitorState.NotSet ||
|
||||
state == MonitorState.AccessLost ||
|
||||
state == MonitorState.AccessDenied ||
|
||||
state == MonitorState.SessionDisconnected
|
||||
) {
|
||||
reinitializeNeeded = true;
|
||||
break;
|
||||
|
||||
@@ -240,6 +240,7 @@ public class Monitor
|
||||
}
|
||||
|
||||
private Texture2D texture_;
|
||||
private System.IntPtr texturePtr_;
|
||||
public Texture2D texture
|
||||
{
|
||||
get
|
||||
@@ -252,8 +253,8 @@ public class Monitor
|
||||
|
||||
public void Render()
|
||||
{
|
||||
if (texture_ && available) {
|
||||
Lib.SetTexturePtr(id, texture_.GetNativeTexturePtr());
|
||||
if (texture_ && available && texturePtr_ != System.IntPtr.Zero) {
|
||||
Lib.SetTexturePtr(id, texturePtr_);
|
||||
GL.IssuePluginEvent(Lib.GetRenderEventFunc(), id);
|
||||
}
|
||||
}
|
||||
@@ -290,6 +291,7 @@ public class Monitor
|
||||
var w = isHorizontal ? width : height;
|
||||
var h = isHorizontal ? height : width;
|
||||
texture_ = new Texture2D(w, h, TextureFormat.BGRA32, false);
|
||||
texturePtr_ = texture_.GetNativeTexturePtr();
|
||||
}
|
||||
|
||||
public void DestroyTexture()
|
||||
@@ -297,6 +299,7 @@ public class Monitor
|
||||
if (texture_) {
|
||||
Object.Destroy(texture_);
|
||||
texture_ = null;
|
||||
texturePtr_ = System.IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,32 +64,14 @@ inline void uddConvertToLinearIfNeeded(inout fixed3 rgb)
|
||||
}
|
||||
|
||||
inline fixed4 uddGetScreenTexture(float2 uv)
|
||||
{
|
||||
fixed4 c = tex2D(_MainTex, uv);
|
||||
return c;
|
||||
}
|
||||
|
||||
inline fixed4 uddGetCursorTexture(float2 uv)
|
||||
{
|
||||
uv.x = (uv.x - _CursorX) / _CursorWidth;
|
||||
uv.y = (uv.y - _CursorY) / _CursorHeight;
|
||||
fixed4 c = tex2D(_CursorTex, uv);
|
||||
fixed a = step(0, uv.x) * step(0, uv.y) * step(uv.x, 1) * step(uv.y, 1);
|
||||
c.a *= step(0.01, a);
|
||||
return c;
|
||||
}
|
||||
|
||||
inline fixed4 uddGetScreenTextureWithCursor(float2 uv)
|
||||
{
|
||||
uv = uddInvertUV(uv);
|
||||
#ifdef USE_CLIP
|
||||
uv = uddClipUV(uv);
|
||||
#endif
|
||||
fixed4 screen = uddGetScreenTexture(uddRotateUV(uv));
|
||||
fixed4 cursor = uddGetCursorTexture(uv);
|
||||
fixed4 color = lerp(screen, cursor, cursor.a);
|
||||
uddConvertToLinearIfNeeded(color.rgb);
|
||||
return color;
|
||||
fixed4 c = tex2D(_MainTex, uddRotateUV(uv));
|
||||
uddConvertToLinearIfNeeded(c.rgb);
|
||||
return c;
|
||||
}
|
||||
|
||||
inline void uddBendVertex(inout float4 v, half radius, half width, half thickness)
|
||||
|
||||
@@ -34,7 +34,7 @@ SubShader
|
||||
|
||||
void surf(Input IN, inout SurfaceOutputStandard o)
|
||||
{
|
||||
fixed4 c = uddGetScreenTextureWithCursor(IN.uv_MainTex) * _Color;
|
||||
fixed4 c = uddGetScreenTexture(IN.uv_MainTex) * _Color;
|
||||
o.Albedo = c.rgb;
|
||||
o.Metallic = _Metallic;
|
||||
o.Smoothness = _Glossiness;
|
||||
|
||||
@@ -39,7 +39,7 @@ v2f vert(appdata v)
|
||||
|
||||
fixed4 frag(v2f i) : SV_Target
|
||||
{
|
||||
return uddGetScreenTextureWithCursor(i.uv);
|
||||
return uddGetScreenTexture(i.uv);
|
||||
}
|
||||
|
||||
ENDCG
|
||||
|
||||
@@ -43,7 +43,7 @@ v2f vert(appdata v)
|
||||
|
||||
fixed4 frag(v2f i) : SV_Target
|
||||
{
|
||||
fixed4 tex = uddGetScreenTextureWithCursor(i.uv);
|
||||
fixed4 tex = uddGetScreenTexture(i.uv);
|
||||
fixed alpha = pow((tex.r + tex.g + tex.b) / 3.0, _Mask);
|
||||
return fixed4(tex.rgb * _Color.rgb, alpha * _Color.a);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ v2f vert(appdata v)
|
||||
|
||||
fixed4 frag(v2f i) : SV_Target
|
||||
{
|
||||
return fixed4(uddGetScreenTextureWithCursor(i.uv).rgb, 1.0) * _Color;
|
||||
return fixed4(uddGetScreenTexture(i.uv).rgb, 1.0) * _Color;
|
||||
}
|
||||
|
||||
ENDCG
|
||||
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
return value_ != nullptr;
|
||||
}
|
||||
|
||||
T operator [](UINT index) const
|
||||
const T operator [](UINT index) const
|
||||
{
|
||||
if (index >= size_)
|
||||
{
|
||||
@@ -93,6 +93,16 @@ public:
|
||||
return value_[index];
|
||||
}
|
||||
|
||||
T& operator [](UINT index)
|
||||
{
|
||||
if (index >= size_)
|
||||
{
|
||||
Debug::Error("Array index out of range: ", index, size_);
|
||||
return value_[0];
|
||||
}
|
||||
return value_[index];
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<T[]> value_;
|
||||
UINT size_ = 0;
|
||||
|
||||
@@ -79,33 +79,43 @@ void Cursor::UpdateTexture()
|
||||
return;
|
||||
}
|
||||
|
||||
// Check desktop texure
|
||||
if (monitor_->GetUnityTexture() == nullptr)
|
||||
{
|
||||
Debug::Error("Cursor::UpdateTexture() => Monitor::GetUnityTexture() is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Cursor information
|
||||
const bool isMono = GetType() == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME;
|
||||
const bool isColorMask = GetType() == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR;
|
||||
const auto cursorImageWidth = GetWidth();
|
||||
const auto cursorImageHeight = GetHeight();
|
||||
const auto cursorImagePitch = GetPitch();
|
||||
|
||||
// Captured area
|
||||
// Captured size
|
||||
auto capturedImageWidth = cursorImageWidth;
|
||||
auto capturedImageHeight = cursorImageHeight;
|
||||
|
||||
// Convert the buffer given by API into BGRA32
|
||||
const UINT bgraBufferSize = cursorImageWidth * cursorImageHeight * 4;
|
||||
bgra32Buffer_.ExpandIfNeeded(bgraBufferSize);
|
||||
bgraBuffer_.ExpandIfNeeded(bgraBufferSize);
|
||||
|
||||
// Check buffers
|
||||
if (!bgra32Buffer_ || !apiBuffer_)
|
||||
if (!bgraBuffer_ || !apiBuffer_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If masked, copy the desktop image and merge it with masked image.
|
||||
if (isMono || isColorMask)
|
||||
// Calculate information to capture desktop image under cursor.
|
||||
D3D11_BOX box;
|
||||
const auto monitorRot = static_cast<DXGI_MODE_ROTATION>(monitor_->GetRotation());
|
||||
auto colMin = 0;
|
||||
auto colMax = cursorImageWidth;
|
||||
auto rowMin = 0;
|
||||
auto rowMax = cursorImageHeight;
|
||||
|
||||
{
|
||||
const auto monitorWidth = monitor_->GetWidth();
|
||||
const auto monitorHeight = monitor_->GetHeight();
|
||||
const auto monitorRot = static_cast<DXGI_MODE_ROTATION>(monitor_->GetRotation());
|
||||
const auto isVertical =
|
||||
monitorRot == DXGI_MODE_ROTATION_ROTATE90 ||
|
||||
monitorRot == DXGI_MODE_ROTATION_ROTATE270;
|
||||
@@ -114,10 +124,6 @@ void Cursor::UpdateTexture()
|
||||
|
||||
auto x = x_;
|
||||
auto y = y_;
|
||||
auto colMin = 0;
|
||||
auto colMax = cursorImageWidth;
|
||||
auto rowMin = 0;
|
||||
auto rowMax = cursorImageHeight;
|
||||
|
||||
if (x < 0)
|
||||
{
|
||||
@@ -142,7 +148,6 @@ void Cursor::UpdateTexture()
|
||||
rowMax = capturedImageHeight;
|
||||
}
|
||||
|
||||
D3D11_BOX box;
|
||||
box.front = 0;
|
||||
box.back = 1;
|
||||
|
||||
@@ -196,13 +201,11 @@ void Cursor::UpdateTexture()
|
||||
"(", desktopImageWidth, ", ", desktopImageHeight, ")");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (monitor_->GetUnityTexture() == nullptr)
|
||||
{
|
||||
Debug::Error("Cursor::UpdateTexture() => Monitor::GetUnityTexture() is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create texture
|
||||
ComPtr<ID3D11Texture2D> texture;
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = capturedImageWidth;
|
||||
desc.Height = capturedImageHeight;
|
||||
@@ -216,83 +219,89 @@ void Cursor::UpdateTexture()
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
ComPtr<ID3D11Texture2D> texture;
|
||||
if (FAILED(GetDevice()->CreateTexture2D(&desc, nullptr, &texture)))
|
||||
if (FAILED(GetDevice()->CreateTexture2D(&desc, nullptr, &texture)))
|
||||
{
|
||||
Debug::Error("Cursor::UpdateTexture() => GetDevice()->CreateTexture2D() failed.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy desktop image to the texture
|
||||
{
|
||||
ComPtr<ID3D11DeviceContext> context;
|
||||
GetDevice()->GetImmediateContext(&context);
|
||||
context->CopySubresourceRegion(texture.Get(), 0, 0, 0, 0, monitor_->GetUnityTexture(), 0, &box);
|
||||
}
|
||||
|
||||
// Get mapped surface
|
||||
ComPtr<IDXGISurface> surface;
|
||||
if (FAILED(texture.As(&surface)))
|
||||
{
|
||||
Debug::Error("Cursor::UpdateTexture() => texture->QueryInterface() failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
DXGI_MAPPED_RECT mappedSurface;
|
||||
if (FAILED(surface->Map(&mappedSurface, DXGI_MAP_READ)))
|
||||
{
|
||||
Debug::Error("Cursor::UpdateTexture() => surface->Map() failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Finally, get the desktop texture under the mouse cursor.
|
||||
const auto desktop32 = reinterpret_cast<UINT*>(mappedSurface.pBits);
|
||||
const UINT desktopPitch = mappedSurface.Pitch / sizeof(UINT);
|
||||
|
||||
// Take the monitor orientation into consideration.
|
||||
const auto getDesktop32 = [&](int col, int row)
|
||||
{
|
||||
switch (monitorRot)
|
||||
{
|
||||
ComPtr<ID3D11DeviceContext> context;
|
||||
GetDevice()->GetImmediateContext(&context);
|
||||
context->CopySubresourceRegion(texture.Get(), 0, 0, 0, 0, monitor_->GetUnityTexture(), 0, &box);
|
||||
case DXGI_MODE_ROTATION_ROTATE90:
|
||||
return desktop32[(capturedImageWidth - 1 - col) * desktopPitch + row];
|
||||
case DXGI_MODE_ROTATION_ROTATE180:
|
||||
return desktop32[(capturedImageHeight - 1 - row) * desktopPitch + (capturedImageWidth - 1 - col)];
|
||||
case DXGI_MODE_ROTATION_ROTATE270:
|
||||
return desktop32[col * desktopPitch + (capturedImageHeight - 1 - row)];
|
||||
case DXGI_MODE_ROTATION_IDENTITY:
|
||||
case DXGI_MODE_ROTATION_UNSPECIFIED:
|
||||
return desktop32[row * desktopPitch + col];
|
||||
}
|
||||
};
|
||||
|
||||
ComPtr<IDXGISurface> surface;
|
||||
if (FAILED(texture.As(&surface)))
|
||||
// Access RGBA values at the same time
|
||||
Buffer<BYTE> output;
|
||||
output.ExpandIfNeeded(bgraBuffer_.Size());
|
||||
auto output32 = output.As<UINT>();
|
||||
|
||||
switch (GetType())
|
||||
{
|
||||
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME:
|
||||
{
|
||||
Debug::Error("Cursor::UpdateTexture() => texture->QueryInterface() failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
DXGI_MAPPED_RECT mappedSurface;
|
||||
if (FAILED(surface->Map(&mappedSurface, DXGI_MAP_READ)))
|
||||
{
|
||||
Debug::Error("Cursor::UpdateTexture() => surface->Map() failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Finally, get the texture behind the mouse cursor.
|
||||
const auto desktop32 = reinterpret_cast<UINT*>(mappedSurface.pBits);
|
||||
const UINT desktopPitch = mappedSurface.Pitch / sizeof(UINT);
|
||||
|
||||
// Take the monitor orientation into consideration.
|
||||
const auto getDesktop32 = [&](int col, int row)
|
||||
{
|
||||
switch (monitorRot)
|
||||
for (int row = rowMin, y = 0; row < rowMax; ++row, ++y)
|
||||
{
|
||||
case DXGI_MODE_ROTATION_ROTATE90:
|
||||
return desktop32[(capturedImageWidth - 1 - col) * desktopPitch + row];
|
||||
break;
|
||||
case DXGI_MODE_ROTATION_ROTATE180:
|
||||
return desktop32[(capturedImageHeight - 1 - row) * desktopPitch + (capturedImageWidth - 1 - col)];
|
||||
break;
|
||||
case DXGI_MODE_ROTATION_ROTATE270:
|
||||
return desktop32[col * desktopPitch + (capturedImageHeight - 1 - row)];
|
||||
break;
|
||||
case DXGI_MODE_ROTATION_IDENTITY:
|
||||
case DXGI_MODE_ROTATION_UNSPECIFIED:
|
||||
return desktop32[row * desktopPitch + col];
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// Access RGBA values at the same time
|
||||
auto output32 = reinterpret_cast<UINT*>(bgra32Buffer_.Get());
|
||||
|
||||
if (isMono)
|
||||
{
|
||||
for (int row = rowMin, y = 0; row < rowMax; ++row, ++y)
|
||||
{
|
||||
for (int col = colMin, x = 0; col < colMax; ++col, ++x)
|
||||
for (int col = colMin, x = 0; col < colMax; ++col, ++x)
|
||||
{
|
||||
const int i = col + row * cursorImageWidth;
|
||||
|
||||
BYTE mask = 0b10000000 >> (col % 8);
|
||||
const BYTE andMask = apiBuffer_[col / 8 + row * cursorImagePitch] & mask;
|
||||
const BYTE xorMask = apiBuffer_[col / 8 + (row + capturedImageHeight) * cursorImagePitch] & mask;
|
||||
const UINT andMask32 = andMask ? 0xFFFFFFFF : 0x00000000;
|
||||
const UINT xorMask32 = xorMask ? 0xFFFFFFFF : 0x00000000;
|
||||
output32[row * cursorImageWidth + col] = (getDesktop32(x, y) & andMask32) ^ xorMask32;
|
||||
|
||||
output32[i] = (getDesktop32(x, y) & andMask32) ^ xorMask32;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else // DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR
|
||||
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR:
|
||||
{
|
||||
const auto buffer32 = reinterpret_cast<UINT*>(apiBuffer_.Get());
|
||||
const auto buffer32 = apiBuffer_.As<UINT>();
|
||||
|
||||
for (int row = rowMin, y = 0; row < rowMax; ++row, ++y)
|
||||
for (int row = rowMin, y = 0; row < rowMax; ++row, ++y)
|
||||
{
|
||||
for (int col = colMin, x = 0; col < colMax; ++col, ++x)
|
||||
for (int col = colMin, x = 0; col < colMax; ++col, ++x)
|
||||
{
|
||||
const int i = col + row * cursorImageWidth;
|
||||
const int j = col + row * cursorImagePitch / sizeof(UINT);
|
||||
@@ -308,28 +317,92 @@ void Cursor::UpdateTexture()
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (FAILED(surface->Unmap()))
|
||||
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR:
|
||||
{
|
||||
return;
|
||||
const auto buffer32 = apiBuffer_.As<UINT>();
|
||||
auto output32 = bgraBuffer_.As<UINT>();
|
||||
|
||||
for (int row = rowMin, y = 0; row < rowMax; ++row, ++y)
|
||||
{
|
||||
for (int col = colMin, x = 0; col < colMax; ++col, ++x)
|
||||
{
|
||||
const int i = 4 * (col + row * cursorImageWidth);
|
||||
|
||||
const auto desktop32 = getDesktop32(x, y);
|
||||
const auto desktop = (BYTE*)(&desktop32);
|
||||
const auto desktopB = desktop[0];
|
||||
const auto desktopG = desktop[1];
|
||||
const auto desktopR = desktop[2];
|
||||
const auto desktopA = desktop[3];
|
||||
|
||||
const auto cursorB = apiBuffer_[i + 0];
|
||||
const auto cursorG = apiBuffer_[i + 1];
|
||||
const auto cursorR = apiBuffer_[i + 2];
|
||||
const auto cursorA = apiBuffer_[i + 3];
|
||||
|
||||
const auto a0 = cursorA / 255.f;
|
||||
const auto a1 = 1.f - a0;
|
||||
|
||||
output[i + 0] = static_cast<BYTE>(cursorB * a0 + desktopB * a1);
|
||||
output[i + 1] = static_cast<BYTE>(cursorG * a0 + desktopG * a1);
|
||||
output[i + 2] = static_cast<BYTE>(cursorR * a0 + desktopR * a1);
|
||||
output[i + 3] = desktopA;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Debug::Error("Cursor::UpdateTexture() => Unknown cursor type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR
|
||||
|
||||
// Rotation
|
||||
auto bgraBuffer32 = bgraBuffer_.As<UINT>();
|
||||
for (int row = rowMin, y = 0; row < rowMax; ++row, ++y)
|
||||
{
|
||||
auto output32 = reinterpret_cast<UINT*>(bgra32Buffer_.Get());
|
||||
const auto buffer32 = reinterpret_cast<UINT*>(apiBuffer_.Get());
|
||||
for (int i = 0; i < cursorImageWidth * cursorImageHeight; ++i)
|
||||
for (int col = colMin, x = 0; col < colMax; ++col, ++x)
|
||||
{
|
||||
output32[i] = buffer32[i];
|
||||
const auto i = col + row * cursorImageWidth;
|
||||
switch (monitorRot)
|
||||
{
|
||||
case DXGI_MODE_ROTATION_ROTATE90:
|
||||
bgraBuffer32[i] = output32[col * cursorImageHeight + (cursorImageHeight - 1 - row)];
|
||||
break;
|
||||
case DXGI_MODE_ROTATION_ROTATE180:
|
||||
bgraBuffer32[i] = output32[(cursorImageHeight - 1 - row) * cursorImageWidth + (cursorImageWidth - 1 - col)];
|
||||
break;
|
||||
case DXGI_MODE_ROTATION_ROTATE270:
|
||||
bgraBuffer32[i] = output32[(cursorImageWidth - 1 - col) * cursorImageHeight + row];
|
||||
break;
|
||||
case DXGI_MODE_ROTATION_IDENTITY:
|
||||
case DXGI_MODE_ROTATION_UNSPECIFIED:
|
||||
bgraBuffer32[i] = output32[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
ComPtr<ID3D11DeviceContext> context;
|
||||
GetDevice()->GetImmediateContext(&context);
|
||||
context->UpdateSubresource(monitor_->GetUnityTexture(), 0, &box, bgraBuffer_.Get(), GetWidth() * 4, 0);
|
||||
}
|
||||
|
||||
if (FAILED(surface->Unmap()))
|
||||
{
|
||||
Debug::Error("Cursor::UpdateTexture() => surface->Unmap() failed.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Cursor::GetTexture(ID3D11Texture2D* texture)
|
||||
{
|
||||
if (!bgra32Buffer_)
|
||||
if (!bgraBuffer_)
|
||||
{
|
||||
Debug::Error("Cursor::GetTexture() => bgra32Buffer is null.");
|
||||
return;
|
||||
@@ -356,7 +429,7 @@ void Cursor::GetTexture(ID3D11Texture2D* texture)
|
||||
|
||||
ComPtr<ID3D11DeviceContext> context;
|
||||
GetDevice()->GetImmediateContext(&context);
|
||||
context->UpdateSubresource(texture, 0, nullptr, bgra32Buffer_.Get(), GetWidth() * 4, 0);
|
||||
context->UpdateSubresource(texture, 0, nullptr, bgraBuffer_.Get(), GetWidth() * 4, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ private:
|
||||
int x_ = -1;
|
||||
int y_ = -1;
|
||||
Buffer<BYTE> apiBuffer_;
|
||||
Buffer<BYTE> bgra32Buffer_;
|
||||
Buffer<BYTE> bgraBuffer_;
|
||||
DXGI_OUTDUPL_POINTER_SHAPE_INFO shapeInfo_;
|
||||
LARGE_INTEGER timestamp_;
|
||||
};
|
||||
@@ -113,10 +113,11 @@ void Monitor::Render(UINT timeout)
|
||||
{
|
||||
if (!deskDupl_) return;
|
||||
|
||||
HRESULT hr;
|
||||
ComPtr<IDXGIResource> resource;
|
||||
DXGI_OUTDUPL_FRAME_INFO frameInfo;
|
||||
|
||||
const auto hr = deskDupl_->AcquireNextFrame(timeout, &frameInfo, &resource);
|
||||
hr = deskDupl_->AcquireNextFrame(timeout, &frameInfo, &resource);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
switch (hr)
|
||||
@@ -191,9 +192,30 @@ void Monitor::Render(UINT timeout)
|
||||
UpdateMetadata(frameInfo);
|
||||
UpdateCursor(frameInfo);
|
||||
|
||||
if (FAILED(deskDupl_->ReleaseFrame()))
|
||||
hr = deskDupl_->ReleaseFrame();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Debug::Error("Monitor::Render() => ReleaseFrame() failed.");
|
||||
switch (hr)
|
||||
{
|
||||
case DXGI_ERROR_ACCESS_LOST:
|
||||
{
|
||||
Debug::Log("Monitor::Render() => DXGI_ERROR_ACCESS_LOST.");
|
||||
state_ = State::AccessLost;
|
||||
break;
|
||||
}
|
||||
case DXGI_ERROR_INVALID_CALL:
|
||||
{
|
||||
Debug::Error("Monitor::Render() => DXGI_ERROR_INVALID_CALL.");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
state_ = State::Unknown;
|
||||
Debug::Error("Monitor::Render() => Unknown Error.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -112,10 +112,11 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<Optimization>Full</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
|
||||
Reference in New Issue
Block a user