diff --git a/Assets/uWindowCapture/Examples/Buffer/Buffer.unity b/Assets/uWindowCapture/Examples/Buffer/Buffer.unity index b27aa00..72df844 100644 Binary files a/Assets/uWindowCapture/Examples/Buffer/Buffer.unity and b/Assets/uWindowCapture/Examples/Buffer/Buffer.unity differ diff --git a/Assets/uWindowCapture/Examples/Buffer/UwcGetBufferExample.cs b/Assets/uWindowCapture/Examples/Buffer/UwcGetBufferExample.cs index 078be37..b98cae7 100644 --- a/Assets/uWindowCapture/Examples/Buffer/UwcGetBufferExample.cs +++ b/Assets/uWindowCapture/Examples/Buffer/UwcGetBufferExample.cs @@ -1,24 +1,24 @@ -using UnityEngine; -using System; -using System.Runtime.InteropServices; - -namespace uWindowCapture -{ - -public class UwcGetBufferExample : MonoBehaviour -{ - [SerializeField] - UwcWindowTexture uwcTexture; - - 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); - - bool isValid +using UnityEngine; +using System; +using System.Runtime.InteropServices; + +namespace uWindowCapture +{ + +public class UwcGetBufferExample : MonoBehaviour +{ + [SerializeField] + UwcWindowTexture uwcTexture; + + 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); + + bool isValid { get { @@ -27,60 +27,39 @@ bool isValid var window = uwcTexture.window; return window != null && window.buffer != IntPtr.Zero; } - } - - void OnDestroy() - { - if (ptr_ != IntPtr.Zero) { - handle_.Free(); - } - } - - void Update() - { - if (!isValid) return; - - var window = uwcTexture.window; - if (texture_ == null || - window.bufferWidth != texture_.width || - window.bufferHeight != texture_.height) { - UpdateTexture(); - } - - CopyTexture(); - } - - void UpdateTexture() - { - if (!isValid) return; - - var window = uwcTexture.window; - var width = window.bufferWidth; - var height = window.bufferHeight; - - 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().material.mainTexture = texture_; - } - - void CopyTexture() - { - if (!isValid) return; - - var window = uwcTexture.window; - var width = window.bufferWidth; - var height = window.bufferHeight; - var buffer = window.buffer; - - memcpy(ptr_, buffer, width * height * sizeof(Byte) * 4); - - texture_.SetPixels32(pixels_); - texture_.Apply(); - } -} - + } + + void OnDestroy() + { + if (ptr_ != IntPtr.Zero) { + handle_.Free(); + } + } + + void Update() + { + if (!isValid) return; + + var window = uwcTexture.window; + var width = window.width; + var height = window.height; + + if (texture_ == null || width != texture_.width || height != texture_.height) { + 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().material.mainTexture = texture_; + } + + // memcpy can be run in another thread. + var buffer = window.buffer; + memcpy(ptr_, buffer, width * height * sizeof(Byte) * 4); + + texture_.SetPixels32(pixels_); + texture_.Apply(); + } +} + } \ No newline at end of file diff --git a/Assets/uWindowCapture/Examples/GetPixels/UwcGetPixelsExample.cs b/Assets/uWindowCapture/Examples/GetPixels/UwcGetPixelsExample.cs index 3a99ed8..f53b216 100644 --- a/Assets/uWindowCapture/Examples/GetPixels/UwcGetPixelsExample.cs +++ b/Assets/uWindowCapture/Examples/GetPixels/UwcGetPixelsExample.cs @@ -37,7 +37,8 @@ void Update() var window = uwcTexture.window; if (window == null || window.bufferWidth == 0) return; - if (window.GetPixels(colors, x, y, w, h) /* this can be threaded */) { + // GetPixels() can be run in another thread + if (window.GetPixels(colors, x, y, w, h)) { texture.SetPixels32(colors); texture.Apply(); } diff --git a/Assets/uWindowCapture/Plugins/x86/uWindowCapture.dll b/Assets/uWindowCapture/Plugins/x86/uWindowCapture.dll index 77ee2fa..6721256 100644 Binary files a/Assets/uWindowCapture/Plugins/x86/uWindowCapture.dll and b/Assets/uWindowCapture/Plugins/x86/uWindowCapture.dll differ diff --git a/Assets/uWindowCapture/Plugins/x86_64/uWindowCapture.dll b/Assets/uWindowCapture/Plugins/x86_64/uWindowCapture.dll index c6f8dbf..7f50c7d 100644 Binary files a/Assets/uWindowCapture/Plugins/x86_64/uWindowCapture.dll and b/Assets/uWindowCapture/Plugins/x86_64/uWindowCapture.dll differ diff --git a/Plugins/uWindowCapture/uWindowCapture/Buffer.h b/Plugins/uWindowCapture/uWindowCapture/Buffer.h index 304d612..66f9871 100644 --- a/Plugins/uWindowCapture/uWindowCapture/Buffer.h +++ b/Plugins/uWindowCapture/uWindowCapture/Buffer.h @@ -77,12 +77,12 @@ class Buffer return value_ != nullptr; } - const T operator [](UINT index) const + const T& operator [](UINT index) const { if (index >= size_) { Debug::Error("Array index out of range: ", index, size_); - return T(0); + return value_[0]; } return value_[index]; } diff --git a/Plugins/uWindowCapture/uWindowCapture/WindowTexture.cpp b/Plugins/uWindowCapture/uWindowCapture/WindowTexture.cpp index 091a13f..9d5da5f 100644 --- a/Plugins/uWindowCapture/uWindowCapture/WindowTexture.cpp +++ b/Plugins/uWindowCapture/uWindowCapture/WindowTexture.cpp @@ -348,7 +348,7 @@ bool WindowTexture::Upload() const UINT rawPitch = bufferWidth_ * 4; const int startIndex = offsetX_ * 4 + offsetY_ * rawPitch; - const auto* start = &buffer_[startIndex]; + const auto* start = buffer_.Get(startIndex); ComPtr context; uploader->GetDevice()->GetImmediateContext(&context); @@ -386,9 +386,16 @@ bool WindowTexture::Render() } -BYTE* WindowTexture::GetBuffer() const +BYTE* WindowTexture::GetBuffer() { - return buffer_.Empty() ? nullptr : buffer_.Get(); + if (buffer_.Empty()) return nullptr; + + std::lock_guard lock(bufferMutex_); + + bufferForGetBuffer_.ExpandIfNeeded(buffer_.Size()); + memcpy(bufferForGetBuffer_.Get(), buffer_.Get(), buffer_.Size()); + + return bufferForGetBuffer_.Get(); } diff --git a/Plugins/uWindowCapture/uWindowCapture/WindowTexture.h b/Plugins/uWindowCapture/uWindowCapture/WindowTexture.h index e7c2aee..58d8175 100644 --- a/Plugins/uWindowCapture/uWindowCapture/WindowTexture.h +++ b/Plugins/uWindowCapture/uWindowCapture/WindowTexture.h @@ -42,7 +42,7 @@ class WindowTexture bool Upload(); bool Render(); - BYTE* GetBuffer() const; + BYTE* GetBuffer(); UINT GetPixel(int x, int y) const; bool GetPixels(BYTE* output, int x, int y, int width, int height) const; @@ -60,6 +60,7 @@ class WindowTexture std::mutex sharedTextureMutex_; Buffer buffer_; + Buffer bufferForGetBuffer_; HBITMAP bitmap_ = nullptr; std::atomic bufferWidth_ = 0; std::atomic bufferHeight_ = 0;