Example #1
1
        protected void Blit(D3D9.Device d3d9Device, HardwarePixelBuffer rsrc, BasicBox srcBox, BasicBox dstBox,
                            BufferResources srcBufferResources, BufferResources dstBufferResources)
        {
            if (dstBufferResources.Surface != null && srcBufferResources.Surface != null)
            {
                // Surface-to-surface
                var dsrcRect  = ToD3DRectangle(srcBox);
                var ddestRect = ToD3DRectangle(dstBox);

                var srcDesc = srcBufferResources.Surface.Description;

                // If we're blitting from a RTT, try GetRenderTargetData
                // if we're going to try to use GetRenderTargetData, need to use system mem pool

                // romeoxbm: not used even in Ogre
                //var tryGetRenderTargetData = false;

                if ((srcDesc.Usage & D3D9.Usage.RenderTarget) != 0 && srcDesc.MultiSampleType == D3D9.MultisampleType.None)
                {
                    // Temp texture
                    var tmptex = new D3D9.Texture(d3d9Device, srcDesc.Width, srcDesc.Height, 1,
                                                  // 1 mip level ie topmost, generate no mipmaps
                                                  0, srcDesc.Format, D3D9.Pool.SystemMemory);

                    var tmpsurface = tmptex.GetSurfaceLevel(0);

                    d3d9Device.GetRenderTargetData(srcBufferResources.Surface, tmpsurface);
                    D3D9.Surface.FromSurface(dstBufferResources.Surface, tmpsurface, D3D9.Filter.Default, 0, dsrcRect,
                                             ddestRect);
                    tmpsurface.SafeDispose();
                    tmptex.SafeDispose();
                    return;
                }

                // Otherwise, try the normal method
                D3D9.Surface.FromSurface(dstBufferResources.Surface, srcBufferResources.Surface, D3D9.Filter.Default, 0,
                                         dsrcRect, ddestRect);
            }
            else if (dstBufferResources.Volume != null && srcBufferResources.Volume != null)
            {
                // Volume-to-volume
                var dsrcBox  = ToD3DBox(srcBox);
                var ddestBox = ToD3DBox(dstBox);

                D3D9.Volume.FromVolume(dstBufferResources.Volume, srcBufferResources.Volume, D3D9.Filter.Default, 0,
                                       dsrcBox, ddestBox);
            }
            else
            {
                // Software fallback
                base.Blit(rsrc, srcBox, dstBox);
            }
        }
        public void CreateBuffer(D3D9.Device d3d9Device, D3D9.Pool ePool)
        {
            // Find the vertex buffer of this device.
            BufferResources bufferResources;

            if (this._mapDeviceToBufferResources.TryGetValue(d3d9Device, out bufferResources))
            {
                bufferResources.VertexBuffer.SafeDispose();
            }
            else
            {
                bufferResources = new BufferResources();
                this._mapDeviceToBufferResources.Add(d3d9Device, bufferResources);
            }

            bufferResources.VertexBuffer  = null;
            bufferResources.IsOutOfDate   = true;
            bufferResources.LockOffset    = 0;
            bufferResources.LockLength    = sizeInBytes;
            bufferResources.LockOptions   = BufferLocking.Normal;
            bufferResources.LastUsedFrame = Root.Instance.NextFrameNumber;

            // Create the vertex buffer
            try
            {
                bufferResources.VertexBuffer = new D3D9.VertexBuffer(d3d9Device, sizeInBytes, D3D9Helper.ConvertEnum(usage), 0, ePool);
            }
            catch (Exception ex)
            {
                throw new AxiomException("Cannot restore D3D9 vertex buffer", ex);
            }

            this._bufferDesc = bufferResources.VertexBuffer.Description;
        }
        protected PixelBox LockBuffer(BufferResources bufferResources, BasicBox lockBox, D3D9.LockFlags flags)
        {
            // Set extents and format
            // Note that we do not carry over the left/top/front here, since the returned
            // PixelBox will be re-based from the locking point onwards
            var rval = new PixelBox(lockBox.Width, lockBox.Height, lockBox.Depth, Format);

            if (bufferResources.Surface != null)
            {
                //Surface
                DX.DataRectangle lrect;                 // Filled in by D3D

                if (lockBox.Left == 0 && lockBox.Top == 0 && lockBox.Right == Width && lockBox.Bottom == Height)
                {
                    // Lock whole surface
                    lrect = bufferResources.Surface.LockRectangle(flags);
                }
                else
                {
                    var prect = ToD3DRectangle(lockBox);
                    lrect = bufferResources.Surface.LockRectangle(prect, flags);
                }

                FromD3DLock(rval, lrect);
            }
            else if (bufferResources.Volume != null)
            {
                // Volume
                var pbox = ToD3DBox(lockBox);                   // specify range to lock
                var lbox = bufferResources.Volume.LockBox(pbox, flags);
                FromD3DLock(rval, lbox);
            }

            return(rval);
        }
        public void Bind(D3D9.Device dev, D3D9.Volume volume, D3D9.BaseTexture mipTex)
        {
            //Entering critical section
            LockDeviceAccess();

            var bufferResources = GetBufferResources(dev);
            var isNewBuffer     = false;

            if (bufferResources == null)
            {
                bufferResources = new BufferResources();
                this.mapDeviceToBufferResources.Add(dev, bufferResources);
                isNewBuffer = true;
            }

            bufferResources.MipTex = mipTex;
            bufferResources.Volume = volume;

            var desc = volume.Description;

            width  = desc.Width;
            height = desc.Height;
            depth  = desc.Depth;
            format = D3D9Helper.ConvertEnum(desc.Format);
            // Default
            rowPitch    = Width;
            slicePitch  = Height * Width;
            sizeInBytes = PixelUtil.GetMemorySize(Width, Height, Depth, Format);

            if (isNewBuffer && this.ownerTexture.IsManuallyLoaded)
            {
                foreach (var it in this.mapDeviceToBufferResources)
                {
                    if (it.Value != bufferResources && it.Value.Volume != null && it.Key.TestCooperativeLevel().Success&&
                        dev.TestCooperativeLevel().Success)
                    {
                        var fullBufferBox = new BasicBox(0, 0, 0, Width, Height, Depth);
                        var dstBox        = new PixelBox(fullBufferBox, Format);

                        var data = new byte[sizeInBytes];
                        using (var d = BufferBase.Wrap(data))
                        {
                            dstBox.Data = d;
                            BlitToMemory(fullBufferBox, dstBox, it.Value, it.Key);
                            BlitFromMemory(dstBox, fullBufferBox, bufferResources);
                            Array.Clear(data, 0, sizeInBytes);
                        }
                        break;
                    }
                }
            }

            //Leaving critical section
            UnlockDeviceAccess();
        }
 protected void UnlockBuffer(BufferResources bufferResources)
 {
     if (bufferResources.Surface != null)
     {
         // Surface
         bufferResources.Surface.UnlockRectangle();
     }
     else if (bufferResources.Volume != null)
     {
         // Volume
         bufferResources.Volume.UnlockBox();
     }
 }
Example #6
0
        /// <summary>
        /// Updates buffer resources from system memory buffer.
        /// </summary>
        private bool _updateBufferResources(BufferBase systemMemoryBuffer, ref BufferResources bufferResources)
        {
            Contract.RequiresNotNull(bufferResources, "Cannot update BufferResources in D3D9HardwareIndexBuffer!");
            Contract.RequiresNotNull(bufferResources.IndexBuffer, "Cannot update BufferResources in D3D9HardwareIndexBuffer!");
            Contract.Requires(bufferResources.IsOutOfDate);

            DX.DataStream dstBytes;

            // Lock the buffer
            try
            {
                dstBytes = bufferResources.IndexBuffer.Lock(bufferResources.LockOffset, bufferResources.LockLength,
                                                            D3D9Helper.ConvertEnum(bufferResources.LockOptions, usage));
            }
            catch (Exception ex)
            {
                throw new AxiomException("Cannot lock D3D9 index buffer!", ex);
            }

            using (var src = systemMemoryBuffer + bufferResources.LockOffset)
            {
                using (var dest = BufferBase.Wrap(dstBytes.DataPointer, (int)dstBytes.Length))
                {
                    Memory.Copy(src, dest, bufferResources.LockLength);
                }
            }

            // Unlock the buffer.
            var hr = bufferResources.IndexBuffer.Unlock();

            if (hr.Failure)
            {
                throw new AxiomException("Cannot unlock D3D9 index buffer: {0}", hr.ToString());
            }

            bufferResources.IsOutOfDate = false;
            bufferResources.LockOffset  = sizeInBytes;
            bufferResources.LockLength  = 0;
            bufferResources.LockOptions = BufferLocking.Normal;

            return(true);
        }
		protected void Blit( D3D9.Device d3d9Device, HardwarePixelBuffer rsrc, BasicBox srcBox, BasicBox dstBox,
		                     BufferResources srcBufferResources, BufferResources dstBufferResources )
		{
			if ( dstBufferResources.Surface != null && srcBufferResources.Surface != null )
			{
				// Surface-to-surface
				var dsrcRect = ToD3DRectangle( srcBox );
				var ddestRect = ToD3DRectangle( dstBox );

				var srcDesc = srcBufferResources.Surface.Description;

				// If we're blitting from a RTT, try GetRenderTargetData
				// if we're going to try to use GetRenderTargetData, need to use system mem pool

				// romeoxbm: not used even in Ogre
				//var tryGetRenderTargetData = false;

				if ( ( srcDesc.Usage & D3D9.Usage.RenderTarget ) != 0 && srcDesc.MultiSampleType == D3D9.MultisampleType.None )
				{
					// Temp texture
					var tmptex = new D3D9.Texture( d3d9Device, srcDesc.Width, srcDesc.Height, 1,
					                               // 1 mip level ie topmost, generate no mipmaps
					                               0, srcDesc.Format, D3D9.Pool.SystemMemory );

					var tmpsurface = tmptex.GetSurfaceLevel( 0 );

					if ( d3d9Device.GetRenderTargetData( srcBufferResources.Surface, tmpsurface ).Success )
					{
						// Hey, it worked
						// Copy from this surface instead
						var res = D3D9.Surface.FromSurface( dstBufferResources.Surface, tmpsurface, D3D9.Filter.Default, 0, dsrcRect,
						                                    ddestRect );
						if ( res.Failure )
						{
							tmpsurface.SafeDispose();
							tmptex.SafeDispose();
							throw new AxiomException( "D3D9.Surface.FromSurface failed in D3D9HardwarePixelBuffer.Blit" );
						}
						tmpsurface.SafeDispose();
						tmptex.SafeDispose();
						return;
					}
				}

				// Otherwise, try the normal method
				var res2 = D3D9.Surface.FromSurface( dstBufferResources.Surface, srcBufferResources.Surface, D3D9.Filter.Default, 0,
				                                     dsrcRect, ddestRect );
				if ( res2.Failure )
				{
					throw new AxiomException( "D3D9.Surface.FromSurface failed in D3D9HardwarePixelBuffer.Blit" );
				}
			}
			else if ( dstBufferResources.Volume != null && srcBufferResources.Volume != null )
			{
				// Volume-to-volume
				var dsrcBox = ToD3DBox( srcBox );
				var ddestBox = ToD3DBox( dstBox );

				var res = D3D9.Volume.FromVolume( dstBufferResources.Volume, srcBufferResources.Volume, D3D9.Filter.Default, 0,
				                                  dsrcBox, ddestBox );
				if ( res.Failure )
				{
					throw new AxiomException( "D3D9.Volume.FromVolume failed in D3D9HardwarePixelBuffer.Blit" );
				}
			}
			else
			{
				// Software fallback
				base.Blit( rsrc, srcBox, dstBox );
			}
		}
		protected void UnlockBuffer( BufferResources bufferResources )
		{
			if ( bufferResources.Surface != null )
			{
				// Surface
				bufferResources.Surface.UnlockRectangle();
			}
			else if ( bufferResources.Volume != null )
			{
				// Volume
				bufferResources.Volume.UnlockBox();
			}
		}
		protected PixelBox LockBuffer( BufferResources bufferResources, BasicBox lockBox, D3D9.LockFlags flags )
		{
			// Set extents and format
			// Note that we do not carry over the left/top/front here, since the returned
			// PixelBox will be re-based from the locking point onwards
			var rval = new PixelBox( lockBox.Width, lockBox.Height, lockBox.Depth, Format );

			if ( bufferResources.Surface != null )
			{
				//Surface
				DX.DataRectangle lrect; // Filled in by D3D

				if ( lockBox.Left == 0 && lockBox.Top == 0 && lockBox.Right == Width && lockBox.Bottom == Height )
				{
					// Lock whole surface
					lrect = bufferResources.Surface.LockRectangle( flags );
				}
				else
				{
					var prect = ToD3DRectangle( lockBox );
					lrect = bufferResources.Surface.LockRectangle( prect, flags );
				}

				FromD3DLock( rval, lrect );
			}
			else if ( bufferResources.Volume != null )
			{
				// Volume
				var pbox = ToD3DBox( lockBox ); // specify range to lock
				var lbox = bufferResources.Volume.LockBox( pbox, flags );
				FromD3DLock( rval, lbox );
			}

			return rval;
		}
		public void Bind( D3D9.Device dev, D3D9.Volume volume, D3D9.BaseTexture mipTex )
		{
			//Entering critical section
			LockDeviceAccess();

			var bufferResources = GetBufferResources( dev );
			var isNewBuffer = false;

			if ( bufferResources == null )
			{
				bufferResources = new BufferResources();
				this.mapDeviceToBufferResources.Add( dev, bufferResources );
				isNewBuffer = true;
			}

			bufferResources.MipTex = mipTex;
			bufferResources.Volume = volume;

			var desc = volume.Description;
			width = desc.Width;
			height = desc.Height;
			depth = desc.Depth;
			format = D3D9Helper.ConvertEnum( desc.Format );
			// Default
			rowPitch = Width;
			slicePitch = Height*Width;
			sizeInBytes = PixelUtil.GetMemorySize( Width, Height, Depth, Format );

			if ( isNewBuffer && this.ownerTexture.IsManuallyLoaded )
			{
				foreach ( var it in this.mapDeviceToBufferResources )
				{
					if ( it.Value != bufferResources && it.Value.Volume != null && it.Key.TestCooperativeLevel().Success &&
					     dev.TestCooperativeLevel().Success )
					{
						var fullBufferBox = new BasicBox( 0, 0, 0, Width, Height, Depth );
						var dstBox = new PixelBox( fullBufferBox, Format );

						var data = new byte[sizeInBytes];
						using ( var d = BufferBase.Wrap( data ) )
						{
							dstBox.Data = d;
							BlitToMemory( fullBufferBox, dstBox, it.Value, it.Key );
							BlitFromMemory( dstBox, fullBufferBox, bufferResources );
							Array.Clear( data, 0, sizeInBytes );
						}
						break;
					}
				}
			}

			//Leaving critical section
			UnlockDeviceAccess();
		}
		/// <summary>
		/// Updates buffer resources from system memory buffer.
		/// </summary>
		private bool _updateBufferResources( BufferBase systemMemoryBuffer, ref BufferResources bufferResources )
		{
			Contract.RequiresNotNull( bufferResources, "Cannot update BufferResources in D3D9HardwareIndexBuffer!" );
			Contract.RequiresNotNull( bufferResources.IndexBuffer, "Cannot update BufferResources in D3D9HardwareIndexBuffer!" );
			Contract.Requires( bufferResources.IsOutOfDate );

			DX.DataStream dstBytes;

			// Lock the buffer
			try
			{
				dstBytes = bufferResources.IndexBuffer.Lock( bufferResources.LockOffset, bufferResources.LockLength,
				                                             D3D9Helper.ConvertEnum( bufferResources.LockOptions, usage ) );
			}
			catch ( Exception ex )
			{
				throw new AxiomException( "Cannot lock D3D9 index buffer!", ex );
			}

			using ( var src = systemMemoryBuffer + bufferResources.LockOffset )
			{
				using ( var dest = BufferBase.Wrap( dstBytes.DataPointer, (int)dstBytes.Length ) )
				{
					Memory.Copy( src, dest, bufferResources.LockLength );
				}
			}

			// Unlock the buffer.
			var hr = bufferResources.IndexBuffer.Unlock();
			if ( hr.Failure )
			{
				throw new AxiomException( "Cannot unlock D3D9 index buffer: {0}", hr.ToString() );
			}

			bufferResources.IsOutOfDate = false;
			bufferResources.LockOffset = sizeInBytes;
			bufferResources.LockLength = 0;
			bufferResources.LockOptions = BufferLocking.Normal;

			return true;
		}
        protected void BlitToMemory(BasicBox srcBox, PixelBox dst, BufferResources srcBufferResources, D3D9.Device d3d9Device)
        {
            // Decide on pixel format of temp surface
            PixelFormat tmpFormat = Format;

            if (D3D9Helper.ConvertEnum(dst.Format) != D3D9.Format.Unknown)
            {
                tmpFormat = dst.Format;
            }

            if (srcBufferResources.Surface != null)
            {
                Debug.Assert(srcBox.Depth == 1 && dst.Depth == 1);
                var srcDesc  = srcBufferResources.Surface.Description;
                var temppool = D3D9.Pool.Scratch;

                // if we're going to try to use GetRenderTargetData, need to use system mem pool
                var tryGetRenderTargetData = false;
                if (((srcDesc.Usage & D3D9.Usage.RenderTarget) != 0) && (srcBox.Width == dst.Width) &&
                    (srcBox.Height == dst.Height) && (srcBox.Width == Width) && (srcBox.Height == Height) &&
                    (Format == tmpFormat))
                {
                    tryGetRenderTargetData = true;
                    temppool = D3D9.Pool.SystemMemory;
                }

                // Create temp texture
                var tmp = new D3D9.Texture(d3d9Device, dst.Width, dst.Height, 1,                  // 1 mip level ie topmost, generate no mipmaps
                                           0, D3D9Helper.ConvertEnum(tmpFormat), temppool);

                var surface = tmp.GetSurfaceLevel(0);

                // Copy texture to this temp surface
                var srcRect  = ToD3DRectangle(srcBox);
                var destRect = ToD3DRectangle(dst);

                // Get the real temp surface format
                var dstDesc = surface.Description;
                tmpFormat = D3D9Helper.ConvertEnum(dstDesc.Format);

                // Use fast GetRenderTargetData if we are in its usage conditions
                var fastLoadSuccess = false;
                if (tryGetRenderTargetData)
                {
                    var result = d3d9Device.GetRenderTargetData(srcBufferResources.Surface, surface);
                    fastLoadSuccess = result.Success;
                }
                if (!fastLoadSuccess)
                {
                    var res = D3D9.Surface.FromSurface(surface, srcBufferResources.Surface, D3D9.Filter.Default, 0, srcRect, destRect);
                    if (res.Failure)
                    {
                        surface.SafeDispose();
                        tmp.SafeDispose();
                        throw new AxiomException("D3D9.Surface.FromSurface failed in D3D9HardwarePixelBuffer.BlitToMemory");
                    }
                }

                // Lock temp surface and copy it to memory
                var lrect = surface.LockRectangle(D3D9.LockFlags.ReadOnly);

                // Copy it
                var locked = new PixelBox(dst.Width, dst.Height, dst.Depth, tmpFormat);
                FromD3DLock(locked, lrect);
                PixelConverter.BulkPixelConversion(locked, dst);
                surface.UnlockRectangle();
                // Release temporary surface and texture
                surface.SafeDispose();
                tmp.SafeDispose();
            }
            else if (srcBufferResources.Volume != null)
            {
                // Create temp texture
                var tmp = new D3D9.VolumeTexture(d3d9Device, dst.Width, dst.Height, dst.Depth, 0, 0,
                                                 D3D9Helper.ConvertEnum(tmpFormat), D3D9.Pool.Scratch);

                var surface = tmp.GetVolumeLevel(0);

                // Volume
                var ddestBox = ToD3DBoxExtent(dst);
                var dsrcBox  = ToD3DBox(srcBox);

                var res = D3D9.Volume.FromVolume(surface, srcBufferResources.Volume, D3D9.Filter.Default, 0, dsrcBox, ddestBox);
                if (res.Failure)
                {
                    surface.SafeDispose();
                    tmp.SafeDispose();
                    throw new AxiomException("D3D9.Surface.FromVolume failed in D3D9HardwarePixelBuffer.BlitToMemory");
                }

                // Lock temp surface and copy it to memory
                var lbox = surface.LockBox(D3D9.LockFlags.ReadOnly);                   // Filled in by D3D

                // Copy it
                var locked = new PixelBox(dst.Width, dst.Height, dst.Depth, tmpFormat);
                FromD3DLock(locked, lbox);
                PixelConverter.BulkPixelConversion(locked, dst);
                surface.UnlockBox();
                // Release temporary surface and texture
                surface.SafeDispose();
                tmp.SafeDispose();
            }
        }
        protected void BlitFromMemory(PixelBox src, BasicBox dstBox, BufferResources dstBufferResources)
        {
            // for scoped deletion of conversion buffer
            var converted = src;
            var bufSize   = 0;

            // convert to pixelbuffer's native format if necessary
            if (D3D9Helper.ConvertEnum(src.Format) == D3D9.Format.Unknown)
            {
                bufSize = PixelUtil.GetMemorySize(src.Width, src.Height, src.Depth, Format);
                var newBuffer = new byte[bufSize];
                using (var data = BufferBase.Wrap(newBuffer))
                {
                    converted = new PixelBox(src.Width, src.Height, src.Depth, Format, data);
                }
                PixelConverter.BulkPixelConversion(src, converted);
            }

            int rowWidth = 0;

            if (PixelUtil.IsCompressed(converted.Format))
            {
                rowWidth = converted.RowPitch / 4;
                // D3D wants the width of one row of cells in bytes
                if (converted.Format == PixelFormat.DXT1)
                {
                    // 64 bits (8 bytes) per 4x4 block
                    rowWidth *= 8;
                }
                else
                {
                    // 128 bits (16 bytes) per 4x4 block
                    rowWidth *= 16;
                }
            }
            else
            {
                rowWidth = converted.RowPitch * PixelUtil.GetNumElemBytes(converted.Format);
            }

            if (dstBufferResources.Surface != null)
            {
                var srcRect  = ToD3DRectangle(converted);
                var destRect = ToD3DRectangle(dstBox);

                bufSize = PixelUtil.GetMemorySize(converted.Width, converted.Height, converted.Depth, converted.Format);
                var data = new byte[bufSize];
                using (var dest = BufferBase.Wrap(data))
                {
                    Memory.Copy(converted.Data, dest, bufSize);
                }

                try
                {
                    D3D9.Surface.FromMemory(dstBufferResources.Surface, data, D3D9.Filter.Default, 0,
                                            D3D9Helper.ConvertEnum(converted.Format), rowWidth, srcRect, destRect);
                }
                catch (Exception e)
                {
                    throw new AxiomException("D3D9.Surface.FromMemory failed in D3D9HardwarePixelBuffer.BlitFromMemory", e);
                }
            }
            else if (dstBufferResources.Volume != null)
            {
                var srcBox     = ToD3DBox(converted);
                var destBox    = ToD3DBox(dstBox);
                var sliceWidth = 0;
                if (PixelUtil.IsCompressed(converted.Format))
                {
                    sliceWidth = converted.SlicePitch / 16;
                    // D3D wants the width of one slice of cells in bytes
                    if (converted.Format == PixelFormat.DXT1)
                    {
                        // 64 bits (8 bytes) per 4x4 block
                        sliceWidth *= 8;
                    }
                    else
                    {
                        // 128 bits (16 bytes) per 4x4 block
                        sliceWidth *= 16;
                    }
                }
                else
                {
                    sliceWidth = converted.SlicePitch * PixelUtil.GetNumElemBytes(converted.Format);
                }

                bufSize = PixelUtil.GetMemorySize(converted.Width, converted.Height, converted.Depth, converted.Format);
                var data = new byte[bufSize];
                using (var dest = BufferBase.Wrap(data))
                {
                    Memory.Copy(converted.Data, dest, bufSize);
                }

                //TODO note sliceWidth and rowWidth are ignored..
                D3D9.ImageInformation info;
                try
                {
                    //D3D9.D3DX9.LoadVolumeFromMemory() not accessible 'cause D3D9.D3DX9 static class is not public
                    D3D9.Volume.FromFileInMemory(dstBufferResources.Volume, data, D3D9.Filter.Default, 0, srcBox, destBox, null,
                                                 out info);
                }
                catch (Exception e)
                {
                    throw new AxiomException("D3D9.Volume.FromFileInMemory failed in D3D9HardwarePixelBuffer.BlitFromMemory", e);
                }
            }

            if (this.doMipmapGen)
            {
                GenMipmaps(dstBufferResources.MipTex);
            }
        }
		protected void BlitFromMemory( PixelBox src, BasicBox dstBox, BufferResources dstBufferResources )
		{
			// for scoped deletion of conversion buffer
			var converted = src;
			var bufSize = 0;

			// convert to pixelbuffer's native format if necessary
			if ( D3D9Helper.ConvertEnum( src.Format ) == D3D9.Format.Unknown )
			{
				bufSize = PixelUtil.GetMemorySize( src.Width, src.Height, src.Depth, Format );
				var newBuffer = new byte[bufSize];
				using ( var data = BufferBase.Wrap( newBuffer ) )
				{
					converted = new PixelBox( src.Width, src.Height, src.Depth, Format, data );
				}
				PixelConverter.BulkPixelConversion( src, converted );
			}

			int rowWidth = 0;
			if ( PixelUtil.IsCompressed( converted.Format ) )
			{
				rowWidth = converted.RowPitch/4;
				// D3D wants the width of one row of cells in bytes
				if ( converted.Format == PixelFormat.DXT1 )
				{
					// 64 bits (8 bytes) per 4x4 block
					rowWidth *= 8;
				}
				else
				{
					// 128 bits (16 bytes) per 4x4 block
					rowWidth *= 16;
				}
			}
			else
			{
				rowWidth = converted.RowPitch*PixelUtil.GetNumElemBytes( converted.Format );
			}

			if ( dstBufferResources.Surface != null )
			{
				var srcRect = ToD3DRectangle( converted );
				var destRect = ToD3DRectangle( dstBox );

				bufSize = PixelUtil.GetMemorySize( converted.Width, converted.Height, converted.Depth, converted.Format );
				var data = new byte[bufSize];
				using ( var dest = BufferBase.Wrap( data ) )
				{
					Memory.Copy( converted.Data, dest, bufSize );
				}

				try
				{
					D3D9.Surface.FromMemory( dstBufferResources.Surface, data, D3D9.Filter.Default, 0,
					                         D3D9Helper.ConvertEnum( converted.Format ), rowWidth, srcRect, destRect );
				}
				catch ( Exception e )
				{
					throw new AxiomException( "D3D9.Surface.FromMemory failed in D3D9HardwarePixelBuffer.BlitFromMemory", e );
				}
			}
			else if ( dstBufferResources.Volume != null )
			{
				var srcBox = ToD3DBox( converted );
				var destBox = ToD3DBox( dstBox );
				var sliceWidth = 0;
				if ( PixelUtil.IsCompressed( converted.Format ) )
				{
					sliceWidth = converted.SlicePitch/16;
					// D3D wants the width of one slice of cells in bytes
					if ( converted.Format == PixelFormat.DXT1 )
					{
						// 64 bits (8 bytes) per 4x4 block
						sliceWidth *= 8;
					}
					else
					{
						// 128 bits (16 bytes) per 4x4 block
						sliceWidth *= 16;
					}
				}
				else
				{
					sliceWidth = converted.SlicePitch*PixelUtil.GetNumElemBytes( converted.Format );
				}

				bufSize = PixelUtil.GetMemorySize( converted.Width, converted.Height, converted.Depth, converted.Format );
                var data = new byte[ bufSize ];
				using ( var dest = BufferBase.Wrap( data ) )
				{
					Memory.Copy( converted.Data, dest, bufSize );
				}

				try
				{
                    using ( var srcData = BufferBase.Wrap( data ) )
                    {
                        var srcMemoryPtr = new IntPtr( srcData.Ptr );
                        dstBufferResources.Volume.LoadFromMemory( null, destBox, srcMemoryPtr, D3D9Helper.ConvertEnum( converted.Format ),
                            rowWidth, slicePitch, null, srcBox, D3D9.Filter.Default, 0 );
                    }
				}
				catch ( Exception e )
				{
					throw new AxiomException( "D3D9.Volume.FromFileInMemory failed in D3D9HardwarePixelBuffer.BlitFromMemory", e );
				}
			}

			if ( this.doMipmapGen )
			{
				GenMipmaps( dstBufferResources.MipTex );
			}
		}
		public void CreateBuffer( D3D9.Device d3d9Device, D3D9.Pool ePool )
		{
			//Entering critical section
			this.LockDeviceAccess();

			BufferResources bufferResources;

			// Find the vertex buffer of this device.
			if ( this._mapDeviceToBufferResources.TryGetValue( d3d9Device, out bufferResources ) )
			{
				bufferResources.IndexBuffer.SafeDispose();
			}
			else
			{
				bufferResources = new BufferResources();
				this._mapDeviceToBufferResources.Add( d3d9Device, bufferResources );
			}

			bufferResources.IndexBuffer = null;
			bufferResources.IsOutOfDate = true;
			bufferResources.LockOffset = 0;
			bufferResources.LockLength = sizeInBytes;
			bufferResources.LockOptions = BufferLocking.Normal;
			bufferResources.LastUsedFrame = Root.Instance.NextFrameNumber;

			// Create the Index buffer
			try
			{
				bufferResources.IndexBuffer = new D3D9.IndexBuffer( d3d9Device, sizeInBytes, D3D9Helper.ConvertEnum( usage ), ePool,
				                                                    D3D9Helper.ConvertEnum( type ) );
			}
			catch ( Exception ex )
			{
				throw new AxiomException( "Cannot create D3D9 Index buffer", ex );
			}

			this._bufferDesc = bufferResources.IndexBuffer.Description;

			//Leaving critical section
			this.UnlockDeviceAccess();
		}
		protected void BlitToMemory( BasicBox srcBox, PixelBox dst, BufferResources srcBufferResources, D3D9.Device d3d9Device )
		{
			// Decide on pixel format of temp surface
			PixelFormat tmpFormat = Format;
			if ( D3D9Helper.ConvertEnum( dst.Format ) != D3D9.Format.Unknown )
			{
				tmpFormat = dst.Format;
			}

			if ( srcBufferResources.Surface != null )
			{
				Debug.Assert( srcBox.Depth == 1 && dst.Depth == 1 );
				var srcDesc = srcBufferResources.Surface.Description;
				var temppool = D3D9.Pool.Scratch;

				// if we're going to try to use GetRenderTargetData, need to use system mem pool
				var tryGetRenderTargetData = false;
				if ( ( ( srcDesc.Usage & D3D9.Usage.RenderTarget ) != 0 ) && ( srcBox.Width == dst.Width ) &&
				     ( srcBox.Height == dst.Height ) && ( srcBox.Width == Width ) && ( srcBox.Height == Height ) &&
				     ( Format == tmpFormat ) )
				{
					tryGetRenderTargetData = true;
					temppool = D3D9.Pool.SystemMemory;
				}

				// Create temp texture
				var tmp = new D3D9.Texture( d3d9Device, dst.Width, dst.Height, 1, // 1 mip level ie topmost, generate no mipmaps
				                            0, D3D9Helper.ConvertEnum( tmpFormat ), temppool );

				var surface = tmp.GetSurfaceLevel( 0 );

				// Copy texture to this temp surface
				var srcRect = ToD3DRectangle( srcBox );
				var destRect = ToD3DRectangle( dst );

				// Get the real temp surface format
				var dstDesc = surface.Description;
				tmpFormat = D3D9Helper.ConvertEnum( dstDesc.Format );

				// Use fast GetRenderTargetData if we are in its usage conditions
				var fastLoadSuccess = false;
				if ( tryGetRenderTargetData )
				{
					var result = d3d9Device.GetRenderTargetData( srcBufferResources.Surface, surface );
					fastLoadSuccess = result.Success;
				}
				if ( !fastLoadSuccess )
				{
					var res = D3D9.Surface.FromSurface( surface, srcBufferResources.Surface, D3D9.Filter.Default, 0, srcRect, destRect );
					if ( res.Failure )
					{
						surface.SafeDispose();
						tmp.SafeDispose();
						throw new AxiomException( "D3D9.Surface.FromSurface failed in D3D9HardwarePixelBuffer.BlitToMemory" );
					}
				}

				// Lock temp surface and copy it to memory
				var lrect = surface.LockRectangle( D3D9.LockFlags.ReadOnly );

				// Copy it
				var locked = new PixelBox( dst.Width, dst.Height, dst.Depth, tmpFormat );
				FromD3DLock( locked, lrect );
				PixelConverter.BulkPixelConversion( locked, dst );
				surface.UnlockRectangle();
				// Release temporary surface and texture
				surface.SafeDispose();
				tmp.SafeDispose();
			}
			else if ( srcBufferResources.Volume != null )
			{
				// Create temp texture
				var tmp = new D3D9.VolumeTexture( d3d9Device, dst.Width, dst.Height, dst.Depth, 0, 0,
				                                  D3D9Helper.ConvertEnum( tmpFormat ), D3D9.Pool.Scratch );

				var surface = tmp.GetVolumeLevel( 0 );

				// Volume
				var ddestBox = ToD3DBoxExtent( dst );
				var dsrcBox = ToD3DBox( srcBox );

				var res = D3D9.Volume.FromVolume( surface, srcBufferResources.Volume, D3D9.Filter.Default, 0, dsrcBox, ddestBox );
				if ( res.Failure )
				{
					surface.SafeDispose();
					tmp.SafeDispose();
					throw new AxiomException( "D3D9.Surface.FromVolume failed in D3D9HardwarePixelBuffer.BlitToMemory" );
				}

				// Lock temp surface and copy it to memory
				var lbox = surface.LockBox( D3D9.LockFlags.ReadOnly ); // Filled in by D3D

				// Copy it
				var locked = new PixelBox( dst.Width, dst.Height, dst.Depth, tmpFormat );
				FromD3DLock( locked, lbox );
				PixelConverter.BulkPixelConversion( locked, dst );
				surface.UnlockBox();
				// Release temporary surface and texture
				surface.SafeDispose();
				tmp.SafeDispose();
			}
		}
		public void CreateBuffer( D3D9.Device d3d9Device, D3D9.Pool ePool )
		{
			// Find the vertex buffer of this device.
			BufferResources bufferResources;
			if ( this._mapDeviceToBufferResources.TryGetValue( d3d9Device, out bufferResources ) )
			{
				bufferResources.VertexBuffer.SafeDispose();
			}
			else
			{
				bufferResources = new BufferResources();
				this._mapDeviceToBufferResources.Add( d3d9Device, bufferResources );
			}

			bufferResources.VertexBuffer = null;
			bufferResources.IsOutOfDate = true;
			bufferResources.LockOffset = 0;
			bufferResources.LockLength = sizeInBytes;
			bufferResources.LockOptions = BufferLocking.Normal;
			bufferResources.LastUsedFrame = Root.Instance.NextFrameNumber;

			// Create the vertex buffer
			try
			{
				bufferResources.VertexBuffer = new D3D9.VertexBuffer( d3d9Device, sizeInBytes, D3D9Helper.ConvertEnum( usage ), 0,
				                                                      // No FVF here, thank you.
				                                                      ePool );
			}
			catch ( Exception ex )
			{
				throw new AxiomException( "Cannot restore D3D9 vertex buffer", ex );
			}

			this._bufferDesc = bufferResources.VertexBuffer.Description;
		}