Compare commits

..

41 Commits

Author SHA1 Message Date
hecomi
74c51e7072 tweak script name. 2018-12-29 00:05:06 +09:00
hecomi
267b286765 add 'buffer' property to Monitor to access the buffer pointer directly. 2018-12-29 00:02:19 +09:00
hecomi
f060ffbfba fix GetPixels() bug #27. 2018-12-23 15:10:40 +09:00
hecomi
467fa86f59 add function-scope timer for debug. 2018-12-08 13:36:16 +09:00
hecomi
608509aa22 output os version and graphics information. 2018-12-08 11:06:07 +09:00
hecomi
9aa488e100 code cleanups. 2018-12-02 23:52:30 +09:00
hecomi
4c225c21c9 rebuild DLLs. 2018-11-16 01:13:02 +09:00
hecomi
b8b4238b5f update unity version to Unity 2018.2.15f1. 2018-11-16 01:09:01 +09:00
hecomi
4d2766ce3f fix Shader.PropertyToID error on Unity 5.x #26 2018-11-13 00:16:55 +09:00
hecomi
f4096ec9fb fix crash bug caused by Windows sleep. 2018-09-12 21:40:57 +09:00
hecomi
0f43788650 add solution file. 2018-09-12 20:54:58 +09:00
hecomi
1c1381a7ba consider clipPos and clipScale for raycast #23. 2018-09-12 00:04:33 +09:00
hecomi
08903cd27a fix orientation of monitor object in Zoom scene. 2018-09-12 00:03:36 +09:00
hecomi
d840983829 update Unity version to 2018.2.7f1. 2018-09-12 00:03:01 +09:00
hecomi
8a6cee9c2d Merge pull request #24 from dj-kusuha/fix_il2cpp_runtime_error
fixed a runtime error when using the IL2CPP scripting backend
2018-09-11 21:36:08 +09:00
dj-kusuha
f7798f752f fixed a runtime error when using the IL2CPP scripting backend 2018-09-11 11:27:43 +09:00
hecomi
70cfad90a9 fix bug that caused darker screen #22. 2018-08-05 00:20:03 +09:00
hecomi
c926127e49 update Unity version to 2018.1. 2018-08-05 00:19:07 +09:00
hecomi
03469ce429 remove unnecessary line break. 2018-08-05 00:18:42 +09:00
hecomi
f63e573f04 remove unnecessary logs. 2018-05-20 15:53:30 +09:00
hecomi
682553a5a2 tweak code. 2018-05-20 02:08:18 +09:00
hecomi
b5fd483d6a call ReleaseFrame() just before AcquireNextFrame() #18. 2018-05-20 01:11:03 +09:00
hecomi
0d2c0e02f0 update Visual Studio version to 2017. 2018-05-20 00:53:36 +09:00
hecomi
6f876f65ed update Unity version to 2017.4. 2018-05-19 21:49:24 +09:00
hecomi
8434d803bb remove build status. 2017-08-24 01:38:00 +09:00
hecomi
1c332ebca7 fix bugs that caused x86 build problem. 2017-08-24 01:34:53 +09:00
hecomi
340e2d5194 remove unnecessary shared flag from cursor texture. 2017-01-09 17:07:26 +09:00
hecomi
e397f5eb84 fix typo. 2017-01-08 01:01:05 +09:00
hecomi
c20c09e275 fix bug that drew cursor on all monitors. 2017-01-08 00:38:01 +09:00
hecomi
a0ca46630e fix perf macro bug. 2017-01-08 00:32:14 +09:00
hecomi
5b5995d7d0 remove unnecessary perf. 2017-01-08 00:29:04 +09:00
hecomi
808a71ed6d remove unnecessary codes. 2017-01-08 00:09:24 +09:00
hecomi
da072aa9f3 draw cursor texture to unity texture instead of cached texture. 2017-01-08 00:02:41 +09:00
hecomi
7237d283ef add error messages. 2017-01-07 23:10:13 +09:00
hecomi
4a28b5f341 tweak shared texture. 2017-01-07 23:02:48 +09:00
hecomi
10091be4b3 lock shared texture. 2017-01-07 15:28:13 +09:00
hecomi
c41fe42aa3 check frame id. 2017-01-07 13:48:38 +09:00
hecomi
c0e1967e2e modify duplicator state handling. 2017-01-07 13:26:28 +09:00
hecomi
f5a8a83c7e change member name. 2017-01-07 13:18:11 +09:00
hecomi
c251de3a30 add debug timer macro. 2017-01-07 01:15:33 +09:00
hecomi
b0877a49ed tweak code. 2017-01-07 00:53:37 +09:00
79 changed files with 1365 additions and 339 deletions

3
.gitignore vendored
View File

@@ -5,6 +5,8 @@
/[Bb]uild/
/[Ww]iki/
/[Mm]isc/
/UnityPackageManager
/Packages
# Autogenerated VS/MD solution and project files
*.csproj
@@ -28,3 +30,4 @@ sysinfo.txt
/Assets/AssetStoreTools*
/Assets/Extensions*
/uDesktopDuplication.log
.vs

View File

@@ -0,0 +1,420 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
OcclusionCullingSettings:
m_ObjectHideFlags: 0
serializedVersion: 2
m_OcclusionBakeSettings:
smallestOccluder: 5
smallestHole: 0.25
backfaceThreshold: 100
m_SceneGUID: 00000000000000000000000000000000
m_OcclusionCullingData: {fileID: 0}
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 9
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
m_FogDensity: 0.01
m_LinearFogStart: 0
m_LinearFogEnd: 300
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 1
m_AmbientMode: 0
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
m_HaloTexture: {fileID: 0}
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
m_DefaultReflectionMode: 0
m_DefaultReflectionResolution: 128
m_ReflectionBounces: 1
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.18028378, g: 0.22571412, b: 0.30692285, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 11
m_GIWorkflowMode: 0
m_GISettings:
serializedVersion: 2
m_BounceScale: 1
m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_TemporalCoherenceThreshold: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 1
m_EnableRealtimeLightmaps: 1
m_LightmapEditorSettings:
serializedVersion: 10
m_Resolution: 2
m_BakeResolution: 40
m_AtlasSize: 1024
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 1
m_CompAOExponentDirect: 0
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
m_TextureCompression: 1
m_FinalGather: 0
m_FinalGatherFiltering: 1
m_FinalGatherRayCount: 256
m_ReflectionCompression: 2
m_MixedBakeMode: 2
m_BakeBackend: 1
m_PVRSampling: 1
m_PVRDirectSampleCount: 32
m_PVRSampleCount: 500
m_PVRBounces: 2
m_PVRFilterTypeDirect: 0
m_PVRFilterTypeIndirect: 0
m_PVRFilterTypeAO: 0
m_PVRFilteringMode: 1
m_PVRCulling: 1
m_PVRFilteringGaussRadiusDirect: 1
m_PVRFilteringGaussRadiusIndirect: 5
m_PVRFilteringGaussRadiusAO: 2
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
m_ShowResolutionOverlay: 1
m_LightingDataAsset: {fileID: 0}
m_UseShadowmask: 1
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 2
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
agentSlope: 45
agentClimb: 0.4
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
minRegionArea: 2
manualCellSize: 0
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &15787040
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 15787043}
- component: {fileID: 15787042}
- component: {fileID: 15787041}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!81 &15787041
AudioListener:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 15787040}
m_Enabled: 1
--- !u!20 &15787042
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 15787040}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 1
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
m_projectionMatrixMode: 1
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 0.3
far clip plane: 1000
field of view: 60
orthographic: 0
orthographic size: 5
m_Depth: -1
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 1
m_AllowMSAA: 1
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!4 &15787043
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 15787040}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &24328793 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 114000012274256594, guid: de6f36e446e5e8a48bf61fe198985bb4,
type: 2}
m_PrefabInternal: {fileID: 930860461}
m_Script: {fileID: 11500000, guid: bb54a34570e4747429b1c5b66c69d356, type: 3}
--- !u!1001 &86016649
Prefab:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalPosition.x
value: 5
objectReference: {fileID: 0}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalPosition.z
value: 10
objectReference: {fileID: 0}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_RootOrder
value: 3
objectReference: {fileID: 0}
- target: {fileID: 114000012274256594, guid: de6f36e446e5e8a48bf61fe198985bb4,
type: 2}
propertyPath: invertX_
value: 0
objectReference: {fileID: 0}
- target: {fileID: 114000012274256594, guid: de6f36e446e5e8a48bf61fe198985bb4,
type: 2}
propertyPath: useClip_
value: 0
objectReference: {fileID: 0}
- target: {fileID: 23000011974915108, guid: de6f36e446e5e8a48bf61fe198985bb4,
type: 2}
propertyPath: m_Materials.Array.data[0]
value:
objectReference: {fileID: 2100000, guid: c181d333a7bee7a44b94c0f4e02c4bd4, type: 2}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalScale.x
value: 0.96
objectReference: {fileID: 0}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalScale.y
value: 0.54
objectReference: {fileID: 0}
- target: {fileID: 1000012642892690, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_Name
value: Monitor Board Dst
objectReference: {fileID: 0}
m_RemovedComponents:
- {fileID: 114000012274256594, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
m_SourcePrefab: {fileID: 100100000, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
m_IsPrefabAsset: 0
--- !u!1 &423308485
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 423308487}
- component: {fileID: 423308486}
m_Layer: 0
m_Name: Directional Light
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!108 &423308486
Light:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 423308485}
m_Enabled: 1
serializedVersion: 8
m_Type: 1
m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
m_Intensity: 1
m_Range: 10
m_SpotAngle: 30
m_CookieSize: 10
m_Shadows:
m_Type: 2
m_Resolution: -1
m_CustomResolution: -1
m_Strength: 1
m_Bias: 0.05
m_NormalBias: 0.4
m_NearPlane: 0.2
m_Cookie: {fileID: 0}
m_DrawHalo: 0
m_Flare: {fileID: 0}
m_RenderMode: 0
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_Lightmapping: 4
m_LightShadowCasterMode: 0
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_ShadowRadius: 0
m_ShadowAngle: 0
--- !u!4 &423308487
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 423308485}
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
m_LocalPosition: {x: 0, y: 3, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
--- !u!1001 &930860461
Prefab:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalPosition.x
value: -5
objectReference: {fileID: 0}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalPosition.z
value: 10
objectReference: {fileID: 0}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_RootOrder
value: 2
objectReference: {fileID: 0}
- target: {fileID: 114000012274256594, guid: de6f36e446e5e8a48bf61fe198985bb4,
type: 2}
propertyPath: invertX_
value: 0
objectReference: {fileID: 0}
- target: {fileID: 114000012274256594, guid: de6f36e446e5e8a48bf61fe198985bb4,
type: 2}
propertyPath: useClip_
value: 0
objectReference: {fileID: 0}
- target: {fileID: 23000011974915108, guid: de6f36e446e5e8a48bf61fe198985bb4,
type: 2}
propertyPath: m_Materials.Array.data[0]
value:
objectReference: {fileID: 2100000, guid: c181d333a7bee7a44b94c0f4e02c4bd4, type: 2}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalScale.x
value: 0.96
objectReference: {fileID: 0}
- target: {fileID: 4000011474108562, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_LocalScale.y
value: 0.54
objectReference: {fileID: 0}
- target: {fileID: 1000012642892690, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
propertyPath: m_Name
value: Monitor Board Src
objectReference: {fileID: 0}
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: de6f36e446e5e8a48bf61fe198985bb4, type: 2}
m_IsPrefabAsset: 0
--- !u!1 &1159532891 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 1000012642892690, guid: de6f36e446e5e8a48bf61fe198985bb4,
type: 2}
m_PrefabInternal: {fileID: 86016649}
--- !u!114 &1159532892
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1159532891}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2bbc456c8248acd46976392616f32f8c, type: 3}
m_Name:
m_EditorClassIdentifier:
uddTexture: {fileID: 24328793}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 36c8d626679d64b46b75b9f1a2923647
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,72 @@
using UnityEngine;
using System;
using System.Runtime.InteropServices;
public class BufferExample : MonoBehaviour
{
[SerializeField]
uDesktopDuplication.Texture uddTexture;
Texture2D texture_;
Color32[] pixels_;
GCHandle handle_;
IntPtr ptr_ = IntPtr.Zero;
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
public static extern IntPtr memcpy(IntPtr dest, IntPtr src, int count);
void Start()
{
if (!uddTexture) return;
uddTexture.monitor.useGetPixels = true;
UpdateTexture();
}
void OnDestroy()
{
if (ptr_ != IntPtr.Zero) {
handle_.Free();
}
}
void Update()
{
if (!uddTexture) return;
if (uddTexture.monitor.width != texture_.width ||
uddTexture.monitor.height != texture_.height) {
UpdateTexture();
}
CopyTexture();
}
void UpdateTexture()
{
var width = uddTexture.monitor.width;
var height = uddTexture.monitor.height;
// TextureFormat.BGRA32 should be set but it causes an error now.
texture_ = new Texture2D(width, height, TextureFormat.RGBA32, false);
texture_.filterMode = FilterMode.Bilinear;
pixels_ = texture_.GetPixels32();
handle_ = GCHandle.Alloc(pixels_, GCHandleType.Pinned);
ptr_ = handle_.AddrOfPinnedObject();
GetComponent<Renderer>().material.mainTexture = texture_;
}
void CopyTexture()
{
var buffer = uddTexture.monitor.buffer;
if (buffer == IntPtr.Zero) return;
var width = uddTexture.monitor.width;
var height = uddTexture.monitor.height;
memcpy(ptr_, buffer, width * height * sizeof(Byte) * 4);
texture_.SetPixels32(pixels_);
texture_.Apply();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2bbc456c8248acd46976392616f32f8c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -6,27 +6,38 @@ public class GetPixelsExample : MonoBehaviour
[SerializeField] int x = 100;
[SerializeField] int y = 100;
const int width = 64;
const int height = 32;
[SerializeField] int w = 64;
[SerializeField] int h = 32;
public Texture2D texture;
Color32[] colors = new Color32[width * height];
Color32[] colors;
void CreateTextureIfNeeded()
{
if (!texture || texture.width != w || texture.height != h)
{
colors = new Color32[w * h];
texture = new Texture2D(w, h, TextureFormat.ARGB32, false);
GetComponent<Renderer>().material.mainTexture = texture;
}
}
void Start()
{
texture = new Texture2D(width, height, TextureFormat.ARGB32, false);
GetComponent<Renderer>().material.mainTexture = texture;
CreateTextureIfNeeded();
}
void Update()
{
CreateTextureIfNeeded();
// must be called (performance will be slightly down).
uDesktopDuplication.Manager.primary.useGetPixels = true;
var monitor = uddTexture.monitor;
if (!monitor.hasBeenUpdated) return;
if (monitor.GetPixels(colors, x, y, width, height)) {
if (monitor.GetPixels(colors, x, y, w, h)) {
texture.SetPixels32(colors);
texture.Apply();
}

View File

@@ -1,41 +1,41 @@
using UnityEngine;
[RequireComponent(typeof(MultipleMonitorCreator))]
public class MultipleMonitorAnalyzer : MonoBehaviour
{
MultipleMonitorCreator creator_;
Vector3 gazePoint_ = Vector3.zero;
public Vector3 gazePoint
{
get { return gazePoint_; }
private set
using UnityEngine;
[RequireComponent(typeof(MultipleMonitorCreator))]
public class MultipleMonitorAnalyzer : MonoBehaviour
{
MultipleMonitorCreator creator_;
Vector3 gazePoint_ = Vector3.zero;
public Vector3 gazePoint
{
get { return gazePoint_; }
private set
{
gazePoint_ += (value - gazePoint) * (gazePointFilter / (1f / 60 / Time.deltaTime));
}
}
[Header("Filters")]
[Range(0f, 1f)] public float gazePointFilter = 0.1f;
[Range(0f, 1f)] public float moveRectFilter = 0.05f;
[Range(0f, 1f)] public float mouseFilter = 0.05f;
[Range(0f, 1f)] public float dirtyRectFilter = 0.01f;
[Range(0f, 1f)] public float noEventFilter = 0.01f;
[Range(0f, 1f)] public float velocityFilter = 0.1f;
[Header("Debug")]
[SerializeField] bool drawGazePoint;
[SerializeField] bool drawAveragePos;
[SerializeField] bool drawMoveRects;
[SerializeField] bool drawDirtyRects;
void Start()
}
}
[Header("Filters")]
[Range(0f, 1f)] public float gazePointFilter = 0.1f;
[Range(0f, 1f)] public float moveRectFilter = 0.05f;
[Range(0f, 1f)] public float mouseFilter = 0.05f;
[Range(0f, 1f)] public float dirtyRectFilter = 0.01f;
[Range(0f, 1f)] public float noEventFilter = 0.01f;
[Range(0f, 1f)] public float velocityFilter = 0.1f;
[Header("Debug")]
[SerializeField] bool drawGazePoint;
[SerializeField] bool drawAveragePos;
[SerializeField] bool drawMoveRects;
[SerializeField] bool drawDirtyRects;
void Start()
{
creator_ = GetComponent<MultipleMonitorCreator>();
}
void Update()
{
var cursorMonitorId = uDesktopDuplication.Manager.cursorMonitorId;
}
void Update()
{
var cursorMonitorId = uDesktopDuplication.Manager.cursorMonitorId;
for (int i = 0; i < creator_.monitors.Count; ++i) {
var info = creator_.monitors[i];
var analyzer =
@@ -44,18 +44,18 @@ public class MultipleMonitorAnalyzer : MonoBehaviour
UpdateAnalyzer(analyzer);
if (info.uddTexture.monitorId == cursorMonitorId) {
gazePoint = analyzer.averagePos;
}
}
if (drawGazePoint) DrawGazePoint();
}
void DrawGazePoint()
}
}
if (drawGazePoint) DrawGazePoint();
}
void DrawGazePoint()
{
Debug.DrawLine(transform.position, gazePoint, Color.magenta);
}
void UpdateAnalyzer(GazePointAnalyzer analyzer)
}
void UpdateAnalyzer(GazePointAnalyzer analyzer)
{
analyzer.moveRectFilter = moveRectFilter;
analyzer.mouseFilter = mouseFilter;
@@ -65,5 +65,5 @@ public class MultipleMonitorAnalyzer : MonoBehaviour
analyzer.drawAveragePos = drawAveragePos;
analyzer.drawMoveRects = drawMoveRects;
analyzer.drawDirtyRects = drawDirtyRects;
}
}
}
}

View File

@@ -1,7 +1,6 @@
using UnityEngine;
using System.Collections;
public class RaycastTest : MonoBehaviour
public class RaycastExample : MonoBehaviour
{
public Transform from;
public Transform to;

View File

@@ -1,53 +1,150 @@
fileFormatVersion: 2
guid: 19d4c78204afead44b6de11427d7f2f6
timeCreated: 1480693943
guid: d3ab0ac3a3d6bb643af0a464a93be957
timeCreated: 1503496900
licenseType: Pro
PluginImporter:
serializedVersion: 1
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
Any:
enabled: 1
settings: {}
Editor:
enabled: 0
settings:
CPU: x86
DefaultValueInitialized: true
Linux:
enabled: 1
settings:
CPU: x86
Linux64:
enabled: 0
settings:
CPU: None
LinuxUniversal:
enabled: 1
settings:
CPU: x86
OSXIntel:
enabled: 1
settings:
CPU: AnyCPU
OSXIntel64:
enabled: 0
settings:
CPU: None
OSXUniversal:
enabled: 0
settings:
CPU: x86
Win:
enabled: 1
settings:
CPU: AnyCPU
Win64:
enabled: 0
settings:
CPU: None
data:
first:
'': Any
second:
enabled: 0
settings:
Exclude Android: 0
Exclude Editor: 0
Exclude Linux: 0
Exclude Linux64: 0
Exclude LinuxUniversal: 0
Exclude OSXIntel: 0
Exclude OSXIntel64: 0
Exclude OSXUniversal: 0
Exclude Win: 0
Exclude Win64: 1
data:
first:
'': data
second:
enabled: 0
settings: {}
data:
first:
Android: Android
second:
enabled: 1
settings:
CPU: ARMv7
data:
first:
Any:
second:
enabled: 1
settings:
Exclude Editor: 0
Exclude Linux: 0
Exclude Linux64: 0
Exclude LinuxUniversal: 0
Exclude OSXIntel: 0
Exclude OSXIntel64: 0
Exclude OSXUniversal: 0
Exclude WebGL: 0
Exclude Win: 0
Exclude Win64: 1
data:
first:
Editor: Editor
second:
enabled: 1
settings:
CPU: x86
DefaultValueInitialized: true
OS: AnyOS
data:
first:
Facebook: WebGL
second:
enabled: 1
settings: {}
data:
first:
Facebook: Win
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: None
data:
first:
Standalone: Linux
second:
enabled: 1
settings:
CPU: x86
data:
first:
Standalone: Linux64
second:
enabled: 1
settings:
CPU: None
data:
first:
Standalone: LinuxUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Standalone: OSXIntel
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Standalone: OSXIntel64
second:
enabled: 1
settings:
CPU: None
data:
first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Standalone: Win
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
data:
first:
WebGL: WebGL
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,54 +1,150 @@
fileFormatVersion: 2
guid: 02fc121822cf2ea4e82e16c4a28bf711
timeCreated: 1477546714
guid: 7cb91c9ae744dc5429005b20e11f4f37
timeCreated: 1503505907
licenseType: Pro
PluginImporter:
serializedVersion: 1
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
Any:
enabled: 1
settings: {}
Editor:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
Linux:
enabled: 0
settings:
CPU: x86
Linux64:
enabled: 0
settings:
CPU: x86_64
LinuxUniversal:
enabled: 0
settings:
CPU: None
OSXIntel:
enabled: 0
settings:
CPU: AnyCPU
OSXIntel64:
enabled: 0
settings:
CPU: AnyCPU
OSXUniversal:
enabled: 0
settings:
CPU: None
Win:
enabled: 0
settings:
CPU: AnyCPU
Win64:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
'': Any
second:
enabled: 0
settings:
Exclude Android: 0
Exclude Editor: 0
Exclude Linux: 0
Exclude Linux64: 0
Exclude LinuxUniversal: 0
Exclude OSXIntel: 0
Exclude OSXIntel64: 0
Exclude OSXUniversal: 0
Exclude Win: 1
Exclude Win64: 0
data:
first:
'': data
second:
enabled: 0
settings: {}
data:
first:
Android: Android
second:
enabled: 1
settings:
CPU: ARMv7
data:
first:
Any:
second:
enabled: 1
settings:
Exclude Editor: 0
Exclude Linux: 0
Exclude Linux64: 0
Exclude LinuxUniversal: 0
Exclude OSXIntel: 0
Exclude OSXIntel64: 0
Exclude OSXUniversal: 0
Exclude WebGL: 0
Exclude Win: 1
Exclude Win64: 0
data:
first:
Editor: Editor
second:
enabled: 1
settings:
CPU: x86_64
DefaultValueInitialized: true
OS: AnyOS
data:
first:
Facebook: WebGL
second:
enabled: 1
settings: {}
data:
first:
Facebook: Win
second:
enabled: 0
settings:
CPU: None
data:
first:
Facebook: Win64
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Standalone: Linux
second:
enabled: 1
settings:
CPU: None
data:
first:
Standalone: Linux64
second:
enabled: 1
settings:
CPU: x86_64
data:
first:
Standalone: LinuxUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Standalone: OSXIntel
second:
enabled: 1
settings:
CPU: None
data:
first:
Standalone: OSXIntel64
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
data:
first:
Standalone: Win64
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
WebGL: WebGL
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -169,6 +169,8 @@ public static class Lib
[DllImport("uDesktopDuplication", EntryPoint = "GetPixels")]
private static extern bool GetPixels_Internal(int id, System.IntPtr ptr, int x, int y, int width, int height);
[DllImport("uDesktopDuplication")]
public static extern IntPtr GetBuffer(int id);
[DllImport("uDesktopDuplication")]
public static extern bool HasBeenUpdated(int id);
[DllImport("uDesktopDuplication")]
public static extern bool UseGetPixels(int id, bool use);

View File

@@ -62,8 +62,13 @@ public class Manager : MonoBehaviour
private float reinitializationTimer_ = 0f;
private bool isFirstFrame_ = true;
public static event Lib.DebugLogDelegate onDebugLog = msg => Debug.Log(msg);
public static event Lib.DebugLogDelegate onDebugErr = msg => Debug.LogError(msg);
public static event Lib.DebugLogDelegate onDebugLog = OnDebugLog;
public static event Lib.DebugLogDelegate onDebugErr = OnDebugErr;
[AOT.MonoPInvokeCallback(typeof(Lib.DebugLogDelegate))]
private static void OnDebugLog(string msg) { Debug.Log(msg); }
[AOT.MonoPInvokeCallback(typeof(Lib.DebugLogDelegate))]
private static void OnDebugErr(string msg) { Debug.LogError(msg); }
public delegate void ReinitializeHandler();
public static event ReinitializeHandler onReinitialized;
@@ -99,6 +104,12 @@ public class Manager : MonoBehaviour
Lib.Initialize();
CreateMonitors();
#if UNITY_2018_1_OR_NEWER
Shader.DisableKeyword("USE_GAMMA_TO_LINEAR_SPACE");
#else
Shader.EnableKeyword("USE_GAMMA_TO_LINEAR_SPACE");
#endif
}
void OnApplicationQuit()

View File

@@ -238,6 +238,11 @@ public class Monitor
get { return Lib.GetDirtyRects(id); }
}
public System.IntPtr buffer
{
get { return Lib.GetBuffer(id); }
}
public bool hasBeenUpdated
{
get { return Lib.HasBeenUpdated(id); }

View File

@@ -240,6 +240,13 @@ public class Texture : MonoBehaviour
}
}
int clipPositionScaleKey_;
void Awake()
{
clipPositionScaleKey_ = Shader.PropertyToID("_ClipPositionScale");
}
void OnEnable()
{
if (monitor == null) {
@@ -271,7 +278,9 @@ public class Texture : MonoBehaviour
void RequireUpdate()
{
monitor.shouldBeUpdated = true;
if (monitor != null) {
monitor.shouldBeUpdated = true;
}
}
void Reinitialize()
@@ -283,8 +292,12 @@ public class Texture : MonoBehaviour
void UpdateMaterial()
{
width = transform.localScale.x;
rotation = monitor.rotation;
material.SetVector("_ClipPositionScale", new Vector4(clipPos.x, clipPos.y, clipScale.x, clipScale.y));
if (monitor != null) {
rotation = monitor.rotation;
}
material.SetVector(clipPositionScaleKey_, new Vector4(clipPos.x, clipPos.y, clipScale.x, clipScale.y));
}
public Vector3 GetWorldPositionFromCoord(Vector2 coord)
@@ -401,6 +414,19 @@ public class Texture : MonoBehaviour
// Calculate coordinates.
var coordX = toAngle / halfWidthAngle * 0.5f;
var coordY = ly / halfHeight * 0.5f;
// Zoom
if (useClip) {
coordX = clipPos.x + (0.5f + coordX) * clipScale.x;
coordX -= Mathf.Floor(coordX);
coordX -= 0.5f;
coordY = (1f - clipPos.y) + (coordY - 0.5f) * clipScale.y;
coordY -= Mathf.Floor(coordY);
coordY -= 0.5f;
}
// Desktop position
int desktopX = monitor.left + (int)((coordX + 0.5f) * monitor.width);
int desktopY = monitor.top + (int)((0.5f - coordY) * monitor.height);

View File

@@ -58,9 +58,11 @@ inline float2 uddClipUV(float2 uv)
inline void uddConvertToLinearIfNeeded(inout fixed3 rgb)
{
#ifdef USE_GAMMA_TO_LINEAR_SPACE
if (!IsGammaSpace()) {
rgb = GammaToLinearSpace(rgb);
}
#endif
}
inline fixed4 uddGetTexture(sampler2D tex, float2 uv)

View File

@@ -31,6 +31,7 @@ SubShader
#pragma multi_compile ___ USE_CLIP
#pragma multi_compile ___ BEND_ON
#pragma multi_compile _FORWARD_Y _FORWARD_Z
#pragma multi_compile ___ USE_GAMMA_TO_LINEAR_SPACE
#define SURFACE_SHADER
#include "./uDD_Common.cginc"

View File

@@ -55,6 +55,7 @@ Pass
#pragma multi_compile ___ USE_CLIP
#pragma multi_compile ___ BEND_ON
#pragma multi_compile _FORWARD_Y _FORWARD_Z
#pragma multi_compile ___ USE_GAMMA_TO_LINEAR_SPACE
ENDCG
}

View File

@@ -61,6 +61,7 @@ Pass
#pragma multi_compile ___ USE_CLIP
#pragma multi_compile ___ BEND_ON
#pragma multi_compile _FORWARD_Y _FORWARD_Z
#pragma multi_compile ___ USE_GAMMA_TO_LINEAR_SPACE
ENDCG
}

View File

@@ -142,7 +142,7 @@ DsOutput domain(
float disp = length(_DispTex.SampleLevel(sampler_DispTex, o.f2TexCoord, 0)) * _DispFactor;
f3Position.xyz += f3Normal * disp;
o.f4Position = mul(UNITY_MATRIX_MVP, float4(f3Position.xyz, 1.0));
o.f4Position = UnityObjectToClipPos(float4(f3Position.xyz, 1.0));
return o;
}
@@ -168,6 +168,7 @@ Pass
#pragma multi_compile ___ USE_CLIP
#pragma multi_compile ___ BEND_ON
#pragma multi_compile _FORWARD_Y _FORWARD_Z
#pragma multi_compile ___ USE_GAMMA_TO_LINEAR_SPACE
ENDCG
}

View File

@@ -57,6 +57,7 @@ Pass
#pragma multi_compile ___ USE_CLIP
#pragma multi_compile ___ BEND_ON
#pragma multi_compile _FORWARD_Y _FORWARD_Z
#pragma multi_compile ___ USE_GAMMA_TO_LINEAR_SPACE
ENDCG
}

View File

@@ -0,0 +1,5 @@
LIBRARY
EXPORTS
UnityPluginLoad
UnityPluginUnload

View File

@@ -0,0 +1,34 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uDesktopDuplication", "uDesktopDuplication\uDesktopDuplication.vcxproj", "{BC5DE2F9-BDCC-4449-A017-E5642E04BB56}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Win32 = Release|Win32
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BC5DE2F9-BDCC-4449-A017-E5642E04BB56}.Debug|Win32.ActiveCfg = Debug|Win32
{BC5DE2F9-BDCC-4449-A017-E5642E04BB56}.Debug|Win32.Build.0 = Debug|Win32
{BC5DE2F9-BDCC-4449-A017-E5642E04BB56}.Debug|x64.ActiveCfg = Debug|x64
{BC5DE2F9-BDCC-4449-A017-E5642E04BB56}.Debug|x64.Build.0 = Debug|x64
{BC5DE2F9-BDCC-4449-A017-E5642E04BB56}.Debug|x86.ActiveCfg = Debug|Win32
{BC5DE2F9-BDCC-4449-A017-E5642E04BB56}.Debug|x86.Build.0 = Debug|Win32
{BC5DE2F9-BDCC-4449-A017-E5642E04BB56}.Release|Win32.ActiveCfg = Release|Win32
{BC5DE2F9-BDCC-4449-A017-E5642E04BB56}.Release|Win32.Build.0 = Release|Win32
{BC5DE2F9-BDCC-4449-A017-E5642E04BB56}.Release|x64.ActiveCfg = Release|x64
{BC5DE2F9-BDCC-4449-A017-E5642E04BB56}.Release|x64.Build.0 = Release|x64
{BC5DE2F9-BDCC-4449-A017-E5642E04BB56}.Release|x86.ActiveCfg = Release|Win32
{BC5DE2F9-BDCC-4449-A017-E5642E04BB56}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -17,6 +17,29 @@ extern std::unique_ptr<MonitorManager> g_manager;
extern std::queue<Message> g_messages;
void OutputWindowsInformation()
{
const auto hModule = ::LoadLibrary(TEXT("ntdll.dll"));
if (!hModule) return;
ScopedReleaser freeModule([&] { ::FreeLibrary(hModule); });
if (const auto address = ::GetProcAddress(hModule, "RtlGetVersion"))
{
using RtlGetVersionType = NTSTATUS(WINAPI *)(OSVERSIONINFOEXW*);
const auto RtlGetVersion = reinterpret_cast<RtlGetVersionType>(address);
OSVERSIONINFOEXW os = { sizeof(os) };
if (!FAILED(RtlGetVersion(&os)))
{
Debug::Log("OS Version : ", os.dwMajorVersion, ".", os.dwMinorVersion);
Debug::Log("Build Number : ", os.dwBuildNumber);
Debug::Log("Service Pack : ", os.szCSDVersion);
}
}
}
IUnityInterfaces* GetUnity()
{
return g_unity;
@@ -37,7 +60,9 @@ const std::unique_ptr<MonitorManager>& GetMonitorManager()
LUID GetUnityAdapterLuid()
{
const auto device = GetUnity()->Get<IUnityGraphicsD3D11>()->GetDevice();
UDD_FUNCTION_SCOPE_TIMER
const auto device = GetDevice();
Microsoft::WRL::ComPtr<IDXGIDevice1> dxgiDevice;
if (FAILED(device->QueryInterface(IID_PPV_ARGS(&dxgiDevice)))){

View File

@@ -7,6 +7,9 @@
// Output windows version
void OutputWindowsInformation();
// Unity interface getter
struct IUnityInterfaces;
IUnityInterfaces* GetUnity();

View File

@@ -21,6 +21,8 @@ Cursor::~Cursor()
void Cursor::UpdateBuffer(Duplicator* duplicator, const DXGI_OUTDUPL_FRAME_INFO& frameInfo)
{
UDD_FUNCTION_SCOPE_TIMER
if (frameInfo.LastMouseUpdateTime.QuadPart == 0)
{
return;
@@ -62,16 +64,18 @@ void Cursor::UpdateBuffer(Duplicator* duplicator, const DXGI_OUTDUPL_FRAME_INFO&
}
void Cursor::Draw(
void Cursor::UpdateTexture(
Duplicator* duplicator,
const ComPtr<ID3D11Texture2D>& targetTexture)
const ComPtr<ID3D11Texture2D>& desktopTexture)
{
UDD_FUNCTION_SCOPE_TIMER
auto monitor = duplicator->GetMonitor();
// Check desktop texure
if (targetTexture == nullptr)
if (desktopTexture == nullptr)
{
Debug::Error("Cursor::UpdateTexture() => target texture is null.");
Debug::Error("Cursor::UpdateTexture() => Desktop texture is null.");
return;
}
@@ -97,6 +101,7 @@ void Cursor::Draw(
// Check buffers
if (!bgraBuffer_ || !buffer_)
{
Debug::Error("Cursor::UpdateTexture() => no buffer.");
return;
}
@@ -193,7 +198,7 @@ void Cursor::Draw(
return;
}
D3D11_BOX capturedImageArea
capturedImageArea_ = D3D11_BOX
{
static_cast<UINT>(capturedImageLeft),
static_cast<UINT>(capturedImageTop),
@@ -230,7 +235,7 @@ void Cursor::Draw(
{
ComPtr<ID3D11DeviceContext> context;
duplicator->GetDevice()->GetImmediateContext(&context);
context->CopySubresourceRegion(texture.Get(), 0, 0, 0, 0, targetTexture.Get(), 0, &capturedImageArea);
context->CopySubresourceRegion(texture.Get(), 0, 0, 0, 0, desktopTexture.Get(), 0, &capturedImageArea_);
}
// Get mapped surface to access pixels in CPU
@@ -358,12 +363,6 @@ void Cursor::Draw(
}
}
{
ComPtr<ID3D11DeviceContext> context;
duplicator->GetDevice()->GetImmediateContext(&context);
context->UpdateSubresource(targetTexture.Get(), 0, &capturedImageArea, bgraBuffer_.Get(), capturedImageWidth * 4, 0);
}
if (FAILED(surface->Unmap()))
{
Debug::Error("Cursor::UpdateTexture() => surface->Unmap() failed.");
@@ -372,8 +371,27 @@ void Cursor::Draw(
}
void Cursor::Draw(const Microsoft::WRL::ComPtr<ID3D11Texture2D>& texture)
{
UDD_FUNCTION_SCOPE_TIMER
if (texture == nullptr)
{
Debug::Error("Cursor::UpdateTexture() => Desktop texture is null.");
return;
}
const auto capturedImageWidth = capturedImageArea_.right - capturedImageArea_.left;
ComPtr<ID3D11DeviceContext> context;
GetDevice()->GetImmediateContext(&context);
context->UpdateSubresource(texture.Get(), 0, &capturedImageArea_, bgraBuffer_.Get(), capturedImageWidth * 4, 0);
}
void Cursor::GetTexture(ID3D11Texture2D* texture)
{
UDD_FUNCTION_SCOPE_TIMER
if (!bgraBuffer_)
{
Debug::Error("Cursor::GetTexture() => bgra32Buffer is null.");

View File

@@ -17,9 +17,10 @@ public:
void UpdateBuffer(
Duplicator* duplicator,
const DXGI_OUTDUPL_FRAME_INFO& frameInfo);
void Draw(
Duplicator* duplicator,
const Microsoft::WRL::ComPtr<ID3D11Texture2D>& targetTexture);
void UpdateTexture(
Duplicator* duplicator,
const Microsoft::WRL::ComPtr<ID3D11Texture2D>& desktopTexture);
void Draw(const Microsoft::WRL::ComPtr<ID3D11Texture2D>& texture);
void GetTexture(ID3D11Texture2D* texture);
bool IsVisible() const;
@@ -38,4 +39,5 @@ private:
Buffer<BYTE> bgraBuffer_;
DXGI_OUTDUPL_POINTER_SHAPE_INFO shapeInfo_;
LARGE_INTEGER timestamp_;
D3D11_BOX capturedImageArea_;
};

View File

@@ -39,4 +39,18 @@ void Debug::Finalize()
}
Debug::SetLogFunc(nullptr);
Debug::SetErrorFunc(nullptr);
}
decltype(DebugFunctionScopedTimer::currentId) DebugFunctionScopedTimer::currentId = 0;
DebugFunctionScopedTimer::DebugFunctionScopedTimer(const char* name)
: ScopedTimer([this](std::chrono::microseconds us) {
Debug::Log("<< [", id_, "]", name_, " : ", us.count(), "[us]");
})
, name_(name)
, id_(currentId++)
{
Debug::Log(">> [", id_, "]", name_);
}

View File

@@ -1,10 +1,20 @@
#pragma once
#include <time.h>
#include <fstream>
#include <sstream>
#include <mutex>
#include "Common.h"
#include "IUnityInterface.h"
// Debug flag
#ifdef _DEBUG
#define UDD_DEBUG_ON
#endif
// Logging
class Debug
{
@@ -32,12 +42,24 @@ private:
};
template <class T>
static void Output(T&& arg)
static void Output(const T& arg)
{
if (mode_ == Mode::None) return;
if (ss_.good())
{
ss_ << std::forward<T>(arg);
ss_ << arg;
}
}
static void Output(const WCHAR* arg)
{
if (mode_ == Mode::None) return;
if (ss_.good())
{
char buf[256];
size_t size;
wcstombs_s(&size, buf, arg, 256);
ss_ << buf;
}
}
@@ -81,10 +103,10 @@ private:
}
template <class Arg, class... RestArgs>
static void _Log(Level level, Arg&& arg, RestArgs&&... restArgs)
static void _Log(Level level, const Arg& arg, const RestArgs&... restArgs)
{
Output(std::forward<Arg>(arg));
_Log(level, std::forward<RestArgs>(restArgs)...);
Output(arg);
_Log(level, restArgs...);
}
static void _Log(Level level)
@@ -133,4 +155,30 @@ private:
static DebugLogFuncPtr logFunc_;
static DebugLogFuncPtr errFunc_;
static std::mutex mutex_;
};
};
class DebugFunctionScopedTimer : public ScopedTimer
{
public:
explicit DebugFunctionScopedTimer(const char* name);
private:
static unsigned int currentId;
const char* const name_;
const unsigned int id_;
};
#ifdef UDD_DEBUG_ON
#define UDD_FUNCTION_SCOPE_TIMER \
DebugFunctionScopedTimer _timer_##__COUNTER__(__FUNCTION__);
#define UDD_SCOPE_TIMER(Name) \
ScopedTimer _timer_##__COUNTER__([](std::chrono::microseconds us) \
{ \
Debug::Log(#Name, " : ", us.count(), " [us]"); \
});
#else
#define UDD_FUNCTION_SCOPE_TIMER
#define UDD_SCOPE_TIMER(Name)
#endif

View File

@@ -7,6 +7,7 @@
#include "IUnityGraphicsD3D11.h"
#include "Device.h"
#include "Debug.h"
#include "Common.h"
#pragma comment(lib, "d3d11.lib")
@@ -14,8 +15,7 @@ using namespace Microsoft::WRL;
IsolatedD3D11Device::IsolatedD3D11Device(UINT cachedTextureNum)
: cachedTextures_(cachedTextureNum)
IsolatedD3D11Device::IsolatedD3D11Device()
{
}
@@ -27,6 +27,8 @@ IsolatedD3D11Device::~IsolatedD3D11Device()
HRESULT IsolatedD3D11Device::Create(const ComPtr<IDXGIAdapter>& adapter)
{
UDD_FUNCTION_SCOPE_TIMER
const auto driverType = adapter ?
D3D_DRIVER_TYPE_UNKNOWN :
D3D_DRIVER_TYPE_HARDWARE;
@@ -65,42 +67,35 @@ ComPtr<ID3D11Device> IsolatedD3D11Device::GetDevice()
}
ComPtr<ID3D11Texture2D> IsolatedD3D11Device::GetCompatibleSharedTexture(
const ComPtr<ID3D11Texture2D>& src,
UINT index)
Microsoft::WRL::ComPtr<ID3D11Texture2D> IsolatedD3D11Device::GetCompatibleSharedTexture(
const ComPtr<ID3D11Texture2D>& src)
{
if (index < 0 || index >= cachedTextures_.size())
{
Debug::Error("IsolatedD3D11Device::GetCompatibleSharedTexture() => ", index, " is out of cachedTextures range.");
return nullptr;
}
auto& cachedTexture = cachedTextures_.at(index);
UDD_FUNCTION_SCOPE_TIMER
D3D11_TEXTURE2D_DESC srcDesc;
src->GetDesc(&srcDesc);
// check if the format and size of the current texture are same as the source one
if (cachedTexture)
if (cachedSharedTexture_)
{
D3D11_TEXTURE2D_DESC targetDesc;
cachedTexture->GetDesc(&targetDesc);
cachedSharedTexture_->GetDesc(&targetDesc);
if (targetDesc.Format == srcDesc.Format &&
targetDesc.Width == srcDesc.Width &&
targetDesc.Height == srcDesc.Height)
{
return cachedTexture;
return cachedSharedTexture_;
}
}
// for sharing this texture with unity device
srcDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
if (FAILED(device_->CreateTexture2D(&srcDesc, nullptr, &cachedTexture)))
if (FAILED(device_->CreateTexture2D(&srcDesc, nullptr, &cachedSharedTexture_)))
{
Debug::Error("IsolatedD3D11Device::GetCompatibleSharedTexture() => Creating shared texture failed.");
return nullptr;
}
return cachedTexture;
return cachedSharedTexture_;
}

View File

@@ -1,6 +1,8 @@
#pragma once
#include <atomic>
#include <vector>
#include <memory>
#include <d3d11.h>
#include <wrl/client.h>
@@ -9,16 +11,15 @@
class IsolatedD3D11Device
{
public:
explicit IsolatedD3D11Device(UINT cachedTextureNum);
IsolatedD3D11Device();
~IsolatedD3D11Device();
HRESULT Create(const Microsoft::WRL::ComPtr<IDXGIAdapter>& adapter);
Microsoft::WRL::ComPtr<ID3D11Device> GetDevice();
Microsoft::WRL::ComPtr<ID3D11Texture2D> GetCompatibleSharedTexture(
const Microsoft::WRL::ComPtr<ID3D11Texture2D>& src,
UINT index);
const Microsoft::WRL::ComPtr<ID3D11Texture2D>& src);
private:
Microsoft::WRL::ComPtr<ID3D11Device> device_;
std::vector<Microsoft::WRL::ComPtr<ID3D11Texture2D>> cachedTextures_;
Microsoft::WRL::ComPtr<ID3D11Texture2D> cachedSharedTexture_;
};

View File

@@ -33,8 +33,9 @@ Duplicator::~Duplicator()
void Duplicator::InitializeDevice()
{
const UINT cachedTextureNum = 2;
device_ = std::make_shared<IsolatedD3D11Device>(cachedTextureNum);
UDD_FUNCTION_SCOPE_TIMER
device_ = std::make_shared<IsolatedD3D11Device>();
if (FAILED(device_->Create(monitor_->GetAdapter())))
{
@@ -46,8 +47,11 @@ void Duplicator::InitializeDevice()
void Duplicator::InitializeDuplication()
{
UDD_FUNCTION_SCOPE_TIMER
ComPtr<IDXGIOutput1> output1;
if (FAILED(monitor_->GetOutput().As(&output1))) {
if (FAILED(monitor_->GetOutput().As(&output1)))
{
return;
}
@@ -57,17 +61,7 @@ void Duplicator::InitializeDuplication()
case S_OK:
{
state_ = State::Ready;
const auto rot = static_cast<DXGI_MODE_ROTATION>(monitor_->GetRotation());
Debug::Log("Duplicator::Initialize() => OK.");
Debug::Log(" ID : ", monitor_->GetId());
Debug::Log(" Size : (", monitor_->GetWidth(), ", ", monitor_->GetHeight(), ")");
Debug::Log(" DPI : (", monitor_->GetDpiX(), ", ", monitor_->GetDpiY(), ")");
Debug::Log(" Rot : ",
rot == DXGI_MODE_ROTATION_IDENTITY ? "Landscape" :
rot == DXGI_MODE_ROTATION_ROTATE90 ? "Portrait" :
rot == DXGI_MODE_ROTATION_ROTATE180 ? "Landscape (flipped)" :
rot == DXGI_MODE_ROTATION_ROTATE270 ? "Portrait (flipped)" :
"Unspecified");
break;
}
case E_INVALIDARG:
@@ -117,6 +111,8 @@ void Duplicator::InitializeDuplication()
void Duplicator::CheckUnityAdapter()
{
UDD_FUNCTION_SCOPE_TIMER
DXGI_ADAPTER_DESC desc;
monitor_->GetAdapter()->GetDesc(&desc);
@@ -135,6 +131,8 @@ void Duplicator::CheckUnityAdapter()
void Duplicator::Start()
{
UDD_FUNCTION_SCOPE_TIMER
if (state_ != State::Ready) return;
Stop();
@@ -162,7 +160,12 @@ void Duplicator::Start()
});
const auto timeout = static_cast<UINT>(frameMilliSeconds);
if (!Duplicate(timeout)) break;
Duplicate(timeout);
if (state_ != State::Running)
{
break;
}
}
if (state_ == State::Running)
@@ -175,6 +178,8 @@ void Duplicator::Start()
void Duplicator::Stop()
{
UDD_FUNCTION_SCOPE_TIMER
shouldRun_ = false;
if (thread_.joinable())
@@ -229,9 +234,13 @@ const Duplicator::Frame& Duplicator::GetLastFrame() const
}
bool Duplicator::Duplicate(UINT timeout)
void Duplicator::Duplicate(UINT timeout)
{
if (!dupl_ || !device_) return false;
UDD_FUNCTION_SCOPE_TIMER
if (!dupl_ || !device_) return;
Release();
ComPtr<IDXGIResource> resource;
DXGI_OUTDUPL_FRAME_INFO frameInfo;
@@ -247,89 +256,104 @@ bool Duplicator::Duplicate(UINT timeout)
// it is necessary to re-initialize monitors.
Debug::Log("Duplicator::Duplicate() => DXGI_ERROR_ACCESS_LOST.");
state_ = State::AccessLost;
return false;
break;
}
case DXGI_ERROR_WAIT_TIMEOUT:
{
// This often occurs when timeout value is small and it is not problem.
// Debug::Log("Duplicator::Duplicate() => DXGI_ERROR_WAIT_TIMEOUT.");
return true;
break;
}
case DXGI_ERROR_INVALID_CALL:
{
Debug::Error("Duplicator::Duplicate() => DXGI_ERROR_INVALID_CALL.");
return false;
break;
}
case E_INVALIDARG:
{
Debug::Error("Duplicator::Duplicate() => E_INVALIDARG.");
return false;
break;
}
default:
{
state_ = State::Unknown;
Debug::Error("Duplicator::Duplicate() => Unknown Error.");
return false;
break;
}
}
return;
}
ScopedReleaser releaser([this]
{
const auto hr = dupl_->ReleaseFrame();
if (FAILED(hr))
{
switch (hr)
{
case DXGI_ERROR_ACCESS_LOST:
{
Debug::Log("Duplicator::Duplicate() => DXGI_ERROR_ACCESS_LOST.");
state_ = State::AccessLost;
break;
}
case DXGI_ERROR_INVALID_CALL:
{
Debug::Error("Duplicator::Duplicate() => DXGI_ERROR_INVALID_CALL.");
break;
}
default:
{
state_ = State::Unknown;
Debug::Error("Duplicator::Duplicate() => Unknown Error.");
break;
}
}
}
});
isFrameAcquired_ = true;
ComPtr<ID3D11Texture2D> texture;
if (FAILED(resource.As(&texture)))
{
return false;
Debug::Error("Duplicator::Duplicate() => IDXGIResource could not be converted to ID3D11Texture2D.");
return;
}
auto sharedTexture = device_->GetCompatibleSharedTexture(texture, frame % 2);
auto sharedTexture = device_->GetCompatibleSharedTexture(texture);
if (!sharedTexture)
{
return false;
Debug::Error("Duplicator::Duplicate() => Shared texture is null.");
return;
}
ComPtr<ID3D11DeviceContext> context;
device_->GetDevice()->GetImmediateContext(&context);
context->CopyResource(sharedTexture.Get(), texture.Get());
{
ComPtr<ID3D11DeviceContext> context;
device_->GetDevice()->GetImmediateContext(&context);
context->CopyResource(sharedTexture.Get(), texture.Get());
}
UpdateCursor(sharedTexture, frameInfo);
UpdateMetadata(frameInfo.TotalMetadataBufferSize);
{
std::lock_guard<std::mutex> lock(mutex_);
lastFrame_.frame = frame++;
lastFrame_.texture = sharedTexture;
lastFrame_.info = frameInfo;
lastFrame_.metaData = metaData_;
lastFrame_ = Frame
{
lastFrameId_++,
sharedTexture,
frameInfo,
metaData_
};
}
}
void Duplicator::Release()
{
UDD_FUNCTION_SCOPE_TIMER
if (!isFrameAcquired_) return;
const auto hr = dupl_->ReleaseFrame();
if (FAILED(hr))
{
switch (hr)
{
case DXGI_ERROR_ACCESS_LOST:
{
Debug::Log("Duplicator::Duplicate() => DXGI_ERROR_ACCESS_LOST.");
state_ = State::AccessLost;
break;
}
case DXGI_ERROR_INVALID_CALL:
{
Debug::Error("Duplicator::Duplicate() => DXGI_ERROR_INVALID_CALL.");
break;
}
default:
{
state_ = State::Unknown;
Debug::Error("Duplicator::Duplicate() => Unknown Error.");
break;
}
}
}
return true;
isFrameAcquired_ = false;
}
@@ -337,6 +361,8 @@ void Duplicator::UpdateCursor(
const ComPtr<ID3D11Texture2D>& texture,
const DXGI_OUTDUPL_FRAME_INFO& frameInfo)
{
UDD_FUNCTION_SCOPE_TIMER
auto& manager = GetMonitorManager();
if (frameInfo.PointerPosition.Visible)
@@ -348,13 +374,15 @@ void Duplicator::UpdateCursor(
{
auto cursor = manager->GetCursor();
cursor->UpdateBuffer(this, frameInfo);
cursor->Draw(this, texture);
cursor->UpdateTexture(this, texture);
}
}
void Duplicator::UpdateMetadata(UINT totalBufferSize)
{
UDD_FUNCTION_SCOPE_TIMER
metaData_.buffer.ExpandIfNeeded(totalBufferSize);
if (!metaData_.buffer.Empty())
{
@@ -366,6 +394,8 @@ void Duplicator::UpdateMetadata(UINT totalBufferSize)
void Duplicator::UpdateMoveRects()
{
UDD_FUNCTION_SCOPE_TIMER
const auto hr = dupl_->GetFrameMoveRects(
metaData_.buffer.Size(),
metaData_.buffer.As<DXGI_OUTDUPL_MOVE_RECT>(),
@@ -408,6 +438,8 @@ void Duplicator::UpdateMoveRects()
void Duplicator::UpdateDirtyRects()
{
UDD_FUNCTION_SCOPE_TIMER
const auto hr = dupl_->GetFrameDirtyRects(
metaData_.buffer.Size() - metaData_.moveRectSize,
metaData_.buffer.As<RECT>(metaData_.moveRectSize /* offset */),

View File

@@ -44,7 +44,7 @@ public:
struct Frame
{
UINT frame = 0;
UINT id;
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture;
DXGI_OUTDUPL_FRAME_INFO info;
Metadata metaData;
@@ -67,7 +67,8 @@ private:
void InitializeDuplication();
void CheckUnityAdapter();
bool Duplicate(UINT timeout);
void Duplicate(UINT timeout);
void Release();
void UpdateCursor(
const Microsoft::WRL::ComPtr<ID3D11Texture2D>& texture,
@@ -76,13 +77,14 @@ private:
void UpdateMoveRects();
void UpdateDirtyRects();
Monitor* monitor_ = nullptr;
Monitor* const monitor_ = nullptr;
std::atomic<State> state_ = State::Ready;
std::shared_ptr<class IsolatedD3D11Device> device_;
Microsoft::WRL::ComPtr<IDXGIOutputDuplication> dupl_;
Frame lastFrame_;
UINT frame = 0;
UINT lastFrameId_ = 0;
bool isFrameAcquired_ = false;
volatile bool shouldRun_ = false;
std::thread thread_;

View File

@@ -21,7 +21,6 @@ Monitor::Monitor(int id)
Monitor::~Monitor()
{
duplicator_->Stop();
}
@@ -30,6 +29,8 @@ void Monitor::Initialize(
const ComPtr<IDXGIOutput> &output
)
{
UDD_FUNCTION_SCOPE_TIMER
adapter_ = adapter;
output_ = output;
@@ -58,44 +59,74 @@ void Monitor::Initialize(
// DPI is set as -1, so the application has to use the appropriate value.
}
const auto rot = outputDesc_.Rotation;
Debug::Log("Monitor::Initialized() =>");
Debug::Log(" ID : ", id_);
Debug::Log(" Size : (", width_, ", ", height_, ")");
Debug::Log(" DPI : (", dpiX_, ", ", dpiY_, ")");
Debug::Log(" Rot : ",
rot == DXGI_MODE_ROTATION_IDENTITY ? "Landscape" :
rot == DXGI_MODE_ROTATION_ROTATE90 ? "Portrait" :
rot == DXGI_MODE_ROTATION_ROTATE180 ? "Landscape (flipped)" :
rot == DXGI_MODE_ROTATION_ROTATE270 ? "Portrait (flipped)" :
"Unspecified");
duplicator_ = std::make_shared<Duplicator>(this);
}
void Monitor::Finalize()
{
UDD_FUNCTION_SCOPE_TIMER
StopCapture();
}
void Monitor::Render()
{
UDD_FUNCTION_SCOPE_TIMER
const auto& frame = duplicator_->GetLastFrame();
const auto& texture = frame.texture;
if (!texture) return;
if (frame.id == lastFrameId_) return;
lastFrameId_ = frame.id;
// Get texture
if (unityTexture_)
{
D3D11_TEXTURE2D_DESC srcDesc, dstDesc;
texture->GetDesc(&srcDesc);
unityTexture_->GetDesc(&dstDesc);
if (srcDesc.Width != dstDesc.Width ||
srcDesc.Height != dstDesc.Height)
{
Debug::Error("Monitor::Render() => Texture sizes are defferent.");
Debug::Error(" Source : (", srcDesc.Width, ", ", srcDesc.Height, ")");
Debug::Error(" Dest : (", dstDesc.Width, ", ", dstDesc.Height, ")");
return;
}
else
{
ComPtr<ID3D11DeviceContext> context;
GetDevice()->GetImmediateContext(&context);
context->CopyResource(unityTexture_, texture.Get());
}
}
if (unityTexture_ == nullptr)
{
Debug::Error("Monitor::Render() => Target texture has not been set yet.");
return;
}
if (!frame.texture)
{
Debug::Error("Monitor::Render() => frame doesn't have texture.");
return;
}
D3D11_TEXTURE2D_DESC srcDesc, dstDesc;
frame.texture->GetDesc(&srcDesc);
unityTexture_->GetDesc(&dstDesc);
if (srcDesc.Width != dstDesc.Width ||
srcDesc.Height != dstDesc.Height)
{
Debug::Error("Monitor::Render() => Texture sizes are defferent.");
Debug::Error(" Source : (", srcDesc.Width, ", ", srcDesc.Height, ")");
Debug::Error(" Dest : (", dstDesc.Width, ", ", dstDesc.Height, ")");
return;
}
else
{
ComPtr<ID3D11DeviceContext> context;
GetDevice()->GetImmediateContext(&context);
context->CopyResource(unityTexture_, frame.texture.Get());
auto& manager = GetMonitorManager();
if (id_ == manager->GetCursorMonitorId())
{
manager->GetCursor()->Draw(unityTexture_);
}
}
if (UseGetPixels())
{
@@ -108,6 +139,8 @@ void Monitor::Render()
void Monitor::StartCapture()
{
UDD_FUNCTION_SCOPE_TIMER
if (duplicator_->GetState() == DuplicatorState::Ready)
{
duplicator_->Start();
@@ -117,6 +150,8 @@ void Monitor::StartCapture()
void Monitor::StopCapture()
{
UDD_FUNCTION_SCOPE_TIMER
duplicator_->Stop();
}
@@ -277,6 +312,8 @@ bool Monitor::UseGetPixels() const
void Monitor::CopyTextureFromGpuToCpu(ID3D11Texture2D* texture)
{
UDD_FUNCTION_SCOPE_TIMER
const auto monitorRot = static_cast<DXGI_MODE_ROTATION>(GetRotation());
const auto monitorWidth = GetWidth();
const auto monitorHeight = GetHeight();
@@ -342,6 +379,8 @@ void Monitor::CopyTextureFromGpuToCpu(ID3D11Texture2D* texture)
bool Monitor::GetPixels(BYTE* output, int x, int y, int width, int height)
{
UDD_FUNCTION_SCOPE_TIMER
if (!UseGetPixels())
{
Debug::Error("Monitor::GetPixels() => UseGetPixels(true) must have been called when you want to use GetPixels().");
@@ -372,24 +411,24 @@ bool Monitor::GetPixels(BYTE* output, int x, int y, int width, int height)
{
left = y;
top = monitorWidth - x - width;
right = y + width;
bottom = monitorWidth - x;
right = y + width - 1;
bottom = monitorWidth - x - 1;
break;
}
case DXGI_MODE_ROTATION_ROTATE180:
{
left = monitorWidth - x - width;
top = monitorHeight - y - height;
right = monitorWidth - x;
bottom = monitorHeight - y;
right = monitorWidth - x - 1;
bottom = monitorHeight - y - 1;
break;
}
case DXGI_MODE_ROTATION_ROTATE270:
{
left = monitorHeight - y - height;
top = x;
right = monitorHeight - y;
bottom = x + width;
right = monitorHeight - y - 1;
bottom = x + width - 1;
break;
}
case DXGI_MODE_ROTATION_IDENTITY:
@@ -398,8 +437,8 @@ bool Monitor::GetPixels(BYTE* output, int x, int y, int width, int height)
{
left = x;
top = y;
right = x + width;
bottom = y + height;
right = x + width - 1;
bottom = y + height - 1;
break;
}
}
@@ -450,7 +489,6 @@ bool Monitor::GetPixels(BYTE* output, int x, int y, int width, int height)
const auto outCol = col;
const auto outIndex = 4 * (outRow * width + outCol);
// BGRA -> RGBA
output[outIndex + 0] = bufferForGetPixels_[inIndex + 2];
output[outIndex + 1] = bufferForGetPixels_[inIndex + 1];
@@ -461,3 +499,14 @@ bool Monitor::GetPixels(BYTE* output, int x, int y, int width, int height)
return true;
}
BYTE* Monitor::GetBuffer() const
{
if (!bufferForGetPixels_)
{
Debug::Error("Monitor::GetBuffer() => CopyTextureFromGpuToCpu() has not been called yet.");
return nullptr;
}
return bufferForGetPixels_.Get();
}

View File

@@ -9,6 +9,7 @@
#include "Common.h"
class MonitorManager;
enum class DuplicatorState;
@@ -52,15 +53,15 @@ public:
void UseGetPixels(bool use);
bool UseGetPixels() const;
bool GetPixels(BYTE* output, int x, int y, int width, int height);
BYTE* GetBuffer() const;
private:
void CopyTextureFromGpuToCpu(ID3D11Texture2D* texture);
int id_ = -1;
MonitorManager* manager_ = nullptr;
const int id_;
UINT dpiX_ = -1, dpiY_ = -1;
int width_ = -1, height_ = -1;
bool hasBeenUpdated_ = false;
bool useGetPixels_ = false;
@@ -70,6 +71,7 @@ private:
MONITORINFOEX monitorInfo_;
std::shared_ptr<class Duplicator> duplicator_;
UINT lastFrameId_ = -1;
ID3D11Texture2D* unityTexture_ = nullptr;
Microsoft::WRL::ComPtr<ID3D11Texture2D> textureForGetPixels_;

View File

@@ -18,23 +18,20 @@ using namespace Microsoft::WRL;
MonitorManager::MonitorManager(LUID unityAdapterLuid)
: unityAdapterLuid_(unityAdapterLuid)
MonitorManager::MonitorManager()
{
}
MonitorManager::~MonitorManager()
{
Finalize();
}
void MonitorManager::Initialize()
{
Finalize();
UDD_FUNCTION_SCOPE_TIMER
// Get factory
ComPtr<IDXGIFactory1> factory;
if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&factory))))
{
@@ -42,27 +39,40 @@ void MonitorManager::Initialize()
return;
}
// Check all display adapters
int id = 0;
std::vector<std::pair<ComPtr<IDXGIAdapter1>, ComPtr<IDXGIOutput>>> outputs;
ComPtr<IDXGIAdapter1> adapter;
for (int i = 0; (factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND); ++i)
{
// Search the main monitor from all outputs
DXGI_ADAPTER_DESC desc;
if (FAILED(adapter->GetDesc(&desc))) continue;
Debug::Log("Graphics Card [", i, "] : ", desc.Description);
ComPtr<IDXGIOutput> output;
for (int j = 0; (adapter->EnumOutputs(j, &output) != DXGI_ERROR_NOT_FOUND); ++j)
{
auto monitor = std::make_shared<Monitor>(id++);
const auto unityAdapterLuid = GetUnityAdapterLuid();
monitor->Initialize(adapter, output);
monitor->StartCapture();
monitors_.push_back(monitor);
DXGI_OUTPUT_DESC desc;
if (FAILED(output->GetDesc(&desc))) continue;
Debug::Log(" > Monitor[", j, "] : ", desc.DeviceName);
outputs.emplace_back(adapter, output);
}
}
for (int id = 0; id < static_cast<int>(outputs.size()); ++id)
{
const auto& pair = outputs.at(id);
auto monitor = std::make_shared<Monitor>(id);
monitor->Initialize(pair.first, pair.second);
monitor->StartCapture();
monitors_.push_back(monitor);
}
}
void MonitorManager::Finalize()
{
UDD_FUNCTION_SCOPE_TIMER
for (const auto& monitor : monitors_)
{
monitor->Finalize();
@@ -74,6 +84,8 @@ void MonitorManager::Finalize()
void MonitorManager::Update()
{
UDD_FUNCTION_SCOPE_TIMER
if (isReinitializationRequired_)
{
Reinitialize();
@@ -84,13 +96,17 @@ void MonitorManager::Update()
void MonitorManager::RequireReinitilization()
{
Debug::Log("MonitorManager::Reinitialize() was required.");
isReinitializationRequired_ = true;
}
void MonitorManager::Reinitialize()
{
UDD_FUNCTION_SCOPE_TIMER
Debug::Log("MonitorManager::Reinitialize()");
Finalize();
Initialize();
SendMessageToUnity(Message::Reinitialized);
}
@@ -98,6 +114,8 @@ void MonitorManager::Reinitialize()
bool MonitorManager::HasMonitorCountChanged() const
{
UDD_FUNCTION_SCOPE_TIMER
ComPtr<IDXGIFactory1> factory;
if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&factory))))
{

View File

@@ -13,7 +13,7 @@ class Cursor;
class MonitorManager
{
public:
explicit MonitorManager(LUID unityAdapterLuid_);
MonitorManager();
~MonitorManager();
void Initialize();
void Finalize();
@@ -34,7 +34,6 @@ public:
int GetTotalHeight() const;
private:
LUID unityAdapterLuid_;
UINT frameRate_ = 60;
bool enableTextureCopyFromGpuToCpu_ = false;
std::vector<std::shared_ptr<Monitor>> monitors_;

View File

@@ -23,7 +23,6 @@
IUnityInterfaces* g_unity = nullptr;
std::unique_ptr<MonitorManager> g_manager;
std::queue<Message> g_messages;
ID3D11DeviceContext* g_deviceContextForMainThread = nullptr;
extern "C"
@@ -35,38 +34,24 @@ extern "C"
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API Initialize()
{
if (g_unity && !g_manager)
if (!g_unity) return;
if (!g_manager)
{
Debug::Initialize();
auto device = g_unity->Get<IUnityGraphicsD3D11>()->GetDevice();
Microsoft::WRL::ComPtr<IDXGIDevice1> dxgiDevice;
if (FAILED(device->QueryInterface(IID_PPV_ARGS(&dxgiDevice)))){
Debug::Error("fatal");
return;
}
Microsoft::WRL::ComPtr<IDXGIAdapter> dxgiAdapter;
if (FAILED(dxgiDevice->GetAdapter(&dxgiAdapter))) {
Debug::Error("fatal");
return;
}
DXGI_ADAPTER_DESC desc;
dxgiAdapter->GetDesc(&desc);
g_manager = std::make_unique<MonitorManager>(desc.AdapterLuid);
OutputWindowsInformation();
g_manager = std::make_unique<MonitorManager>();
g_manager->Initialize();
}
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API Finalize()
{
if (!g_manager) return;
g_manager->Finalize();
g_manager.reset();
if (g_manager)
{
g_manager->Finalize();
g_manager.reset();
}
std::queue<Message> empty;
g_messages.swap(empty);
@@ -381,7 +366,7 @@ extern "C"
return 0;
}
UNITY_INTERFACE_EXPORT void* UNITY_INTERFACE_API GetMoveRects(int id)
UNITY_INTERFACE_EXPORT DXGI_OUTDUPL_MOVE_RECT* UNITY_INTERFACE_API GetMoveRects(int id)
{
if (!g_manager) return nullptr;
if (auto monitor = g_manager->GetMonitor(id))
@@ -401,7 +386,7 @@ extern "C"
return 0;
}
UNITY_INTERFACE_EXPORT void* UNITY_INTERFACE_API GetDirtyRects(int id)
UNITY_INTERFACE_EXPORT RECT* UNITY_INTERFACE_API GetDirtyRects(int id)
{
if (!g_manager) return nullptr;
if (auto monitor = g_manager->GetMonitor(id))
@@ -413,7 +398,7 @@ extern "C"
UNITY_INTERFACE_EXPORT bool UNITY_INTERFACE_API GetPixels(int id, BYTE* output, int x, int y, int width, int height)
{
if (!g_manager) return nullptr;
if (!g_manager) return false;
if (auto monitor = g_manager->GetMonitor(id))
{
return monitor->GetPixels(output, x, y, width, height);
@@ -421,6 +406,16 @@ extern "C"
return false;
}
UNITY_INTERFACE_EXPORT BYTE* UNITY_INTERFACE_API GetBuffer(int id)
{
if (!g_manager) return nullptr;
if (auto monitor = g_manager->GetMonitor(id))
{
return monitor->GetBuffer();
}
return nullptr;
}
UNITY_INTERFACE_EXPORT bool UNITY_INTERFACE_API HasBeenUpdated(int id)
{
if (!g_manager) return nullptr;

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -21,7 +21,7 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{BC5DE2F9-BDCC-4449-A017-E5642E04BB56}</ProjectGuid>
<RootNamespace>uDesktopDuplication</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
<ProjectName>uDesktopDuplication</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
@@ -82,6 +82,8 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);include</IncludePath>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -92,6 +94,10 @@
<PostBuildEvent>
<Command>copy /Y "$(SolutionDir)$(Platform)\$(Configuration)\$(TargetFileName)" "$(SolutionDir)..\..\Assets\$(ProjectName)\Plugins\x86_64"</Command>
</PostBuildEvent>
<Link>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -100,8 +106,11 @@
<SDLCheck>true</SDLCheck>
</ClCompile>
<PostBuildEvent>
<Command>copy /Y "$(SolutionDir)$(Platform)\$(Configuration)\$(TargetFileName)" "$(SolutionDir)..\..\Assets\$(ProjectName)\Plugins\x86_64"</Command>
<Command>copy /Y "$(SolutionDir)$(Platform)\$(Configuration)\$(TargetFileName)" "$(SolutionDir)..\..\Assets\$(ProjectName)\Plugins\x86"</Command>
</PostBuildEvent>
<Link>
<ModuleDefinitionFile>$(SolutionDir)$(ProjectName).def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
@@ -115,6 +124,8 @@
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
</Link>
<PostBuildEvent>
<Command>copy /Y "$(SolutionDir)$(Platform)\$(Configuration)\$(TargetFileName)" "$(SolutionDir)..\..\Assets\$(ProjectName)\Plugins\x86_64"</Command>
@@ -132,6 +143,7 @@
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>$(SolutionDir)$(ProjectName).def</ModuleDefinitionFile>
</Link>
<PostBuildEvent>
<Command>copy /Y "$(SolutionDir)$(Platform)\$(Configuration)\$(TargetFileName)" "$(SolutionDir)..\..\Assets\$(ProjectName)\Plugins\x86"</Command>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,6 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1386491679 &1
PresetManager:
m_ObjectHideFlags: 0
m_DefaultList: []

View File

@@ -1 +1 @@
m_EditorVersion: 5.5.0f3
m_EditorVersion: 2018.2.15f1

Binary file not shown.

Binary file not shown.

View File

@@ -2,7 +2,6 @@ uDesktopDuplication
===================
![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)
![Build Status](http://unitybuildbadge.azurewebsites.net/api/status/7566d616-2916-4c99-bb14-e7ab9501cf7e)
**uDesktopDuplication** is an Unity asset to use the realtime screen capture as `Texture2D` using Desktop Duplication API.
@@ -28,7 +27,7 @@ Usage
Attach `uDesktopDuplication/Texture` component to the target object, then its main texture will be replaced with the captured screen. Please see example scenes for more details.
Lisence
License
-------
The MIT License (MIT)