@@ -33,21 +33,20 @@ public sealed class PixelViewElement : UserControl
33
33
readonly SpriteVisual _spriteVisual ;
34
34
Visual ? _capturedVisual = null ;
35
35
36
- // Indicates if PixelView should update the image.
37
- public bool Active { get ; set ; } = false ;
38
-
39
36
// Checkerboard pattern bitmap.
40
37
static CanvasBitmap ? _patternBitmap = null ;
41
38
42
39
// Previously rendered bitmap info.
43
- CanvasBitmap ? _previousBitmap = null ;
44
- Color [ ] ? _previousColors = null ;
40
+ CanvasBitmap ? _currentBitmap = null ;
41
+ Color [ ] ? _currentColors = null ;
45
42
46
43
Color ? _currentColor = null ;
47
44
48
- Direct3D11CaptureFramePool ? _framePool = null ;
49
45
GraphicsCaptureSession ? _session = null ;
50
- CanvasDevice ? _canvasDevice = null ;
46
+ Direct3D11CaptureFramePool _framePool ;
47
+ ICompositionSurface _surface ;
48
+ CanvasSwapChain _swapchain ;
49
+ CanvasDevice _canvasDevice ;
51
50
52
51
public static readonly DependencyProperty CurrentColorStringProperty =
53
52
DependencyProperty . RegisterAttached (
@@ -85,6 +84,19 @@ public PixelViewElement()
85
84
_spriteVisual = compositor . CreateSpriteVisual ( ) ;
86
85
_spriteVisual . RelativeSizeAdjustment = Vector2 . One ;
87
86
ElementCompositionPreview . SetElementChildVisual ( this , _spriteVisual ) ;
87
+
88
+ _canvasDevice = CanvasDevice . GetSharedDevice ( ) ;
89
+
90
+ // Swapchain will be resized later
91
+ _swapchain = new CanvasSwapChain ( _canvasDevice , 512 , 512 , 96 ) ;
92
+ _surface = CanvasComposition . CreateCompositionSurfaceForSwapChain ( compositor , _swapchain ) ;
93
+ _spriteVisual . Brush = compositor . CreateSurfaceBrush ( _surface ) ;
94
+
95
+ // Create a frame pool with room for only 1 frame because we're getting a single frame, not a video.
96
+ _framePool =
97
+ Direct3D11CaptureFramePool . Create ( _canvasDevice , DirectXPixelFormat . B8G8R8A8UIntNormalized , 3 , new SizeInt32 { Width = 512 , Height = 512 } ) ;
98
+
99
+ _framePool . FrameArrived += OnFrameArrived ;
88
100
}
89
101
90
102
public void SetElementToCapture ( FrameworkElement element )
@@ -96,58 +108,63 @@ public void SetElementToCapture(FrameworkElement element)
96
108
_capturedVisual . BorderMode = CompositionBorderMode . Soft ;
97
109
98
110
OnResolutionUpdated ( ( int ) element . ActualWidth , ( int ) element . ActualHeight ) ;
111
+
112
+ _session = _framePool . CreateCaptureSession ( GraphicsCaptureItem . CreateFromVisual ( _capturedVisual ) ) ;
113
+ _session . StartCapture ( ) ;
99
114
}
100
115
101
116
public void OnMouseMove ( object sender , PointerRoutedEventArgs e )
102
117
{
103
118
var position = e . GetCurrentPoint ( this ) . Position ;
104
119
105
- if ( _previousBitmap == null || ActualHeight <= 0 )
120
+ if ( _currentBitmap == null || ActualHeight <= 0 )
106
121
{
107
122
return ;
108
123
}
109
124
110
- int pixelX = ( int ) Math . Floor ( position . X * ( _previousBitmap . Size . Height / ActualHeight ) ) ;
111
- int pixelY = ( int ) Math . Floor ( position . Y * ( _previousBitmap . Size . Width / ActualWidth ) ) ;
125
+ int pixelX = ( int ) Math . Floor ( position . X * ( _currentBitmap . Size . Height / ActualHeight ) ) ;
126
+ int pixelY = ( int ) Math . Floor ( position . Y * ( _currentBitmap . Size . Width / ActualWidth ) ) ;
112
127
113
- if ( pixelX < 0 || pixelX >= _previousBitmap . SizeInPixels . Width || pixelY < 0 || pixelY >= _previousBitmap . SizeInPixels . Height )
128
+ if ( pixelX < 0 || pixelX >= _currentBitmap . SizeInPixels . Width || pixelY < 0 || pixelY >= _currentBitmap . SizeInPixels . Height )
114
129
{
115
130
return ;
116
131
}
117
132
118
- if ( _previousColors == null )
133
+ if ( _currentColors == null )
119
134
{
120
- _previousColors = _previousBitmap . GetPixelColors ( ) ;
135
+ _currentColors = _currentBitmap . GetPixelColors ( ) ;
121
136
}
122
137
123
- _currentColor = _previousColors [ ( pixelY * _previousBitmap . SizeInPixels . Width ) + pixelX ] ;
138
+ _currentColor = _currentColors [ ( pixelY * _currentBitmap . SizeInPixels . Width ) + pixelX ] ;
124
139
SetValue ( CurrentColorStringProperty , _currentColor . ToString ( ) ) ;
125
140
SetValue ( CurrentPositionProperty , new Vector2 ( pixelX , pixelY ) ) ;
126
141
}
127
142
128
143
async Task ShowBitmapOnTargetAsync ( CanvasBitmap bitmap )
129
144
{
130
- int scale = ( int ) Math . Ceiling ( ActualSize . Y / bitmap . Size . Height ) ;
145
+ int scale = Math . Max ( ( int ) Math . Ceiling ( ActualSize . Y / bitmap . Size . Height ) , 1 ) ;
131
146
132
147
Height = bitmap . Size . Height / bitmap . Size . Width * ActualSize . X ;
133
148
134
- _previousBitmap = bitmap ;
135
- _previousColors = null ;
149
+ _currentBitmap ? . Dispose ( ) ;
150
+ _currentBitmap = bitmap ;
151
+ _currentColors = null ;
136
152
137
153
var compositor = ElementCompositionPreview . GetElementVisual ( this ) . Compositor ;
138
- var compositionGraphicsDevice = CanvasComposition . CreateCompositionGraphicsDevice ( compositor , CanvasDevice . GetSharedDevice ( ) ) ;
139
154
140
155
if ( _patternBitmap is null )
141
156
{
142
157
_patternBitmap = await CanvasBitmap . LoadAsync ( CanvasDevice . GetSharedDevice ( ) , @"Assets\BackgroundPattern.png" ) ;
143
158
}
144
159
145
- var surface = compositionGraphicsDevice . CreateDrawingSurface (
146
- new Size ( bitmap . Size . Width * scale , bitmap . Size . Height * scale ) ,
147
- DirectXPixelFormat . B8G8R8A8UIntNormalized ,
148
- DirectXAlphaMode . Premultiplied ) ;
160
+ var size = new Size ( bitmap . Size . Width * scale , bitmap . Size . Height * scale ) ;
161
+
162
+ if ( _swapchain . Size . Width != size . Width || _swapchain . Size . Height != size . Height )
163
+ {
164
+ _swapchain . ResizeBuffers ( size ) ;
165
+ }
149
166
150
- using ( var drawingSession = CanvasComposition . CreateDrawingSession ( surface ) )
167
+ using ( var drawingSession = _swapchain ! . CreateDrawingSession ( Colors . Transparent ) )
151
168
{
152
169
var border = new BorderEffect
153
170
{
@@ -168,19 +185,15 @@ async Task ShowBitmapOnTargetAsync(CanvasBitmap bitmap)
168
185
drawingSession . DrawImage ( scaleEffect ) ;
169
186
}
170
187
171
- var surfaceBrush = compositor . CreateSurfaceBrush ( surface ) ;
172
- _spriteVisual . Brush = surfaceBrush ;
188
+ _swapchain . Present ( ) ;
173
189
}
174
190
175
191
void OnFrameArrived ( Direct3D11CaptureFramePool sender , object args )
176
192
{
177
- if ( Active )
193
+ using ( var frame = sender . TryGetNextFrame ( ) )
178
194
{
179
- using ( var frame = sender . TryGetNextFrame ( ) )
180
- {
181
- CanvasBitmap bitmap = CanvasBitmap . CreateFromDirect3D11Surface ( _canvasDevice ! , frame . Surface ) ;
182
- _ = ShowBitmapOnTargetAsync ( bitmap ) ;
183
- }
195
+ CanvasBitmap bitmap = CanvasBitmap . CreateFromDirect3D11Surface ( _canvasDevice ! , frame . Surface ) ;
196
+ _ = ShowBitmapOnTargetAsync ( bitmap ) ;
184
197
}
185
198
}
186
199
@@ -189,32 +202,12 @@ public void OnResolutionUpdated(int width, int height)
189
202
190
203
public void UpdateResolution ( SizeInt32 size )
191
204
{
192
- if ( size . Height <= 0 || size . Width < = 0 )
205
+ if ( size . Width == 0 || size . Height = = 0 )
193
206
{
194
207
return ;
195
208
}
196
209
197
- if ( _framePool is not null && _session is not null )
198
- {
199
- // Unsubscribe from old framePool
200
- _framePool . FrameArrived -= OnFrameArrived ;
201
-
202
- // Dispose old session and framePool
203
- _session . Dispose ( ) ;
204
- _framePool . Dispose ( ) ;
205
- }
206
-
207
- _canvasDevice = CanvasDevice . GetSharedDevice ( ) ;
208
-
209
- // Create a frame pool with room for only 1 frame because we're getting a single frame, not a video.
210
- _framePool =
211
- Direct3D11CaptureFramePool . Create ( _canvasDevice , DirectXPixelFormat . B8G8R8A8UIntNormalized , 1 , size ) ;
212
-
213
- _session = _framePool . CreateCaptureSession ( GraphicsCaptureItem . CreateFromVisual ( _capturedVisual ) ) ;
214
-
215
- _framePool . FrameArrived += OnFrameArrived ;
216
-
217
- _session . StartCapture ( ) ;
210
+ _framePool . Recreate ( _canvasDevice , DirectXPixelFormat . B8G8R8A8UIntNormalized , 3 , new SizeInt32 { Width = size . Width , Height = size . Height } ) ;
218
211
}
219
212
}
220
213
}
0 commit comments