private void PlatformSetData <T>(int level, Rectangle?rect, T[] data, int startIndex, int elementCount) where T : struct { var elementSizeInByte = Marshal.SizeOf(typeof(T)); var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); // Use try..finally to make sure dataHandle is freed in case of an error try { var startBytes = startIndex * elementSizeInByte; var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes); int x, y, w, h; if (rect.HasValue) { x = rect.Value.X; y = rect.Value.Y; w = rect.Value.Width; h = rect.Value.Height; } else { x = 0; y = 0; w = Math.Max(width >> level, 1); h = Math.Max(height >> level, 1); // For DXT textures the width and height of each level is a multiple of 4. // OpenGL only: The last two mip levels require the width and height to be // passed as 2x2 and 1x1, but there needs to be enough data passed to occupy // a 4x4 block. // Ref: http://www.mentby.com/Group/mac-opengl/issue-with-dxt-mipmapped-textures.html if (_format == SurfaceFormat.Dxt1 || _format == SurfaceFormat.Dxt1a || _format == SurfaceFormat.Dxt3 || _format == SurfaceFormat.Dxt5) { w = (w + 3) & ~3; h = (h + 3) & ~3; } } var box = new SharpDX.DataBox(dataPtr, GetPitch(w), 0); var region = new SharpDX.Direct3D11.ResourceRegion(); region.Top = y; region.Front = 0; region.Back = 1; region.Bottom = y + h; region.Left = x; region.Right = x + w; // TODO: We need to deal with threaded contexts here! var d3dContext = GraphicsDevice._d3dContext; lock (d3dContext) d3dContext.UpdateSubresource(box, GetTexture(), level, region); } finally { dataHandle.Free(); } }
private void PlatformSetDataInternal <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, SetDataOptions options) where T : struct { GenerateIfRequired(); if (_isDynamic) { // We assume discard by default. var mode = SharpDX.Direct3D11.MapMode.WriteDiscard; if ((options & SetDataOptions.NoOverwrite) == SetDataOptions.NoOverwrite) { mode = SharpDX.Direct3D11.MapMode.WriteNoOverwrite; } var d3dContext = GraphicsDevice._d3dContext; lock (d3dContext) { var dataBox = d3dContext.MapSubresource(_buffer, 0, mode, SharpDX.Direct3D11.MapFlags.None); SharpDX.Utilities.Write(IntPtr.Add(dataBox.DataPointer, offsetInBytes), data, startIndex, elementCount); d3dContext.UnmapSubresource(_buffer, 0); } } else { var elementSizeInBytes = ReflectionHelpers.SizeOf <T> .Get(); var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); try { var startBytes = startIndex * elementSizeInBytes; var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes); var box = new SharpDX.DataBox(dataPtr, elementCount * elementSizeInBytes, 0); var region = new SharpDX.Direct3D11.ResourceRegion(); region.Top = 0; region.Front = 0; region.Back = 1; region.Bottom = 1; region.Left = offsetInBytes; region.Right = offsetInBytes + (elementCount * elementSizeInBytes); // TODO: We need to deal with threaded contexts here! var d3dContext = GraphicsDevice._d3dContext; lock (d3dContext) d3dContext.UpdateSubresource(box, _buffer, 0, region); } finally { dataHandle.Free(); } } }
public void CopyFromGpuTexture2D(Point2 destination, GpuTexture2D source, Rectangle region) { if (region.Right - region.Left == 0 || region.Bottom - region.Top == 0) { return; } var resourceRegion = new SharpDX.Direct3D11.ResourceRegion( region.Left, region.Top, 0, region.Right, region.Bottom, 1); GpuDevice.ImmediateContext.CopySubresourceRegion(source.mResource, 0, resourceRegion, mResource, 0, destination.X, destination.Y); }
public byte[] GetPixelBytes(int left, int top, int width, int height) { if (width <= 0 || height <= 0) { return(new byte[] { }); } var device = _texture.Device; var description = new SharpDX.Direct3D11.Texture2DDescription() { Width = width, Height = height, Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm, ArraySize = 1, MipLevels = 1, SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), Usage = SharpDX.Direct3D11.ResourceUsage.Staging, BindFlags = SharpDX.Direct3D11.BindFlags.None, CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.Read, OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None }; byte[] result = new byte[width * height * 4]; using (var staging = new SharpDX.Direct3D11.Texture2D(device, description)) { var textureWidth = _texture.Description.Width; var textureHeight = _texture.Description.Height; var srcX0 = Math.Max(0, left); var srcY0 = Math.Max(0, top); var srcX1 = Math.Min(textureWidth, Math.Max(0, left + width)); var srcY1 = Math.Min(textureHeight, Math.Max(0, top + height)); if (srcX1 <= srcX0 || srcY1 <= srcY0) { return(new byte[] { }); } var region = new SharpDX.Direct3D11.ResourceRegion(srcX0, srcY0, 0, srcX1, srcY1, 1); var dstX0 = Math.Max(0, -left); var dstY0 = Math.Max(0, -top); device.ImmediateContext.CopySubresourceRegion(_texture, 0, region, staging, 0, dstX0, dstY0); var box = device.ImmediateContext.MapSubresource( staging, 0, SharpDX.Direct3D11.MapMode.Read, SharpDX.Direct3D11.MapFlags.None); for (int i = 0; i < height; ++i) { Marshal.Copy(box.DataPointer + i * box.RowPitch, result, i * width * 4, width * 4); } device.ImmediateContext.UnmapSubresource(staging, 0); } return(result); }
private unsafe void PlatformSetData( int byteOffset, ReadOnlySpan <byte> source, SetDataOptions options) { GenerateIfRequired(); if (IsDynamic) { // We assume discard by default. var mode = SharpDX.Direct3D11.MapMode.WriteDiscard; if ((options & SetDataOptions.NoOverwrite) == SetDataOptions.NoOverwrite) { mode = SharpDX.Direct3D11.MapMode.WriteNoOverwrite; } var d3dContext = GraphicsDevice._d3dContext; lock (d3dContext) { var box = d3dContext.MapSubresource(_buffer, 0, mode, SharpDX.Direct3D11.MapFlags.None); int dstBytes = Capacity * ElementType.TypeSize(); var dst = new Span <byte>((void *)(box.DataPointer + byteOffset), dstBytes); source.CopyTo(dst); d3dContext.UnmapSubresource(_buffer, 0); } } else { var region = new SharpDX.Direct3D11.ResourceRegion { Top = 0, Front = 0, Back = 1, Bottom = 1, Left = byteOffset, Right = byteOffset + source.Length }; // TODO: We need to deal with threaded contexts here! var d3dContext = GraphicsDevice._d3dContext; lock (d3dContext) { ref var mutableData = ref MemoryMarshal.GetReference(source); d3dContext.UpdateSubresource(ref mutableData, _buffer, 0, source.Length, 0, region); } }
public SurfaceWithInfo WaitForNewFrame() { // Let's get a fresh one. _currentFrame?.Dispose(); _frameEvent.Reset(); var signaledEvent = _events[WaitHandle.WaitAny(_events)]; if (signaledEvent == _closedEvent) { Cleanup(); return(null); } var result = new SurfaceWithInfo(); //System.Diagnostics.Debug.WriteLine("Using _currentFrame"); result.SystemRelativeTime = _currentFrame.SystemRelativeTime; //System.Diagnostics.Debug.WriteLine("Done using _currentFrame"); //result.Surface = _currentFrame.Surface; return result; using (var multithreadLock = new MultithreadLock(_multithread)) using (var sourceTexture = Direct3D11Helpers.CreateSharpDXTexture2D(_currentFrame.Surface)) { var description = sourceTexture.Description; description.Usage = SharpDX.Direct3D11.ResourceUsage.Default; description.BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource | SharpDX.Direct3D11.BindFlags.RenderTarget; description.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None; description.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None; using (var copyTexture = new SharpDX.Direct3D11.Texture2D(_d3dDevice, description)) { var width = Math.Clamp(_currentFrame.ContentSize.Width, 0, _currentFrame.Surface.Description.Width); var height = Math.Clamp(_currentFrame.ContentSize.Height, 0, _currentFrame.Surface.Description.Height); var region = new SharpDX.Direct3D11.ResourceRegion(0, 0, 0, width, height, 1); _d3dDevice.ImmediateContext.CopyResource(_blankTexture, copyTexture); _d3dDevice.ImmediateContext.CopySubresourceRegion(sourceTexture, 0, region, copyTexture, 0); result.Surface = Direct3D11Helpers.CreateDirect3DSurfaceFromSharpDXTexture(copyTexture); } } return(result); }
public void CopyRegion(GraphicsResource source, int sourceSubresource, ResourceRegion?sourecRegion, GraphicsResource destination, int destinationSubResource, int dstX = 0, int dstY = 0, int dstZ = 0) { if (source == null) { throw new ArgumentNullException("source"); } if (destination == null) { throw new ArgumentNullException("destination"); } var nullableSharpDxRegion = new SharpDX.Direct3D11.ResourceRegion?(); if (sourecRegion.HasValue) { var value = sourecRegion.Value; nullableSharpDxRegion = new SharpDX.Direct3D11.ResourceRegion(value.Left, value.Top, value.Front, value.Right, value.Bottom, value.Back); } NativeDeviceContext.CopySubresourceRegion(source.NativeResource, sourceSubresource, nullableSharpDxRegion, destination.NativeResource, destinationSubResource, dstX, dstY, dstZ); }
public SurfaceWithInfo WaitForNewFrame() { // Let's get a fresh one. this.currentFrame?.Dispose(); this.frameEvent.Reset(); var signaledEvent = this.events[WaitHandle.WaitAny(this.events)]; if (signaledEvent == this.closedEvent) { this.CleanupItem(); return(null); } using var multithreadLock = new MultithreadLock(this.multithread); using var sourceTexture = Direct3D11Helper.CreateSharpDXTexture2D(this.currentFrame.Surface); var description = sourceTexture.Description; description.Usage = SharpDX.Direct3D11.ResourceUsage.Default; description.BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource | SharpDX.Direct3D11.BindFlags.RenderTarget; description.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None; description.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None; using var copyTexture = new SharpDX.Direct3D11.Texture2D(this.d3dDevice, description); var width = Math.Clamp(this.currentFrame.ContentSize.Width, 0, this.currentFrame.Surface.Description.Width); var height = Math.Clamp(this.currentFrame.ContentSize.Height, 0, this.currentFrame.Surface.Description.Height); var region = new SharpDX.Direct3D11.ResourceRegion(0, 0, 0, width, height, 1); this.d3dDevice.ImmediateContext.CopyResource(blankTexture, copyTexture); this.d3dDevice.ImmediateContext.CopySubresourceRegion(sourceTexture, 0, region, copyTexture, 0); var result = new SurfaceWithInfo { SystemRelativeTime = this.currentFrame.SystemRelativeTime, Surface = Direct3D11Helper.CreateDirect3DSurfaceFromSharpDXTexture(copyTexture) }; return(result); }
public void CopyRegion(GraphicsResource source, int sourceSubresource, ResourceRegion? sourecRegion, GraphicsResource destination, int destinationSubResource, int dstX = 0, int dstY = 0, int dstZ = 0) { if (source == null) throw new ArgumentNullException("source"); if (destination == null) throw new ArgumentNullException("destination"); var nullableSharpDxRegion = new SharpDX.Direct3D11.ResourceRegion?(); if (sourecRegion.HasValue) { var value = sourecRegion.Value; nullableSharpDxRegion = new SharpDX.Direct3D11.ResourceRegion(value.Left, value.Top, value.Front, value.Right, value.Bottom, value.Back); } NativeDeviceContext.CopySubresourceRegion(source.NativeResource, sourceSubresource, nullableSharpDxRegion, destination.NativeResource, destinationSubResource, dstX, dstY, dstZ); }
protected void SetData <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride, SetDataOptions options) where T : struct { if (data == null) { throw new ArgumentNullException("data is null"); } if (data.Length < (startIndex + elementCount)) { throw new InvalidOperationException("The array specified in the data parameter is not the correct size for the amount of data requested."); } var bufferSize = VertexCount * VertexDeclaration.VertexStride; if ((vertexStride > bufferSize) || (vertexStride < VertexDeclaration.VertexStride)) { throw new ArgumentOutOfRangeException("One of the following conditions is true:\nThe vertex stride is larger than the vertex buffer.\nThe vertex stride is too small for the type of data requested."); } #if !PSS var elementSizeInBytes = Marshal.SizeOf(typeof(T)); #endif #if DIRECTX if (_isDynamic) { // We assume discard by default. var mode = SharpDX.Direct3D11.MapMode.WriteDiscard; if ((options & SetDataOptions.NoOverwrite) == SetDataOptions.NoOverwrite) { mode = SharpDX.Direct3D11.MapMode.WriteNoOverwrite; } SharpDX.DataStream stream; lock (graphicsDevice._d3dContext) { graphicsDevice._d3dContext.MapSubresource( _buffer, mode, SharpDX.Direct3D11.MapFlags.None, out stream); stream.Position = offsetInBytes; stream.WriteRange(data, startIndex, elementCount); graphicsDevice._d3dContext.UnmapSubresource(_buffer, 0); } } else { var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); var startBytes = startIndex * elementSizeInBytes; var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes); var box = new SharpDX.DataBox(dataPtr, 1, 0); var region = new SharpDX.Direct3D11.ResourceRegion(); region.Top = 0; region.Front = 0; region.Back = 1; region.Bottom = 1; region.Left = offsetInBytes; region.Right = offsetInBytes + (elementCount * elementSizeInBytes); lock (graphicsDevice._d3dContext) graphicsDevice._d3dContext.UpdateSubresource(box, _buffer, 0, region); dataHandle.Free(); } #elif PSS if (_vertexArray == null) { _vertexArray = new T[VertexCount]; } Array.Copy(data, offsetInBytes / vertexStride, _vertexArray, startIndex, elementCount); #else Threading.BlockOnUIThread(() => { var sizeInBytes = elementSizeInBytes * elementCount; GL.BindBuffer(BufferTarget.ArrayBuffer, vbo); GraphicsExtensions.CheckGLError(); if (options == SetDataOptions.Discard) { // By assigning NULL data to the buffer this gives a hint // to the device to discard the previous content. GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)bufferSize, IntPtr.Zero, _isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw); GraphicsExtensions.CheckGLError(); } GL.BufferSubData(BufferTarget.ArrayBuffer, (IntPtr)offsetInBytes, (IntPtr)sizeInBytes, data); GraphicsExtensions.CheckGLError(); }); #endif }
private void PlatformSetDataInternal <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride, SetDataOptions options, int bufferSize, int elementSizeInBytes) where T : struct { GenerateIfRequired(); if (_isDynamic) { // We assume discard by default. var mode = SharpDX.Direct3D11.MapMode.WriteDiscard; if ((options & SetDataOptions.NoOverwrite) == SetDataOptions.NoOverwrite) { mode = SharpDX.Direct3D11.MapMode.WriteNoOverwrite; } var d3dContext = GraphicsDevice._d3dContext; lock (d3dContext) { var dataBox = d3dContext.MapSubresource(_buffer, 0, mode, SharpDX.Direct3D11.MapFlags.None); if (vertexStride == elementSizeInBytes) { SharpDX.Utilities.Write(dataBox.DataPointer + offsetInBytes, data, startIndex, elementCount); } else { for (int i = 0; i < elementCount; i++) { SharpDX.Utilities.Write(dataBox.DataPointer + offsetInBytes + i * vertexStride, data, startIndex + i, 1); } } d3dContext.UnmapSubresource(_buffer, 0); } } else { var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); try { var startBytes = startIndex * elementSizeInBytes; var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes); var d3dContext = GraphicsDevice._d3dContext; if (vertexStride == elementSizeInBytes) { var box = new SharpDX.DataBox(dataPtr, elementCount * elementSizeInBytes, 0); var region = new SharpDX.Direct3D11.ResourceRegion(); region.Top = 0; region.Front = 0; region.Back = 1; region.Bottom = 1; region.Left = offsetInBytes; region.Right = offsetInBytes + (elementCount * elementSizeInBytes); lock (d3dContext) d3dContext.UpdateSubresource(box, _buffer, 0, region); } else { // Copy the buffer to a staging resource, so that any elements we don't write to will still be correct. var stagingDesc = _buffer.Description; stagingDesc.BindFlags = SharpDX.Direct3D11.BindFlags.None; stagingDesc.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.Read | SharpDX.Direct3D11.CpuAccessFlags.Write; stagingDesc.Usage = SharpDX.Direct3D11.ResourceUsage.Staging; stagingDesc.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None; using (var stagingBuffer = new SharpDX.Direct3D11.Buffer(GraphicsDevice._d3dDevice, stagingDesc)) { lock (d3dContext) { d3dContext.CopyResource(_buffer, stagingBuffer); // Map the staging resource to a CPU accessible memory var box = d3dContext.MapSubresource(stagingBuffer, 0, SharpDX.Direct3D11.MapMode.Read, SharpDX.Direct3D11.MapFlags.None); for (int i = 0; i < elementCount; i++) { SharpDX.Utilities.CopyMemory( box.DataPointer + i * vertexStride + offsetInBytes, dataPtr + i * elementSizeInBytes, elementSizeInBytes); } // Make sure that we unmap the resource in case of an exception d3dContext.UnmapSubresource(stagingBuffer, 0); // Copy back from staging resource to real buffer. d3dContext.CopyResource(stagingBuffer, _buffer); } } } } finally { dataHandle.Free(); } } }
public void SetData<T>(int level, Rectangle? rect, T[] data, int startIndex, int elementCount) where T : struct { if (data == null) throw new ArgumentNullException("data"); #if OPENGL Threading.BlockOnUIThread(() => { #endif #if !PSM var elementSizeInByte = Marshal.SizeOf(typeof(T)); var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); // Use try..finally to make sure dataHandle is freed in case of an error try { var startBytes = startIndex * elementSizeInByte; var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes); #endif int x, y, w, h; if (rect.HasValue) { x = rect.Value.X; y = rect.Value.Y; w = rect.Value.Width; h = rect.Value.Height; } else { x = 0; y = 0; w = Math.Max(width >> level, 1); h = Math.Max(height >> level, 1); // For DXT textures the width and height of each level is a multiple of 4. // OpenGL only: The last two mip levels require the width and height to be // passed as 2x2 and 1x1, but there needs to be enough data passed to occupy // a 4x4 block. // Ref: http://www.mentby.com/Group/mac-opengl/issue-with-dxt-mipmapped-textures.html if (_format == SurfaceFormat.Dxt1 || _format == SurfaceFormat.Dxt1a || _format == SurfaceFormat.Dxt3 || _format == SurfaceFormat.Dxt5) { #if DIRECTX w = (w + 3) & ~3; h = (h + 3) & ~3; #else if (w > 4) w = (w + 3) & ~3; if (h > 4) h = (h + 3) & ~3; #endif } } #if DIRECTX var box = new SharpDX.DataBox(dataPtr, GetPitch(w), 0); var region = new SharpDX.Direct3D11.ResourceRegion(); region.Top = y; region.Front = 0; region.Back = 1; region.Bottom = y + h; region.Left = x; region.Right = x + w; // TODO: We need to deal with threaded contexts here! var d3dContext = GraphicsDevice._d3dContext; lock (d3dContext) d3dContext.UpdateSubresource(box, GetTexture(), level, region); #elif PSM _texture2D.SetPixels(level, data, _texture2D.Format, startIndex, 0, x, y, w, h); #elif OPENGL // Store the current bound texture. var prevTexture = GraphicsExtensions.GetBoundTexture2D(); GenerateGLTextureIfRequired(); GL.BindTexture(TextureTarget.Texture2D, this.glTexture); GraphicsExtensions.CheckGLError(); if (glFormat == (GLPixelFormat)All.CompressedTextureFormats) { if (rect.HasValue) { GL.CompressedTexSubImage2D(TextureTarget.Texture2D, level, x, y, w, h, #if GLES glInternalFormat, #else glFormat, #endif data.Length - startBytes, dataPtr); GraphicsExtensions.CheckGLError(); } else { GL.CompressedTexImage2D(TextureTarget.Texture2D, level, glInternalFormat, w, h, 0, data.Length - startBytes, dataPtr); GraphicsExtensions.CheckGLError(); } } else { // Set pixel alignment to match texel size in bytes GL.PixelStore(PixelStoreParameter.UnpackAlignment, GraphicsExtensions.Size(this.Format)); if (rect.HasValue) { GL.TexSubImage2D(TextureTarget.Texture2D, level, x, y, w, h, glFormat, glType, dataPtr); GraphicsExtensions.CheckGLError(); } else { GL.TexImage2D(TextureTarget.Texture2D, level, #if GLES (int)glInternalFormat, #else glInternalFormat, #endif w, h, 0, glFormat, glType, dataPtr); GraphicsExtensions.CheckGLError(); } // Return to default pixel alignment GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4); } #if !ANDROID GL.Finish(); GraphicsExtensions.CheckGLError(); #endif // Restore the bound texture. GL.BindTexture(TextureTarget.Texture2D, prevTexture); GraphicsExtensions.CheckGLError(); #endif // OPENGL #if !PSM } finally { dataHandle.Free(); } #endif #if OPENGL #if !ANDROID // Required to make sure that any texture uploads on a thread are completed // before the main thread tries to use the texture. GL.Finish(); #endif }); #endif }
public void SetData<T>(int level, Rectangle? rect, T[] data, int startIndex, int elementCount) where T : struct { if (data == null) throw new ArgumentNullException("data"); #if OPENGL Threading.BlockOnUIThread(() => { #endif #if !PSM var elementSizeInByte = Marshal.SizeOf(typeof(T)); var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); var startBytes = startIndex * elementSizeInByte; var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes); #endif int x, y, w, h; if (rect.HasValue) { x = rect.Value.X; y = rect.Value.Y; w = rect.Value.Width; h = rect.Value.Height; } else { x = 0; y = 0; w = Math.Max(width >> level, 1); h = Math.Max(height >> level, 1); } #if DIRECTX var box = new SharpDX.DataBox(dataPtr, GetPitch(w), 0); var region = new SharpDX.Direct3D11.ResourceRegion(); region.Top = y; region.Front = 0; region.Back = 1; region.Bottom = y + h; region.Left = x; region.Right = x + w; // TODO: We need to deal with threaded contexts here! var d3dContext = GraphicsDevice._d3dContext; lock (d3dContext) d3dContext.UpdateSubresource(box, _texture, level, region); #elif PSM _texture2D.SetPixels(level, data, _texture2D.Format, startIndex, 0, x, y, w, h); #elif OPENGL // Store the current bound texture. var prevTexture = GraphicsExtensions.GetBoundTexture2D(); GenerateGLTextureIfRequired(); GL.BindTexture(TextureTarget.Texture2D, this.glTexture); GraphicsExtensions.CheckGLError(); if (glFormat == (GLPixelFormat)All.CompressedTextureFormats) { if (rect.HasValue) { GL.CompressedTexSubImage2D(TextureTarget.Texture2D, level, x, y, w, h, #if GLES glInternalFormat, #else glFormat, #endif data.Length - startBytes, dataPtr); GraphicsExtensions.CheckGLError(); } else { GL.CompressedTexImage2D(TextureTarget.Texture2D, level, glInternalFormat, w, h, 0, data.Length - startBytes, dataPtr); GraphicsExtensions.CheckGLError(); } } else { // Set pixel alignment to match texel size in bytes GL.PixelStore(PixelStoreParameter.UnpackAlignment, GraphicsExtensions.Size(this.Format)); if (rect.HasValue) { GL.TexSubImage2D(TextureTarget.Texture2D, level, x, y, w, h, glFormat, glType, dataPtr); GraphicsExtensions.CheckGLError(); } else { GL.TexImage2D(TextureTarget.Texture2D, level, #if GLES (int)glInternalFormat, #else glInternalFormat, #endif w, h, 0, glFormat, glType, dataPtr); GraphicsExtensions.CheckGLError(); } // Return to default pixel alignment GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4); } #if !ANDROID GL.Finish(); GraphicsExtensions.CheckGLError(); #endif // Restore the bound texture. GL.BindTexture(TextureTarget.Texture2D, prevTexture); GraphicsExtensions.CheckGLError(); #endif // OPENGL #if !PSM dataHandle.Free(); #endif #if OPENGL #if !ANDROID // Required to make sure that any texture uploads on a thread are completed // before the main thread tries to use the texture. GL.Finish(); #endif }); #endif }
protected void SetDataInternal <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, SetDataOptions options) where T : struct { if (data == null) { throw new ArgumentNullException("data is null"); } if (data.Length < (startIndex + elementCount)) { throw new InvalidOperationException("The array specified in the data parameter is not the correct size for the amount of data requested."); } #if DIRECTX if (_isDynamic) { // We assume discard by default. var mode = SharpDX.Direct3D11.MapMode.WriteDiscard; if ((options & SetDataOptions.NoOverwrite) == SetDataOptions.NoOverwrite) { mode = SharpDX.Direct3D11.MapMode.WriteNoOverwrite; } SharpDX.DataStream stream; lock (graphicsDevice._d3dContext) { graphicsDevice._d3dContext.MapSubresource( _buffer, mode, SharpDX.Direct3D11.MapFlags.None, out stream); stream.Position = offsetInBytes; stream.WriteRange(data, startIndex, elementCount); graphicsDevice._d3dContext.UnmapSubresource(_buffer, 0); } } else { var elementSizeInBytes = Marshal.SizeOf(typeof(T)); var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); var startBytes = startIndex * elementSizeInBytes; var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes); var box = new SharpDX.DataBox(dataPtr, 1, 0); var region = new SharpDX.Direct3D11.ResourceRegion(); region.Top = 0; region.Front = 0; region.Back = 1; region.Bottom = 1; region.Left = offsetInBytes; region.Right = offsetInBytes + (elementCount * elementSizeInBytes); // TODO: We need to deal with threaded contexts here! lock (graphicsDevice._d3dContext) graphicsDevice._d3dContext.UpdateSubresource(box, _buffer, 0, region); dataHandle.Free(); } #elif PSS if (typeof(T) == typeof(ushort)) { Array.Copy(data, offsetInBytes / sizeof(ushort), _buffer, startIndex, elementCount); } else { throw new NotImplementedException("PSS Currently only supports ushort (SixteenBits) index elements"); //Something like as follows probably works if you really need this, but really just make a ushort array! /* * int indexOffset = offsetInBytes / sizeof(T); * for (int i = 0; i < elementCount; i++) * _buffer[i + startIndex] = (ushort)(object)data[i + indexOffset]; */ } #else Threading.BlockOnUIThread(() => { var elementSizeInByte = Marshal.SizeOf(typeof(T)); var sizeInBytes = elementSizeInByte * elementCount; var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startIndex * elementSizeInByte); var bufferSize = IndexCount * (IndexElementSize == IndexElementSize.SixteenBits ? 2 : 4); GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo); GraphicsExtensions.CheckGLError(); if (options == SetDataOptions.Discard) { // By assigning NULL data to the buffer this gives a hint // to the device to discard the previous content. GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)bufferSize, IntPtr.Zero, _isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw); GraphicsExtensions.CheckGLError(); } GL.BufferSubData(BufferTarget.ElementArrayBuffer, (IntPtr)offsetInBytes, (IntPtr)sizeInBytes, dataPtr); GraphicsExtensions.CheckGLError(); dataHandle.Free(); }); #endif }
private async void MainToggleButton_Checked(object sender, RoutedEventArgs e) { // Select what we want to capture var picker = new GraphicsCapturePicker(); var item = await picker.PickSingleItemAsync(); if (item != null) { // Get a temporary file to save our gif to var file = await GetTempFileAsync(); using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite)) { // Get the various d3d objects we'll need var d3dDevice = Direct3D11Helpers.CreateSharpDXDevice(_device); // Create our encoder var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.GifEncoderId, stream); // Write the application block // http://www.vurdalakov.net/misc/gif/netscape-looping-application-extension var containerProperties = encoder.BitmapContainerProperties; await containerProperties.SetPropertiesAsync(new[] { new KeyValuePair <string, BitmapTypedValue>("/appext/application", new BitmapTypedValue(PropertyValue.CreateUInt8Array(Encoding.ASCII.GetBytes("NETSCAPE2.0")), PropertyType.UInt8Array)), // The first value is the size of the block, which is the fixed value 3. // The second value is the looping extension, which is the fixed value 1. // The third and fourth values comprise an unsigned 2-byte integer (little endian). // The value of 0 means to loop infinitely. // The final value is the block terminator, which is the fixed value 0. new KeyValuePair <string, BitmapTypedValue>("/appext/data", new BitmapTypedValue(PropertyValue.CreateUInt8Array(new byte[] { 3, 1, 0, 0, 0 }), PropertyType.UInt8Array)), }); // Setup Windows.Graphics.Capture var itemSize = item.Size; var framePool = Direct3D11CaptureFramePool.CreateFreeThreaded( _device, DirectXPixelFormat.B8G8R8A8UIntNormalized, 1, itemSize); var session = framePool.CreateCaptureSession(item); // We need a blank texture (background) and a texture that will hold the frame we'll be encoding var description = new SharpDX.Direct3D11.Texture2DDescription { Width = itemSize.Width, Height = itemSize.Height, MipLevels = 1, ArraySize = 1, Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm, SampleDescription = new SharpDX.DXGI.SampleDescription() { Count = 1, Quality = 0 }, Usage = SharpDX.Direct3D11.ResourceUsage.Default, BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource | SharpDX.Direct3D11.BindFlags.RenderTarget, CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None, OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None }; var gifTexture = new SharpDX.Direct3D11.Texture2D(d3dDevice, description); var renderTargetView = new SharpDX.Direct3D11.RenderTargetView(d3dDevice, gifTexture); // Encode frames as they arrive. Because we created our frame pool using // Direct3D11CaptureFramePool::CreateFreeThreaded, this lambda will fire on a different thread // than our current one. If you'd like the callback to fire on your thread, create the frame pool // using Direct3D11CaptureFramePool::Create and make sure your thread has a DispatcherQueue and you // are pumping messages. TimeSpan lastTimeStamp = TimeSpan.MinValue; var frameCount = 0; framePool.FrameArrived += async(s, a) => { using (var frame = s.TryGetNextFrame()) { var contentSize = frame.ContentSize; var timeStamp = frame.SystemRelativeTime; using (var sourceTexture = Direct3D11Helpers.CreateSharpDXTexture2D(frame.Surface)) { var width = Math.Clamp(contentSize.Width, 0, itemSize.Width); var height = Math.Clamp(contentSize.Height, 0, itemSize.Height); var region = new SharpDX.Direct3D11.ResourceRegion(0, 0, 0, width, height, 1); d3dDevice.ImmediateContext.ClearRenderTargetView(renderTargetView, new SharpDX.Mathematics.Interop.RawColor4(0, 0, 0, 1)); d3dDevice.ImmediateContext.CopySubresourceRegion(sourceTexture, 0, region, gifTexture, 0); } if (lastTimeStamp == TimeSpan.MinValue) { lastTimeStamp = timeStamp; } var timeStampDelta = timeStamp - lastTimeStamp; lastTimeStamp = timeStamp; var milliseconds = timeStampDelta.TotalMilliseconds; // Use 10ms units var frameDelay = milliseconds / 10; if (frameCount > 0) { await encoder.GoToNextFrameAsync(); } // Write our frame delay await encoder.BitmapProperties.SetPropertiesAsync(new[] { new KeyValuePair <string, BitmapTypedValue>("/grctlext/Delay", new BitmapTypedValue(PropertyValue.CreateUInt16((ushort)frameDelay), PropertyType.UInt16)), }); // Write the frame to our image var gifSurface = Direct3D11Helpers.CreateDirect3DSurfaceFromSharpDXTexture(gifTexture); var copy = await SoftwareBitmap.CreateCopyFromSurfaceAsync(gifSurface); encoder.SetSoftwareBitmap(copy); frameCount++; } }; session.StartCapture(); await _semaphore.WaitAsync(); session.Dispose(); framePool.Dispose(); await Task.Delay(1000); await encoder.FlushAsync(); var newFile = await PickGifAsync(); if (newFile == null) { await file.DeleteAsync(); return; } await file.MoveAndReplaceAsync(newFile); await Launcher.LaunchFileAsync(newFile); } } }
protected void SetDataInternal <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, SetDataOptions options) where T : struct { if (data == null) { throw new ArgumentNullException("data is null"); } if (data.Length < (startIndex + elementCount)) { throw new InvalidOperationException("The array specified in the data parameter is not the correct size for the amount of data requested."); } #if !PORTABLE #if DIRECTX GenerateIfRequired(); if (_isDynamic) { // We assume discard by default. var mode = SharpDX.Direct3D11.MapMode.WriteDiscard; if ((options & SetDataOptions.NoOverwrite) == SetDataOptions.NoOverwrite) { mode = SharpDX.Direct3D11.MapMode.WriteNoOverwrite; } var d3dContext = GraphicsDevice._d3dContext; lock (d3dContext) { var dataBox = d3dContext.MapSubresource(_buffer, 0, mode, SharpDX.Direct3D11.MapFlags.None); SharpDX.Utilities.Write(IntPtr.Add(dataBox.DataPointer, offsetInBytes), data, startIndex, elementCount); d3dContext.UnmapSubresource(_buffer, 0); } } else { var elementSizeInBytes = Marshal.SizeOf(typeof(T)); var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); var startBytes = startIndex * elementSizeInBytes; var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes); var box = new SharpDX.DataBox(dataPtr, 1, 0); var region = new SharpDX.Direct3D11.ResourceRegion(); region.Top = 0; region.Front = 0; region.Back = 1; region.Bottom = 1; region.Left = offsetInBytes; region.Right = offsetInBytes + (elementCount * elementSizeInBytes); // TODO: We need to deal with threaded contexts here! var d3dContext = GraphicsDevice._d3dContext; lock (d3dContext) d3dContext.UpdateSubresource(box, _buffer, 0, region); dataHandle.Free(); } #elif PSM if (typeof(T) == typeof(ushort)) { Array.Copy(data, offsetInBytes / sizeof(ushort), _buffer, startIndex, elementCount); } else { throw new NotImplementedException("PSS Currently only supports ushort (SixteenBits) index elements"); //Something like as follows probably works if you really need this, but really just make a ushort array! /* * int indexOffset = offsetInBytes / sizeof(T); * for (int i = 0; i < elementCount; i++) * _buffer[i + startIndex] = (ushort)(object)data[i + indexOffset]; */ } #else if (Threading.IsOnUIThread()) { BufferData(offsetInBytes, data, startIndex, elementCount, options); } else { Threading.BlockOnUIThread(() => BufferData(offsetInBytes, data, startIndex, elementCount, options)); } #endif #endif }
protected void SetDataInternal <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride, SetDataOptions options) where T : struct { if (data == null) { throw new ArgumentNullException("data is null"); } if (data.Length < (startIndex + elementCount)) { throw new InvalidOperationException("The array specified in the data parameter is not the correct size for the amount of data requested."); } var bufferSize = VertexCount * VertexDeclaration.VertexStride; if ((vertexStride > bufferSize) || (vertexStride < VertexDeclaration.VertexStride)) { throw new ArgumentOutOfRangeException("One of the following conditions is true:\nThe vertex stride is larger than the vertex buffer.\nThe vertex stride is too small for the type of data requested."); } #if !PSM var elementSizeInBytes = Marshal.SizeOf(typeof(T)); #endif #if DIRECTX GenerateIfRequired(); if (_isDynamic) { // We assume discard by default. var mode = SharpDX.Direct3D11.MapMode.WriteDiscard; if ((options & SetDataOptions.NoOverwrite) == SetDataOptions.NoOverwrite) { mode = SharpDX.Direct3D11.MapMode.WriteNoOverwrite; } var d3dContext = GraphicsDevice._d3dContext; lock (d3dContext) { var dataBox = d3dContext.MapSubresource(_buffer, 0, mode, SharpDX.Direct3D11.MapFlags.None); SharpDX.Utilities.Write(IntPtr.Add(dataBox.DataPointer, offsetInBytes), data, startIndex, elementCount); d3dContext.UnmapSubresource(_buffer, 0); } } else { var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); var startBytes = startIndex * elementSizeInBytes; var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes); var box = new SharpDX.DataBox(dataPtr, 1, 0); var region = new SharpDX.Direct3D11.ResourceRegion(); region.Top = 0; region.Front = 0; region.Back = 1; region.Bottom = 1; region.Left = offsetInBytes; region.Right = offsetInBytes + (elementCount * elementSizeInBytes); lock (GraphicsDevice._d3dContext) GraphicsDevice._d3dContext.UpdateSubresource(box, _buffer, 0, region); dataHandle.Free(); } #elif PSM if (_vertexArray == null) { _vertexArray = new T[VertexCount]; } Array.Copy(data, offsetInBytes / vertexStride, _vertexArray, startIndex, elementCount); #else if (Threading.IsOnUIThread()) { SetBufferData(bufferSize, elementSizeInBytes, offsetInBytes, data, startIndex, elementCount, vertexStride, options); } else { Threading.BlockOnUIThread(() => SetBufferData(bufferSize, elementSizeInBytes, offsetInBytes, data, startIndex, elementCount, vertexStride, options)); } #endif }