internal override SharpDX.Direct3D11.Resource CreateTexture() { var description = new Texture2DDescription { Width = size, Height = size, MipLevels = _levelCount, ArraySize = 6, // A texture cube is a 2D texture array with 6 textures. Format = SharpDXHelper.ToFormat(_format), BindFlags = BindFlags.ShaderResource, CpuAccessFlags = CpuAccessFlags.None, SampleDescription = { Count = 1, Quality = 0 }, Usage = ResourceUsage.Default, OptionFlags = ResourceOptionFlags.TextureCube }; if (_renderTarget) { description.BindFlags |= BindFlags.RenderTarget; if (_mipMap) { description.OptionFlags |= ResourceOptionFlags.GenerateMipMaps; } } return(new SharpDX.Direct3D11.Texture2D(GraphicsDevice._d3dDevice, description)); }
private void PlatformGetData <T>(int level, int left, int top, int right, int bottom, int front, int back, T[] data, int startIndex, int elementCount) where T : struct { // Create a temp staging resource for copying the data. // // TODO: Like in Texture2D, we should probably be pooling these staging resources // and not creating a new one each time. // var desc = new Texture3DDescription { Width = _width, Height = _height, Depth = _depth, MipLevels = 1, Format = SharpDXHelper.ToFormat(_format), BindFlags = BindFlags.None, CpuAccessFlags = CpuAccessFlags.Read, Usage = ResourceUsage.Staging, OptionFlags = ResourceOptionFlags.None, }; var d3dContext = GraphicsDevice._d3dContext; using (var stagingTex = new SharpDX.Direct3D11.Texture3D(GraphicsDevice._d3dDevice, desc)) { lock (d3dContext) { // Copy the data from the GPU to the staging texture. d3dContext.CopySubresourceRegion(GetTexture(), level, new ResourceRegion(left, top, front, right, bottom, back), stagingTex, 0); // Copy the data to the array. DataStream stream = null; try { var databox = d3dContext.MapSubresource(stagingTex, 0, MapMode.Read, MapFlags.None, out stream); // Some drivers may add pitch to rows or slices. // We need to copy each row separatly and skip trailing zeros. var currentIndex = startIndex; var elementSize = _format.GetSize(); var elementsInRow = right - left; var rowsInSlice = bottom - top; for (var slice = front; slice < back; slice++) { for (var row = top; row < bottom; row++) { stream.ReadRange(data, currentIndex, elementsInRow); stream.Seek(databox.RowPitch - (elementSize * elementsInRow), SeekOrigin.Current); currentIndex += elementsInRow; } stream.Seek(databox.SlicePitch - (databox.RowPitch * rowsInSlice), SeekOrigin.Current); } } finally { SharpDX.Utilities.Dispose(ref stream); } } } }
internal override SharpDX.Direct3D11.Resource CreateTexture() { var description = new Texture3DDescription { Width = width, Height = height, Depth = depth, MipLevels = _levelCount, Format = SharpDXHelper.ToFormat(_format), BindFlags = BindFlags.ShaderResource, CpuAccessFlags = CpuAccessFlags.None, Usage = ResourceUsage.Default, OptionFlags = ResourceOptionFlags.None, }; if (renderTarget) { description.BindFlags |= BindFlags.RenderTarget; if (mipMap) { // Note: XNA 4 does not have a method Texture.GenerateMipMaps() // because generation of mipmaps is not supported on the Xbox 360. // TODO: New method Texture.GenerateMipMaps() required. description.OptionFlags |= ResourceOptionFlags.GenerateMipMaps; } } return(new SharpDX.Direct3D11.Texture3D(GraphicsDevice._d3dDevice, description)); }
protected internal virtual Texture2DDescription GetTexture2DDescription() { var desc = new Texture2DDescription(); desc.Width = width; desc.Height = height; desc.MipLevels = _levelCount; desc.ArraySize = ArraySize; desc.Format = SharpDXHelper.ToFormat(_format); desc.BindFlags = BindFlags.ShaderResource; desc.CpuAccessFlags = CpuAccessFlags.None; desc.SampleDescription = CreateSampleDescription(); desc.Usage = ResourceUsage.Default; desc.OptionFlags = ResourceOptionFlags.None; if (_shared) { desc.OptionFlags |= ResourceOptionFlags.Shared; } if (_mipmap) { desc.OptionFlags |= ResourceOptionFlags.GenerateMipMaps; desc.BindFlags |= BindFlags.RenderTarget; } return(desc); }
private void PlatformConstruct(GraphicsDevice graphicsDevice, int width, int height, bool mipMap, DepthFormat preferredDepthFormat, int preferredMultiSampleCount, RenderTargetUsage usage) { // Setup the multisampling description. var multisampleDesc = new SharpDX.DXGI.SampleDescription(1, 0); if (preferredMultiSampleCount > 1) { multisampleDesc.Count = preferredMultiSampleCount; multisampleDesc.Quality = (int)StandardMultisampleQualityLevels.StandardMultisamplePattern; } // Create a descriptor for the depth/stencil buffer. // Allocate a 2-D surface as the depth/stencil buffer. // Create a DepthStencil view on this surface to use on bind. using (var depthBuffer = new SharpDX.Direct3D11.Texture2D(graphicsDevice._d3dDevice, new Texture2DDescription { Format = SharpDXHelper.ToFormat(preferredDepthFormat), ArraySize = 1, MipLevels = 1, Width = width, Height = height, SampleDescription = multisampleDesc, BindFlags = BindFlags.DepthStencil, })) { // Create the view for binding to the device. _depthStencilView = new DepthStencilView(graphicsDevice._d3dDevice, depthBuffer, new DepthStencilViewDescription() { Format = SharpDXHelper.ToFormat(preferredDepthFormat), Dimension = DepthStencilViewDimension.Texture2D }); } }
private void PlatformConstruct(GraphicsDevice graphicsDevice, int width, int height, bool mipMap, DepthFormat preferredDepthFormat, int preferredMultiSampleCount, RenderTargetUsage usage, bool shared) { _msSampleDescription = GraphicsDevice.GetSupportedSampleDescription(SharpDXHelper.ToFormat(this.Format), this.MultiSampleCount); GenerateIfRequired(); }
internal override SharpDX.Direct3D11.Resource CreateTexture() { // TODO: Move this to SetData() if we want to make Immutable textures! var desc = new SharpDX.Direct3D11.Texture2DDescription(); desc.Width = width; desc.Height = height; desc.MipLevels = _levelCount; desc.ArraySize = 1; desc.Format = SharpDXHelper.ToFormat(_format); desc.BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource; desc.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None; desc.SampleDescription.Count = 1; desc.SampleDescription.Quality = 0; desc.Usage = SharpDX.Direct3D11.ResourceUsage.Default; desc.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None; if (_renderTarget) { desc.BindFlags |= SharpDX.Direct3D11.BindFlags.RenderTarget; if (_mipmap) { // Note: XNA 4 does not have a method Texture.GenerateMipMaps() // because generation of mipmaps is not supported on the Xbox 360. // TODO: New method Texture.GenerateMipMaps() required. desc.OptionFlags |= SharpDX.Direct3D11.ResourceOptionFlags.GenerateMipMaps; } } if (_shared) desc.OptionFlags |= SharpDX.Direct3D11.ResourceOptionFlags.Shared; return new SharpDX.Direct3D11.Texture2D(GraphicsDevice._d3dDevice, desc); }
private void PlatformConstruct(GraphicsDevice graphicsDevice, bool mipMap, SurfaceFormat preferredFormat, DepthFormat preferredDepthFormat, int preferredMultiSampleCount, RenderTargetUsage usage) { // Create one render target view per cube map face. _renderTargetViews = new RenderTargetView[6]; for (int i = 0; i < _renderTargetViews.Length; i++) { var renderTargetViewDescription = new RenderTargetViewDescription { Dimension = RenderTargetViewDimension.Texture2DArray, Format = SharpDXHelper.ToFormat(preferredFormat), Texture2DArray = { ArraySize = 1, FirstArraySlice = i, MipSlice = 0 } }; _renderTargetViews[i] = new RenderTargetView(graphicsDevice._d3dDevice, GetTexture(), renderTargetViewDescription); } // If we don't need a depth buffer then we're done. if (preferredDepthFormat == DepthFormat.None) { return; } var sampleDescription = new SampleDescription(1, 0); if (preferredMultiSampleCount > 1) { sampleDescription.Count = preferredMultiSampleCount; sampleDescription.Quality = (int)StandardMultisampleQualityLevels.StandardMultisamplePattern; } var depthStencilDescription = new Texture2DDescription { Format = SharpDXHelper.ToFormat(preferredDepthFormat), ArraySize = 1, MipLevels = 1, Width = size, Height = size, SampleDescription = sampleDescription, BindFlags = BindFlags.DepthStencil, }; using (var depthBuffer = new SharpDX.Direct3D11.Texture2D(graphicsDevice._d3dDevice, depthStencilDescription)) { var depthStencilViewDescription = new DepthStencilViewDescription { Dimension = DepthStencilViewDimension.Texture2D, Format = SharpDXHelper.ToFormat(preferredDepthFormat), }; _depthStencilView = new DepthStencilView(graphicsDevice._d3dDevice, depthBuffer, depthStencilViewDescription); } }
internal virtual void ResolveSubresource() { lock (GraphicsDevice._d3dContext) { GraphicsDevice._d3dContext.ResolveSubresource( GetMSTexture(), 0, GetTexture(), 0, SharpDXHelper.ToFormat(Format)); } }
internal void ResolveSubresource() { lock (GraphicsDevice._d3dContext) { GraphicsDevice._d3dContext.ResolveSubresource( this._texture, 0, _resolvedTexture._texture, 0, SharpDXHelper.ToFormat(_format)); } }
public Texture3D(GraphicsDevice graphicsDevice, int width, int height, int depth, bool mipMap, SurfaceFormat format) { if (graphicsDevice == null) { throw new ArgumentNullException("graphicsDevice"); } this.GraphicsDevice = graphicsDevice; this.width = width; this.height = height; this.depth = depth; this.levelCount = 1; #if OPENGL this.glTarget = TextureTarget.Texture3D; GL.GenTextures(1, out this.glTexture); GraphicsExtensions.CheckGLError(); GL.BindTexture(glTarget, glTexture); GraphicsExtensions.CheckGLError(); format.GetGLFormat(out glInternalFormat, out glFormat, out glType); GL.TexImage3D(glTarget, 0, glInternalFormat, width, height, depth, 0, glFormat, glType, IntPtr.Zero); GraphicsExtensions.CheckGLError(); if (mipMap) { throw new NotImplementedException("Texture3D does not yet support mipmaps."); } #elif DIRECTX if (mipMap) { this.levelCount = CalculateMipLevels(width, height, depth); } var description = new Texture3DDescription { Width = width, Height = height, Depth = depth, MipLevels = levelCount, Format = SharpDXHelper.ToFormat(format), BindFlags = BindFlags.ShaderResource, CpuAccessFlags = CpuAccessFlags.None, Usage = ResourceUsage.Default, OptionFlags = ResourceOptionFlags.None, }; _texture = new SharpDX.Direct3D11.Texture3D(graphicsDevice._d3dDevice, description); #endif }
private unsafe void PlatformGetData( CubeMapFace cubeMapFace, int level, Rectangle rect, Span <byte> destination) { // Create a temp staging resource for copying the data. // // TODO: Like in Texture2D, we should probably be pooling these staging resources // and not creating a new one each time. var min = Format.IsCompressedFormat() ? 4 : 1; var levelSize = Math.Max(Size >> level, min); var desc = new Texture2DDescription { Width = levelSize, Height = levelSize, MipLevels = 1, ArraySize = 1, Format = SharpDXHelper.ToFormat(Format), SampleDescription = new SampleDescription(1, 0), BindFlags = BindFlags.None, CpuAccessFlags = CpuAccessFlags.Read, Usage = ResourceUsage.Staging, OptionFlags = ResourceOptionFlags.None, }; var subresourceIndex = CalculateSubresourceIndex(cubeMapFace, level); var columns = rect.Width; var rows = rect.Height; var region = new ResourceRegion(rect.Left, rect.Top, 0, rect.Right, rect.Bottom, 1); var d3dContext = GraphicsDevice._d3dContext; using (var stagingTex = new SharpDX.Direct3D11.Texture2D(GraphicsDevice._d3dDevice, desc)) { lock (d3dContext) { // Copy the data from the GPU to the staging texture. d3dContext.CopySubresourceRegion(GetTexture(), subresourceIndex, region, stagingTex, 0); var elementSize = Format.GetSize(); if (Format.IsCompressedFormat()) { // for 4x4 block compression formats an element is one block, so elementsInRow // and number of rows are 1/4 of number of pixels in width and height of the rectangle columns /= 4; rows /= 4; } var box = d3dContext.MapSubresource(stagingTex, 0, MapMode.Read, MapFlags.None); GraphicsDevice.CopyResourceTo(Format, box, columns, rows, destination); } } }
private void GenerateIfRequired() { if (_renderTargetView != null) { return; } // Create a view interface on the rendertarget to use on bind. _renderTargetView = new RenderTargetView(GraphicsDevice._d3dDevice, GetTexture()); // If we don't need a depth buffer then we're done. if (DepthStencilFormat == DepthFormat.None) { return; } // Setup the multisampling description. var multisampleDesc = new SharpDX.DXGI.SampleDescription(1, 0); if (MultiSampleCount > 1) { multisampleDesc.Count = MultiSampleCount; multisampleDesc.Quality = (int)StandardMultisampleQualityLevels.StandardMultisamplePattern; } // Create a descriptor for the depth/stencil buffer. // Allocate a 2-D surface as the depth/stencil buffer. // Create a DepthStencil view on this surface to use on bind. using (var depthBuffer = new SharpDX.Direct3D11.Texture2D(GraphicsDevice._d3dDevice, new Texture2DDescription { Format = SharpDXHelper.ToFormat(DepthStencilFormat), ArraySize = 1, MipLevels = 1, Width = width, Height = height, SampleDescription = multisampleDesc, BindFlags = BindFlags.DepthStencil, })) { // Create the view for binding to the device. _depthStencilView = new DepthStencilView(GraphicsDevice._d3dDevice, depthBuffer, new DepthStencilViewDescription() { Format = SharpDXHelper.ToFormat(DepthStencilFormat), Dimension = DepthStencilViewDimension.Texture2D }); } }
private int GetMaxMultiSampleCount(GraphicsDevice device) { var format = SharpDXHelper.ToFormat(device.PresentationParameters.BackBufferFormat); var qualityLevels = 0; var maxLevel = 32; while (maxLevel > 0) { qualityLevels = ((SharpDX.Direct3D11.Device)device.Handle).CheckMultisampleQualityLevels(format, maxLevel); if (qualityLevels > 0) { break; } maxLevel /= 2; } return(maxLevel); }
public RenderTarget3D(GraphicsDevice graphicsDevice, int width, int height, int depth, bool mipMap, SurfaceFormat preferredFormat, DepthFormat preferredDepthFormat, int preferredMultiSampleCount, RenderTargetUsage usage) : base(graphicsDevice, width, height, depth, mipMap, preferredFormat, true) { DepthStencilFormat = preferredDepthFormat; MultiSampleCount = preferredMultiSampleCount; RenderTargetUsage = usage; // If we don't need a depth buffer then we're done. if (preferredDepthFormat == DepthFormat.None) { return; } #if DIRECTX // Setup the multisampling description. var multisampleDesc = new SharpDX.DXGI.SampleDescription(1, 0); if (preferredMultiSampleCount > 1) { multisampleDesc.Count = preferredMultiSampleCount; multisampleDesc.Quality = (int)StandardMultisampleQualityLevels.StandardMultisamplePattern; } // Create a descriptor for the depth/stencil buffer. // Allocate a 2-D surface as the depth/stencil buffer. // Create a DepthStencil view on this surface to use on bind. using (var depthBuffer = new SharpDX.Direct3D11.Texture2D(graphicsDevice._d3dDevice, new Texture2DDescription { Format = SharpDXHelper.ToFormat(preferredDepthFormat), ArraySize = 1, MipLevels = 1, Width = width, Height = height, SampleDescription = multisampleDesc, BindFlags = BindFlags.DepthStencil, })) { // Create the view for binding to the device. _depthStencilView = new DepthStencilView(graphicsDevice._d3dDevice, depthBuffer, new DepthStencilViewDescription() { Format = SharpDXHelper.ToFormat(preferredDepthFormat), Dimension = DepthStencilViewDimension.Texture2D }); } #endif // DIRECTX }
private int GetMaxMultiSampleCount(GraphicsDevice device) { var format = SharpDXHelper.ToFormat(device.PresentationParameters.BackBufferFormat); // Find the maximum supported level starting with the game's requested multisampling level // and halving each time until reaching 0 (meaning no multisample support). var qualityLevels = 0; var maxLevel = MultiSampleCountLimit; while (maxLevel > 0) { qualityLevels = device._d3dDevice.CheckMultisampleQualityLevels(format, maxLevel); if (qualityLevels > 0) { break; } maxLevel /= 2; } return(maxLevel); }
public SwapChainRenderTarget( GraphicsDevice graphicsDevice, IntPtr windowHandle, int width, int height, bool mipMap, SurfaceFormat surfaceFormat, DepthFormat depthFormat, int preferredMultiSampleCount, RenderTargetUsage usage, PresentInterval presentInterval) : base(graphicsDevice, width, height, mipMap, surfaceFormat, depthFormat, preferredMultiSampleCount, usage, SurfaceType.SwapChainRenderTarget) { var dxgiFormat = surfaceFormat == SurfaceFormat.Rgba32 ? SharpDX.DXGI.Format.B8G8R8A8_UNorm : SharpDXHelper.ToFormat(surfaceFormat); var multisampleDesc = GraphicsDevice.GetSupportedSampleDescription(dxgiFormat, MultiSampleCount); _windowHandle = windowHandle; PresentInterval = presentInterval; SwapChainRenderTargetConstruct(depthFormat, ref dxgiFormat, ref multisampleDesc); }
private void SwapChainRenderTargetConstruct( DepthFormat depthFormat, ref Format dxgiFormat, ref SampleDescription multisampleDesc) { var backBuffer = CreateSwaipChainTexture(dxgiFormat, multisampleDesc); // Once the desired swap chain description is configured, it must // be created on the same adapter as our D3D Device var d3dDevice = GraphicsDevice._d3dDevice; // Create a view interface on the rendertarget to use on bind. _renderTargetViews = new[] { new RenderTargetView(d3dDevice, backBuffer) }; // Get the rendertarget dimensions for later. var backBufferDesc = backBuffer.Description; var targetSize = new Point(backBufferDesc.Width, backBufferDesc.Height); // Create the depth buffer if we need it. if (depthFormat != DepthFormat.None) { dxgiFormat = SharpDXHelper.ToFormat(depthFormat); // Allocate a 2-D surface as the depth/stencil buffer. var textureDescription = new Texture2DDescription() { Format = dxgiFormat, ArraySize = 1, MipLevels = 1, Width = targetSize.X, Height = targetSize.Y, SampleDescription = multisampleDesc, Usage = ResourceUsage.Default, BindFlags = BindFlags.DepthStencil, }; using (var depthBuffer = new SharpDX.Direct3D11.Texture2D(d3dDevice, textureDescription)) { // Create a DepthStencil view on this surface to use on bind. _depthStencilView = new DepthStencilView(d3dDevice, depthBuffer); } } }
RenderTargetView IRenderTarget.GetRenderTargetView(int arraySlice) { if (arraySlice >= Depth) { throw new ArgumentOutOfRangeException("The arraySlice is out of range for this Texture3D."); } // Dispose the previous target. if (_currentSlice != arraySlice && _renderTargetView != null) { _renderTargetView.Dispose(); _renderTargetView = null; } // Create the new target view interface. if (_renderTargetView == null) { _currentSlice = arraySlice; var desc = new RenderTargetViewDescription { Format = SharpDXHelper.ToFormat(_format), Dimension = RenderTargetViewDimension.Texture3D, Texture3D = { DepthSliceCount = -1, FirstDepthSlice = arraySlice, MipSlice = 0, } }; _renderTargetView = new RenderTargetView(GraphicsDevice._d3dDevice, GetTexture(), desc); } return(_renderTargetView); }
protected internal override SampleDescription CreateSampleDescription() { return(this.GraphicsDevice.GetSupportedSampleDescription (SharpDXHelper.ToFormat(this._format), this.MultiSampleCount)); }
protected Texture3D(GraphicsDevice graphicsDevice, int width, int height, int depth, bool mipMap, SurfaceFormat format, bool renderTarget) { if (graphicsDevice == null) { throw new ArgumentNullException("graphicsDevice"); } this.GraphicsDevice = graphicsDevice; this.width = width; this.height = height; this.depth = depth; this._levelCount = 1; this._format = format; #if OPENGL this.glTarget = TextureTarget.Texture3D; GL.GenTextures(1, out this.glTexture); GraphicsExtensions.CheckGLError(); GL.BindTexture(glTarget, glTexture); GraphicsExtensions.CheckGLError(); format.GetGLFormat(out glInternalFormat, out glFormat, out glType); GL.TexImage3D(glTarget, 0, glInternalFormat, width, height, depth, 0, glFormat, glType, IntPtr.Zero); GraphicsExtensions.CheckGLError(); if (mipMap) { throw new NotImplementedException("Texture3D does not yet support mipmaps."); } #elif DIRECTX if (mipMap) { this._levelCount = CalculateMipLevels(width, height, depth); } var description = new Texture3DDescription { Width = width, Height = height, Depth = depth, MipLevels = _levelCount, Format = SharpDXHelper.ToFormat(format), BindFlags = BindFlags.ShaderResource, CpuAccessFlags = CpuAccessFlags.None, Usage = ResourceUsage.Default, OptionFlags = ResourceOptionFlags.None, }; if (renderTarget) { description.BindFlags |= BindFlags.RenderTarget; if (mipMap) { // Note: XNA 4 does not have a method Texture.GenerateMipMaps() // because generation of mipmaps is not supported on the Xbox 360. // TODO: New method Texture.GenerateMipMaps() required. description.OptionFlags |= ResourceOptionFlags.GenerateMipMaps; } } _texture = new SharpDX.Direct3D11.Texture3D(graphicsDevice._d3dDevice, description); #endif }
private void PlatformGetData <T>(CubeMapFace cubeMapFace, int level, Rectangle rect, T[] data, int startIndex, int elementCount) where T : struct { // Create a temp staging resource for copying the data. // // TODO: Like in Texture2D, we should probably be pooling these staging resources // and not creating a new one each time. // var min = _format.IsCompressedFormat() ? 4 : 1; var levelSize = Math.Max(size >> level, min); var desc = new Texture2DDescription { Width = levelSize, Height = levelSize, MipLevels = 1, ArraySize = 1, Format = SharpDXHelper.ToFormat(_format), SampleDescription = new SampleDescription(1, 0), BindFlags = BindFlags.None, CpuAccessFlags = CpuAccessFlags.Read, Usage = ResourceUsage.Staging, OptionFlags = ResourceOptionFlags.None, }; var d3dContext = GraphicsDevice._d3dContext; using (var stagingTex = new SharpDX.Direct3D11.Texture2D(GraphicsDevice._d3dDevice, desc)) { lock (d3dContext) { // Copy the data from the GPU to the staging texture. var subresourceIndex = CalculateSubresourceIndex(cubeMapFace, level); var elementsInRow = rect.Width; var rows = rect.Height; var region = new ResourceRegion(rect.Left, rect.Top, 0, rect.Right, rect.Bottom, 1); d3dContext.CopySubresourceRegion(GetTexture(), subresourceIndex, region, stagingTex, 0); // Copy the data to the array. DataStream stream = null; try { var databox = d3dContext.MapSubresource(stagingTex, 0, MapMode.Read, MapFlags.None, out stream); var elementSize = _format.GetSize(); if (_format.IsCompressedFormat()) { // for 4x4 block compression formats an element is one block, so elementsInRow // and number of rows are 1/4 of number of pixels in width and height of the rectangle elementsInRow /= 4; rows /= 4; } var rowSize = elementSize * elementsInRow; if (rowSize == databox.RowPitch) { stream.ReadRange(data, startIndex, elementCount); } else { // Some drivers may add pitch to rows. // We need to copy each row separatly and skip trailing zeros. stream.Seek(0, SeekOrigin.Begin); var elementSizeInByte = ReflectionHelpers.SizeOf <T> .Get(); for (var row = 0; row < rows; row++) { int i; for (i = row * rowSize / elementSizeInByte; i < (row + 1) * rowSize / elementSizeInByte; i++) { data[i + startIndex] = stream.Read <T>(); } if (i >= elementCount) { break; } stream.Seek(databox.RowPitch - rowSize, SeekOrigin.Current); } } } finally { SharpDX.Utilities.Dispose(ref stream); } } } }
public void GetData<T>(int level, Rectangle? rect, T[] data, int startIndex, int elementCount) where T : struct { if (data == null || data.Length == 0) throw new ArgumentException("data cannot be null"); if (data.Length < startIndex + elementCount) throw new ArgumentException("The data passed has a length of " + data.Length + " but " + elementCount + " pixels have been requested."); #if IOS // Reading back a texture from GPU memory is unsupported // in OpenGL ES 2.0 and no work around has been implemented. throw new NotSupportedException("OpenGL ES 2.0 does not support texture reads."); #elif ANDROID Rectangle r; if (rect != null) { r = rect.Value; } else { r = new Rectangle(0, 0, Width, Height); } // Get the Color values if (typeof(T) == typeof(uint)) { Color[] colors = new Color[elementCount]; GetData<Color>(level, rect, colors, startIndex, elementCount); uint[] final = data as uint[]; for (int i = 0; i < final.Length; i++) { final[i] = (uint) ( // use correct xna byte order (and remember to convert it yourself as needed) colors[i].A << 24 | colors[i].B << 16 | colors[i].G << 8 | colors[i].R ); } } // Get the Color values else if ((typeof(T) == typeof(Color))) { byte[] imageInfo = GetTextureData(0); int rWidth = r.Width; int rHeight = r.Height; // Loop through and extract the data but we need to load it var dataRowColOffset = 0; var sz = 0; var pixelOffset = 0; for (int y = r.Top; y < rHeight; y++) { for (int x = r.Left; x < rWidth; x++) { var result = new Color(0, 0, 0, 0); dataRowColOffset = ((y * r.Width) + x); switch (Format) { case SurfaceFormat.Color: //kTexture2DPixelFormat_RGBA8888 case SurfaceFormat.Dxt3: sz = 4; pixelOffset = dataRowColOffset * sz; result.R = imageInfo[pixelOffset]; result.G = imageInfo[pixelOffset + 1]; result.B = imageInfo[pixelOffset + 2]; result.A = imageInfo[pixelOffset + 3]; break; case SurfaceFormat.Bgra4444: //kTexture2DPixelFormat_RGBA4444 // sz = 2; // pos = ((y * imageSize.Width) + x) * sz; // pixelOffset = new IntPtr (imageData.ToInt64 () + pos); // // Marshal.Copy (pixelOffset, pixel, 0, 4); // // result.R = pixel [0]; // result.G = pixel [1]; // result.B = pixel [2]; // result.A = pixel [3]; sz = 2; pixelOffset = dataRowColOffset * sz; result.R = imageInfo[pixelOffset]; result.G = imageInfo[pixelOffset + 1]; result.B = imageInfo[pixelOffset + 2]; result.A = imageInfo[pixelOffset + 3]; break; case SurfaceFormat.Bgra5551: //kTexture2DPixelFormat_RGB5A1 // sz = 2; // pos = ((y * imageSize.Width) + x) * sz; // pixelOffset = new IntPtr (imageData.ToInt64 () + pos); // Marshal.Copy (pixelOffset, pixel, 0, 4); // // result.R = pixel [0]; // result.G = pixel [1]; // result.B = pixel [2]; // result.A = pixel [3]; sz = 2; pixelOffset = dataRowColOffset * sz; result.R = imageInfo[pixelOffset]; result.G = imageInfo[pixelOffset + 1]; result.B = imageInfo[pixelOffset + 2]; result.A = imageInfo[pixelOffset + 3]; break; case SurfaceFormat.Alpha8: // kTexture2DPixelFormat_A8 // sz = 1; // pos = ((y * imageSize.Width) + x) * sz; // pixelOffset = new IntPtr (imageData.ToInt64 () + pos); // Marshal.Copy (pixelOffset, pixel, 0, 4); // // result.A = pixel [0]; sz = 1; pixelOffset = dataRowColOffset * sz; result.A = imageInfo[pixelOffset]; break; default: throw new NotSupportedException("Texture format"); } data[dataRowColOffset] = (T)(object)result; } } } else { throw new NotImplementedException("GetData not implemented for type."); } #elif PSM Rectangle r; if (rect.HasValue) { r = rect.Value; } else { r = new Rectangle(0, 0, Width, Height); } int rWidth = r.Width; int rHeight = r.Height; var sz = 4; // Loop through and extract the data but we need to load it var dataRowColOffset = 0; var pixelOffset = 0; var result = new Color(0, 0, 0, 0); byte[] imageInfo = new byte[(rWidth * rHeight) * sz]; ImageRect old_scissor = GraphicsDevice.Context.GetScissor(); ImageRect old_viewport = GraphicsDevice.Context.GetViewport(); FrameBuffer old_frame_buffer = GraphicsDevice.Context.GetFrameBuffer(); ColorBuffer color_buffer = new ColorBuffer(rWidth, rHeight, PixelFormat.Rgba); FrameBuffer frame_buffer = new FrameBuffer(); frame_buffer.SetColorTarget(color_buffer); GraphicsDevice.Context.SetFrameBuffer(frame_buffer); GraphicsDevice.Context.SetTexture(0, this._texture2D); GraphicsDevice.Context.ReadPixels(imageInfo, PixelFormat.Rgba, 0, 0, rWidth, rHeight); GraphicsDevice.Context.SetFrameBuffer(old_frame_buffer); GraphicsDevice.Context.SetScissor(old_scissor); GraphicsDevice.Context.SetViewport(old_viewport); for (int y = r.Top; y < rHeight; y++) { for (int x = r.Left; x < rWidth; x++) { dataRowColOffset = ((y * r.Width) + x); pixelOffset = dataRowColOffset * sz; result.R = imageInfo[pixelOffset]; result.G = imageInfo[pixelOffset + 1]; result.B = imageInfo[pixelOffset + 2]; result.A = imageInfo[pixelOffset + 3]; data[dataRowColOffset] = (T)(object)result; } } #elif DIRECTX // Create a temp staging resource for copying the data. // // TODO: We should probably be pooling these staging resources // and not creating a new one each time. // var desc = new SharpDX.Direct3D11.Texture2DDescription(); desc.Width = width; desc.Height = height; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = SharpDXHelper.ToFormat(_format); desc.BindFlags = SharpDX.Direct3D11.BindFlags.None; desc.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.Read; desc.SampleDescription.Count = 1; desc.SampleDescription.Quality = 0; desc.Usage = SharpDX.Direct3D11.ResourceUsage.Staging; desc.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None; var d3dContext = GraphicsDevice._d3dContext; using (var stagingTex = new SharpDX.Direct3D11.Texture2D(GraphicsDevice._d3dDevice, desc)) lock (d3dContext) { // Copy the data from the GPU to the staging texture. int elementsInRow; int rows; if (rect.HasValue) { elementsInRow = rect.Value.Width; rows = rect.Value.Height; d3dContext.CopySubresourceRegion(GetTexture(), level, new SharpDX.Direct3D11.ResourceRegion(rect.Value.Left, rect.Value.Top, 0, rect.Value.Right, rect.Value.Bottom, 1), stagingTex, 0, 0, 0, 0); } else { elementsInRow = width; rows = height; d3dContext.CopySubresourceRegion(GetTexture(), level, null, stagingTex, 0, 0, 0, 0); } // Copy the data to the array. SharpDX.DataStream stream; var databox = d3dContext.MapSubresource(stagingTex, 0, SharpDX.Direct3D11.MapMode.Read, SharpDX.Direct3D11.MapFlags.None, out stream); // Some drivers may add pitch to rows. // We need to copy each row separatly and skip trailing zeros. var currentIndex = startIndex; var elementSize = SharpDX.Utilities.SizeOf<T>(); for (var row = 0; row < rows; row++) { stream.ReadRange(data, currentIndex, elementsInRow); stream.Seek(databox.RowPitch - (elementSize * elementsInRow), SeekOrigin.Current); currentIndex += elementsInRow; } stream.Dispose(); } #else GL.BindTexture(TextureTarget.Texture2D, this.glTexture); if (glFormat == (GLPixelFormat)All.CompressedTextureFormats) { throw new NotImplementedException(); } else { if (rect.HasValue) { var temp = new T[this.width*this.height]; GL.GetTexImage(TextureTarget.Texture2D, level, this.glFormat, this.glType, temp); int z = 0, w = 0; for(int y= rect.Value.Y; y < rect.Value.Y+ rect.Value.Height; y++) { for(int x=rect.Value.X; x < rect.Value.X + rect.Value.Width; x++) { data[z*rect.Value.Width+w] = temp[(y*width)+x]; w++; } z++; } } else { GL.GetTexImage(TextureTarget.Texture2D, level, this.glFormat, this.glType, data); } } #endif }
public RenderTarget2D(GraphicsDevice graphicsDevice, int width, int height, bool mipMap, SurfaceFormat preferredFormat, DepthFormat preferredDepthFormat, int preferredMultiSampleCount, RenderTargetUsage usage) : base(graphicsDevice, width, height, mipMap, preferredFormat, true) { DepthStencilFormat = preferredDepthFormat; MultiSampleCount = preferredMultiSampleCount; RenderTargetUsage = usage; #if DIRECTX // Create a view interface on the rendertarget to use on bind. _renderTargetView = new SharpDX.Direct3D11.RenderTargetView(graphicsDevice._d3dDevice, _texture); #endif // If we don't need a depth buffer then we're done. if (preferredDepthFormat == DepthFormat.None) { return; } #if DIRECTX // Setup the multisampling description. var multisampleDesc = new SharpDX.DXGI.SampleDescription(1, 0); if (preferredMultiSampleCount > 1) { multisampleDesc.Count = preferredMultiSampleCount; multisampleDesc.Quality = (int)SharpDX.Direct3D11.StandardMultisampleQualityLevels.StandardMultisamplePattern; } // Create a descriptor for the depth/stencil buffer. // Allocate a 2-D surface as the depth/stencil buffer. // Create a DepthStencil view on this surface to use on bind. using (var depthBuffer = new SharpDX.Direct3D11.Texture2D(graphicsDevice._d3dDevice, new SharpDX.Direct3D11.Texture2DDescription() { Format = SharpDXHelper.ToFormat(preferredDepthFormat), ArraySize = 1, MipLevels = 1, Width = width, Height = height, SampleDescription = multisampleDesc, BindFlags = SharpDX.Direct3D11.BindFlags.DepthStencil, })) // Create the view for binding to the device. _depthStencilView = new SharpDX.Direct3D11.DepthStencilView(graphicsDevice._d3dDevice, depthBuffer, new SharpDX.Direct3D11.DepthStencilViewDescription() { Format = SharpDXHelper.ToFormat(preferredDepthFormat), Dimension = SharpDX.Direct3D11.DepthStencilViewDimension.Texture2D }); #elif OPENGL #if GLES GL.GenRenderbuffers(1, ref glDepthStencilBuffer); #else GL.GenRenderbuffers(1, out glDepthStencilBuffer); #endif GraphicsExtensions.CheckGLError(); GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, this.glDepthStencilBuffer); GraphicsExtensions.CheckGLError(); var glDepthStencilFormat = GLDepthComponent16; switch (preferredDepthFormat) { case DepthFormat.Depth16: glDepthStencilFormat = GLDepthComponent16; break; case DepthFormat.Depth24: glDepthStencilFormat = GLDepthComponent24; break; case DepthFormat.Depth24Stencil8: glDepthStencilFormat = GLDepth24Stencil8; break; } GL.RenderbufferStorage(GLRenderbuffer, glDepthStencilFormat, this.width, this.height); GraphicsExtensions.CheckGLError(); #endif }
public SwapChainRenderTarget(GraphicsDevice graphicsDevice, IntPtr windowHandle, int width, int height, bool mipMap, SurfaceFormat surfaceFormat, DepthFormat depthFormat, int preferredMultiSampleCount, RenderTargetUsage usage, PresentInterval presentInterval) : base( graphicsDevice, width, height, mipMap, surfaceFormat, depthFormat, preferredMultiSampleCount, usage, SurfaceType.SwapChainRenderTarget) { var dxgiFormat = surfaceFormat == SurfaceFormat.Color ? SharpDX.DXGI.Format.B8G8R8A8_UNorm : SharpDXHelper.ToFormat(surfaceFormat); var multisampleDesc = new SampleDescription(1, 0); if (preferredMultiSampleCount > 1) { multisampleDesc.Count = preferredMultiSampleCount; multisampleDesc.Quality = (int)StandardMultisampleQualityLevels.StandardMultisamplePattern; } var desc = new SwapChainDescription() { ModeDescription = { Format = dxgiFormat, Scaling = DisplayModeScaling.Stretched, Width = width, Height = height, }, OutputHandle = windowHandle, SampleDescription = multisampleDesc, Usage = Usage.RenderTargetOutput, BufferCount = 2, SwapEffect = SharpDXHelper.ToSwapEffect(presentInterval), IsWindowed = true, }; PresentInterval = presentInterval; // Once the desired swap chain description is configured, it must // be created on the same adapter as our D3D Device var d3dDevice = graphicsDevice._d3dDevice; // First, retrieve the underlying DXGI Device from the D3D Device. // Creates the swap chain using (var dxgiDevice = d3dDevice.QueryInterface <SharpDX.DXGI.Device1>()) using (var dxgiAdapter = dxgiDevice.Adapter) using (var dxgiFactory = dxgiAdapter.GetParent <Factory1>()) { _swapChain = new SwapChain(dxgiFactory, dxgiDevice, desc); } // Obtain the backbuffer for this window which will be the final 3D rendertarget. var backBuffer = SharpDX.Direct3D11.Resource.FromSwapChain <SharpDX.Direct3D11.Texture2D>(_swapChain, 0); // Create a view interface on the rendertarget to use on bind. _renderTargetViews = new[] { new RenderTargetView(d3dDevice, backBuffer) }; // Get the rendertarget dimensions for later. var backBufferDesc = backBuffer.Description; var targetSize = new Point(backBufferDesc.Width, backBufferDesc.Height); _texture = backBuffer; // Create the depth buffer if we need it. if (depthFormat != DepthFormat.None) { dxgiFormat = SharpDXHelper.ToFormat(depthFormat); // Allocate a 2-D surface as the depth/stencil buffer. using ( var depthBuffer = new SharpDX.Direct3D11.Texture2D(d3dDevice, new Texture2DDescription() { Format = dxgiFormat, ArraySize = 1, MipLevels = 1, Width = targetSize.X, Height = targetSize.Y, SampleDescription = multisampleDesc, Usage = ResourceUsage.Default, BindFlags = BindFlags.DepthStencil, })) // Create a DepthStencil view on this surface to use on bind. _depthStencilView = new DepthStencilView(d3dDevice, depthBuffer); } }
protected Texture2D(GraphicsDevice graphicsDevice, int width, int height, bool mipmap, SurfaceFormat format, SurfaceType type, bool shared) { if (graphicsDevice == null) throw new ArgumentNullException("Graphics Device Cannot Be Null"); this.GraphicsDevice = graphicsDevice; this.width = width; this.height = height; this._format = format; this._levelCount = mipmap ? CalculateMipLevels(width, height) : 1; // Texture will be assigned by the swap chain. if (type == SurfaceType.SwapChainRenderTarget) return; #if DIRECTX // TODO: Move this to SetData() if we want to make Immutable textures! var desc = new SharpDX.Direct3D11.Texture2DDescription(); desc.Width = width; desc.Height = height; desc.MipLevels = _levelCount; desc.ArraySize = 1; desc.Format = SharpDXHelper.ToFormat(format); desc.BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource; desc.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None; desc.SampleDescription.Count = 1; desc.SampleDescription.Quality = 0; desc.Usage = SharpDX.Direct3D11.ResourceUsage.Default; desc.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None; if (type == SurfaceType.RenderTarget) { desc.BindFlags |= SharpDX.Direct3D11.BindFlags.RenderTarget; if (mipmap) { // Note: XNA 4 does not have a method Texture.GenerateMipMaps() // because generation of mipmaps is not supported on the Xbox 360. // TODO: New method Texture.GenerateMipMaps() required. desc.OptionFlags |= SharpDX.Direct3D11.ResourceOptionFlags.GenerateMipMaps; } } if (shared) desc.OptionFlags |= SharpDX.Direct3D11.ResourceOptionFlags.Shared; _texture = new SharpDX.Direct3D11.Texture2D(graphicsDevice._d3dDevice, desc); #elif PSM PixelBufferOption option = PixelBufferOption.None; if (type == SurfaceType.RenderTarget) option = PixelBufferOption.Renderable; _texture2D = new Sce.PlayStation.Core.Graphics.Texture2D(width, height, mipmap, PSSHelper.ToFormat(format),option); #else this.glTarget = TextureTarget.Texture2D; Threading.BlockOnUIThread(() => { // Store the current bound texture. var prevTexture = GraphicsExtensions.GetBoundTexture2D(); GenerateGLTextureIfRequired(); format.GetGLFormat(out glInternalFormat, out glFormat, out glType); if (glFormat == (GLPixelFormat)All.CompressedTextureFormats) { var imageSize = 0; switch (format) { case SurfaceFormat.RgbPvrtc2Bpp: case SurfaceFormat.RgbaPvrtc2Bpp: imageSize = (Math.Max(this.width, 8) * Math.Max(this.height, 8) * 2 + 7) / 8; break; case SurfaceFormat.RgbPvrtc4Bpp: case SurfaceFormat.RgbaPvrtc4Bpp: imageSize = (Math.Max(this.width, 16) * Math.Max(this.height, 8) * 4 + 7) / 8; break; case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1a: case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt5: imageSize = ((this.width + 3) / 4) * ((this.height + 3) / 4) * format.Size(); break; default: throw new NotImplementedException(); } GL.CompressedTexImage2D(TextureTarget.Texture2D, 0, glInternalFormat, this.width, this.height, 0, imageSize, IntPtr.Zero); GraphicsExtensions.CheckGLError(); } else { GL.TexImage2D(TextureTarget.Texture2D, 0, #if IOS || ANDROID (int)glInternalFormat, #else glInternalFormat, #endif this.width, this.height, 0, glFormat, glType, IntPtr.Zero); GraphicsExtensions.CheckGLError(); } // Restore the bound texture. GL.BindTexture(TextureTarget.Texture2D, prevTexture); GraphicsExtensions.CheckGLError(); }); #endif }
private void GenerateIfRequired() { if (_renderTargetViews != null) { return; } var viewTex = MultiSampleCount > 1 ? GetMSTexture() : GetTexture(); // Create a view interface on the rendertarget to use on bind. if (ArraySize > 1) { _renderTargetViews = new RenderTargetView[ArraySize]; for (var i = 0; i < ArraySize; i++) { var renderTargetViewDescription = new RenderTargetViewDescription(); if (MultiSampleCount > 1) { renderTargetViewDescription.Dimension = RenderTargetViewDimension.Texture2DMultisampledArray; renderTargetViewDescription.Texture2DMSArray.ArraySize = 1; renderTargetViewDescription.Texture2DMSArray.FirstArraySlice = i; } else { renderTargetViewDescription.Dimension = RenderTargetViewDimension.Texture2DArray; renderTargetViewDescription.Texture2DArray.ArraySize = 1; renderTargetViewDescription.Texture2DArray.FirstArraySlice = i; renderTargetViewDescription.Texture2DArray.MipSlice = 0; } _renderTargetViews[i] = new RenderTargetView( GraphicsDevice._d3dDevice, viewTex, renderTargetViewDescription); } } else { _renderTargetViews = new[] { new RenderTargetView(GraphicsDevice._d3dDevice, viewTex) }; } // If we don't need a depth buffer then we're done. if (DepthStencilFormat == DepthFormat.None) { return; } // The depth stencil view's multisampling configuration must strictly // match the texture's multisampling configuration. Ignore whatever parameters // were provided and use the texture's configuration so that things are // guarenteed to work. var multisampleDesc = _msSampleDescription; // Create a descriptor for the depth/stencil buffer. // Allocate a 2-D surface as the depth/stencil buffer. // Create a DepthStencil view on this surface to use on bind. using (var depthBuffer = new SharpDX.Direct3D11.Texture2D(GraphicsDevice._d3dDevice, new Texture2DDescription { Format = SharpDXHelper.ToFormat(DepthStencilFormat), ArraySize = 1, MipLevels = 1, Width = Width, Height = Height, SampleDescription = multisampleDesc, BindFlags = BindFlags.DepthStencil, })) { // Create the view for binding to the device. _depthStencilView = new DepthStencilView(GraphicsDevice._d3dDevice, depthBuffer, new DepthStencilViewDescription() { Format = SharpDXHelper.ToFormat(DepthStencilFormat), Dimension = MultiSampleCount > 1 ? DepthStencilViewDimension.Texture2DMultisampled : DepthStencilViewDimension.Texture2D }); } }
internal Texture2D(GraphicsDevice graphicsDevice, int width, int height, bool mipmap, SurfaceFormat format, bool renderTarget) { if (graphicsDevice == null) throw new ArgumentNullException("Graphics Device Cannot Be Null"); this.GraphicsDevice = graphicsDevice; this.width = width; this.height = height; this.format = format; this.levelCount = 1; if (mipmap) { int size = Math.Max(this.width, this.height); while (size > 1) { size = size / 2; this.levelCount++; } } #if DIRECTX // TODO: Move this to SetData() if we want to make Immutable textures! var desc = new SharpDX.Direct3D11.Texture2DDescription(); desc.Width = width; desc.Height = height; desc.MipLevels = levelCount; desc.ArraySize = 1; desc.Format = SharpDXHelper.ToFormat(format); desc.BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource; desc.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None; desc.SampleDescription.Count = 1; desc.SampleDescription.Quality = 0; desc.Usage = SharpDX.Direct3D11.ResourceUsage.Default; desc.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None; if (renderTarget) desc.BindFlags |= SharpDX.Direct3D11.BindFlags.RenderTarget; _texture = new SharpDX.Direct3D11.Texture2D(graphicsDevice._d3dDevice, desc); #elif PSM _texture2D = new Sce.PlayStation.Core.Graphics.Texture2D(width, height, mipmap, PSSHelper.ToFormat(format)); #else this.glTarget = TextureTarget.Texture2D; Threading.BlockOnUIThread(() => { // Store the current bound texture. var prevTexture = GraphicsExtensions.GetBoundTexture2D(); GenerateGLTextureIfRequired(); format.GetGLFormat(out glInternalFormat, out glFormat, out glType); if (glFormat == (GLPixelFormat)All.CompressedTextureFormats) { var imageSize = 0; switch (format) { case SurfaceFormat.RgbPvrtc2Bpp: case SurfaceFormat.RgbaPvrtc2Bpp: imageSize = (Math.Max(this.width, 8) * Math.Max(this.height, 8) * 2 + 7) / 8; break; case SurfaceFormat.RgbPvrtc4Bpp: case SurfaceFormat.RgbaPvrtc4Bpp: imageSize = (Math.Max(this.width, 16) * Math.Max(this.height, 8) * 4 + 7) / 8; break; case SurfaceFormat.Dxt1: imageSize = ((this.width + 3) / 4) * ((this.height + 3) / 4) * 8 * 1; break; case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt5: imageSize = ((this.width + 3) / 4) * ((this.height + 3) / 4) * 16 * 1; break; default: throw new NotImplementedException(); } GL.CompressedTexImage2D(TextureTarget.Texture2D, 0, glInternalFormat, this.width, this.height, 0, imageSize, IntPtr.Zero); GraphicsExtensions.CheckGLError(); } else { GL.TexImage2D(TextureTarget.Texture2D, 0, #if IOS || ANDROID (int)glInternalFormat, #else glInternalFormat, #endif this.width, this.height, 0, glFormat, glType, IntPtr.Zero); GraphicsExtensions.CheckGLError(); } // Restore the bound texture. GL.BindTexture(TextureTarget.Texture2D, prevTexture); GraphicsExtensions.CheckGLError(); }); #endif }
/// <summary> /// Gets a copy of 3D texture data, specifying a mipmap level, source box, start index, and number of elements. /// </summary> /// <typeparam name="T">The type of the elements in the array.</typeparam> /// <param name="level">Mipmap level.</param> /// <param name="left">Position of the left side of the box on the x-axis.</param> /// <param name="top">Position of the top of the box on the y-axis.</param> /// <param name="right">Position of the right side of the box on the x-axis.</param> /// <param name="bottom">Position of the bottom of the box on the y-axis.</param> /// <param name="front">Position of the front of the box on the z-axis.</param> /// <param name="back">Position of the back of the box on the z-axis.</param> /// <param name="data">Array of data.</param> /// <param name="startIndex">Index of the first element to get.</param> /// <param name="elementCount">Number of elements to get.</param> public void GetData <T>(int level, int left, int top, int right, int bottom, int front, int back, T[] data, int startIndex, int elementCount) where T : struct { if (data == null || data.Length == 0) { throw new ArgumentException("data cannot be null"); } if (data.Length < startIndex + elementCount) { throw new ArgumentException("The data passed has a length of " + data.Length + " but " + elementCount + " pixels have been requested."); } // Disallow negative box size if ((left < 0 || left >= right) || (top < 0 || top >= bottom) || (front < 0 || front >= back)) { throw new ArgumentException("Neither box size nor box position can be negative"); } #if IOS // Reading back a texture from GPU memory is unsupported // in OpenGL ES 2.0 and no work around has been implemented. throw new NotSupportedException("OpenGL ES 2.0 does not support texture reads."); #elif ANDROID throw new NotImplementedException(); #elif PSM throw new NotImplementedException(); #elif DIRECTX // Create a temp staging resource for copying the data. // // TODO: Like in Texture2D, we should probably be pooling these staging resources // and not creating a new one each time. // var desc = new Texture3DDescription { Width = width, Height = height, Depth = depth, MipLevels = 1, Format = SharpDXHelper.ToFormat(_format), BindFlags = BindFlags.None, CpuAccessFlags = CpuAccessFlags.Read, Usage = ResourceUsage.Staging, OptionFlags = ResourceOptionFlags.None, }; var d3dContext = GraphicsDevice._d3dContext; using (var stagingTex = new SharpDX.Direct3D11.Texture3D(GraphicsDevice._d3dDevice, desc)) { lock (d3dContext) { // Copy the data from the GPU to the staging texture. d3dContext.CopySubresourceRegion(GetTexture(), level, new ResourceRegion(left, top, front, right, bottom, back), stagingTex, 0); // Copy the data to the array. DataStream stream; var databox = d3dContext.MapSubresource(stagingTex, 0, MapMode.Read, MapFlags.None, out stream); // Some drivers may add pitch to rows or slices. // We need to copy each row separatly and skip trailing zeros. var currentIndex = startIndex; var elementSize = SharpDX.Utilities.SizeOf <T>(); var elementsInRow = right - left; var rowsInSlice = bottom - top; for (var slice = front; slice < back; slice++) { for (var row = top; row < bottom; row++) { stream.ReadRange(data, currentIndex, elementsInRow); stream.Seek(databox.RowPitch - (elementSize * elementsInRow), SeekOrigin.Current); currentIndex += elementsInRow; } stream.Seek(databox.SlicePitch - (databox.RowPitch * rowsInSlice), SeekOrigin.Current); } stream.Dispose(); } } #else throw new NotImplementedException(); #endif }
public void GetData<T>(int level, Rectangle? rect, T[] data, int startIndex, int elementCount) where T : struct { #if IOS throw new NotImplementedException(); #elif ANDROID if (data == null) { throw new ArgumentException("data cannot be null"); } if (data.Length < startIndex + elementCount) { throw new ArgumentException("The data passed has a length of " + data.Length + " but " + elementCount + " pixels have been requested."); } Rectangle r; if (rect != null) { r = rect.Value; } else { r = new Rectangle(0, 0, Width, Height); } // Get the Color values if (typeof(T) == typeof(uint)) { Color[] colors = new Color[elementCount]; GetData<Color>(level, rect, colors, startIndex, elementCount); uint[] final = data as uint[]; for (int i = 0; i < final.Length; i++) { final[i] = (uint) ( colors[i].R << 24 | colors[i].G << 16 | colors[i].B << 8 | colors[i].A ); } } // Get the Color values else if ((typeof(T) == typeof(Color))) { byte[] imageInfo = GetTextureData(0); int rWidth = r.Width; int rHeight = r.Height; // Loop through and extract the data but we need to load it var dataRowColOffset = 0; var sz = 0; var pixelOffset = 0; for (int y = r.Top; y < rHeight; y++) { for (int x = r.Left; x < rWidth; x++) { var result = new Color(0, 0, 0, 0); dataRowColOffset = ((y * r.Width) + x); switch (Format) { case SurfaceFormat.Color: //kTexture2DPixelFormat_RGBA8888 case SurfaceFormat.Dxt3: sz = 4; pixelOffset = dataRowColOffset * sz; result.R = imageInfo[pixelOffset]; result.G = imageInfo[pixelOffset + 1]; result.B = imageInfo[pixelOffset + 2]; result.A = imageInfo[pixelOffset + 3]; break; case SurfaceFormat.Bgra4444: //kTexture2DPixelFormat_RGBA4444 // sz = 2; // pos = ((y * imageSize.Width) + x) * sz; // pixelOffset = new IntPtr (imageData.ToInt64 () + pos); // // Marshal.Copy (pixelOffset, pixel, 0, 4); // // result.R = pixel [0]; // result.G = pixel [1]; // result.B = pixel [2]; // result.A = pixel [3]; sz = 2; pixelOffset = dataRowColOffset * sz; result.R = imageInfo[pixelOffset]; result.G = imageInfo[pixelOffset + 1]; result.B = imageInfo[pixelOffset + 2]; result.A = imageInfo[pixelOffset + 3]; break; case SurfaceFormat.Bgra5551: //kTexture2DPixelFormat_RGB5A1 // sz = 2; // pos = ((y * imageSize.Width) + x) * sz; // pixelOffset = new IntPtr (imageData.ToInt64 () + pos); // Marshal.Copy (pixelOffset, pixel, 0, 4); // // result.R = pixel [0]; // result.G = pixel [1]; // result.B = pixel [2]; // result.A = pixel [3]; sz = 2; pixelOffset = dataRowColOffset * sz; result.R = imageInfo[pixelOffset]; result.G = imageInfo[pixelOffset + 1]; result.B = imageInfo[pixelOffset + 2]; result.A = imageInfo[pixelOffset + 3]; break; case SurfaceFormat.Alpha8: // kTexture2DPixelFormat_A8 // sz = 1; // pos = ((y * imageSize.Width) + x) * sz; // pixelOffset = new IntPtr (imageData.ToInt64 () + pos); // Marshal.Copy (pixelOffset, pixel, 0, 4); // // result.A = pixel [0]; sz = 1; pixelOffset = dataRowColOffset * sz; result.A = imageInfo[pixelOffset]; break; default: throw new NotSupportedException("Texture format"); } data[dataRowColOffset] = (T)(object)result; } } } else { throw new NotImplementedException("GetData not implemented for type."); } #elif PSM throw new NotImplementedException(); #elif DIRECTX // Create a temp staging resource for copying the data. // // TODO: We should probably be pooling these staging resources // and not creating a new one each time. // var desc = new SharpDX.Direct3D11.Texture2DDescription(); desc.Width = width; desc.Height = height; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = SharpDXHelper.ToFormat(format); desc.BindFlags = SharpDX.Direct3D11.BindFlags.None; desc.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.Read; desc.SampleDescription.Count = 1; desc.SampleDescription.Quality = 0; desc.Usage = SharpDX.Direct3D11.ResourceUsage.Staging; desc.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None; var d3dContext = GraphicsDevice._d3dContext; using (var stagingTex = new SharpDX.Direct3D11.Texture2D(GraphicsDevice._d3dDevice, desc)) lock (d3dContext) { // Copy the data from the GPU to the staging texture. if (rect.HasValue) { // TODO: Need to deal with subregion copies! throw new NotImplementedException(); } else d3dContext.CopySubresourceRegion(_texture, level, null, stagingTex, 0, 0, 0, 0); // Copy the data to the array. SharpDX.DataStream stream; d3dContext.MapSubresource(stagingTex, 0, SharpDX.Direct3D11.MapMode.Read, SharpDX.Direct3D11.MapFlags.None, out stream); stream.ReadRange(data, startIndex, elementCount); stream.Dispose(); } #else GL.BindTexture(TextureTarget.Texture2D, this.glTexture); if (rect.HasValue) { throw new NotImplementedException(); } if (glFormat == (GLPixelFormat)All.CompressedTextureFormats) { throw new NotImplementedException(); } else { GL.GetTexImage(TextureTarget.Texture2D, level, this.glFormat, this.glType, data); } #endif }