public PixelBox(BasicBox extents, PixelFormat format) { CopyFromBasicBox(extents); this.format = format; this.offset = 0; SetConsecutive(); }
/// <summary> /// Return a subvolume of this PixelBox. /// </summary> /// <param name="def"> Defines the bounds of the subregion to return </param> /// <returns> A pixel box describing the region and the data in it </returns> /// <remarks> /// This function does not copy any data, it just returns a PixelBox object with a data pointer pointing somewhere inside the data of object. Throws an Exception if def is not fully contained. /// </remarks> public PixelBox GetSubVolume(BasicBox def) { if (Compressed(this.format)) { if (def.Left == left && def.Top == top && def.Front == front && def.Right == right && def.Bottom == bottom && def.Back == back) { // Entire buffer is being queried return(this); } throw new Exception("Cannot return subvolume of compressed PixelBuffer, in PixelBox.GetSubVolume"); } if (!Contains(def)) { throw new Exception("Bounds out of range, in PixelBox.GetSubVolume"); } var elemSize = PixelUtil.GetNumElemBytes(this.format); // Calculate new data origin var rval = new PixelBox(def, this.format, this.data); rval.offset = (((def.Left - left) * elemSize) + ((def.Top - top) * this.rowPitch * elemSize) + ((def.Front - front) * this.slicePitch * elemSize)); rval.rowPitch = this.rowPitch; rval.slicePitch = this.slicePitch; rval.format = this.format; return(rval); }
///<summary> /// Constructor providing extents in the form of a Box object. This constructor assumes the pixel data is laid out consecutively in memory. (this means row after row, slice after slice, with no space in between) ///</summary> ///<param name="extents"> Extents of the region defined by data </param> ///<param name="format"> Format of this buffer </param> ///<param name="data"> Pointer to the actual data </param> internal PixelBox(BasicBox extents, PixelFormat format, BufferBase data) { CopyFromBasicBox(extents); this.format = format; this.data = data; this.offset = 0; SetConsecutive(); }
///<summary> /// Constructor providing extents in the form of a Box object. This constructor /// assumes the pixel data is laid out consecutively in memory. (this /// means row after row, slice after slice, with no space in between) ///</summary> ///<param name="extents">Extents of the region defined by data</param> ///<param name="ormat">Format of this buffer</param> ///<param name="data">Pointer to the actual data</param> protected PixelBox(BasicBox extents, PixelFormat format, IntPtr data) { CopyFromBasicBox(extents); this.format = format; this.data = data; this.offset = 0; SetConsecutive(); }
public void CopyFromBasicBox(BasicBox src) { this.left = src.left; this.top = src.top; this.front = src.front; this.right = src.right; this.bottom = src.bottom; this.back = src.back; }
public void CopyFromBasicBox(BasicBox src) { left = src.left; top = src.top; front = src.front; right = src.right; bottom = src.bottom; back = src.back; }
public override void BlitToMemory( BasicBox srcBox, PixelBox dst ) { //Entering critical section LockDeviceAccess(); var pair = this.mapDeviceToBufferResources.First(); BlitToMemory( srcBox, dst, pair.Value, pair.Key ); //Leaving critical section UnlockDeviceAccess(); }
///<summary> /// Copies a region from normal memory to a region of this pixelbuffer. The source /// image can be in any pixel format supported by Axiom, and in any size. ///</summary> ///<param name="src">PixelBox containing the source pixels and format in memory</param> ///<param name="dstBox">Image.BasicBox describing the destination region in this buffer</param> ///<remarks> /// The source and destination regions dimensions don't have to match, in which /// case scaling is done. This scaling is generally done using a bilinear filter in hardware, /// but it is faster to pass the source image in the right dimensions. /// Only call this function when both buffers are unlocked. ///</remarks> public override void BlitFromMemory( PixelBox src, BasicBox dstBox ) { var converted = src; var bufGCHandle = new GCHandle(); var bufSize = 0; // Get src.Data as byte[] bufSize = PixelUtil.GetMemorySize( src.Width, src.Height, src.Depth, Format ); var newBuffer = new byte[bufSize]; //bufGCHandle = GCHandle.Alloc( newBuffer, GCHandleType.Pinned ); //XnaHelper.Convert(XFG.SurfaceFormat) would never have returned SurfaceFormat.Unknown anyway... //if (XnaHelper.Convert(src.Format) != XFG.SurfaceFormat.Unknown) { converted = new PixelBox( src.Width, src.Height, src.Depth, Format, BufferBase.Wrap( newBuffer ) ); PixelConverter.BulkPixelConversion( src, converted ); } //else //{ // Memory.Copy(converted.Data, BufferBase.Wrap(newBuffer), bufSize); //} if ( surface != null ) { surface.SetData( mipLevel, XnaHelper.ToRectangle( dstBox ), newBuffer, 0, bufSize ); } else if ( cube != null ) { cube.SetData( face, mipLevel, XnaHelper.ToRectangle( dstBox ), newBuffer, 0, bufSize ); } else { throw new NotSupportedException( "BlitFromMemory on Volume Textures not supported." ); } // If we allocated a buffer for the temporary conversion, free it here if ( bufGCHandle.IsAllocated ) bufGCHandle.Free(); if ( doMipmapGen ) GenMipmaps(); }
public override void Blit( HardwarePixelBuffer rsrc, BasicBox srcBox, BasicBox dstBox ) { //Entering critical section LockDeviceAccess(); var _src = (D3D9HardwarePixelBuffer)rsrc; foreach ( var it in this.mapDeviceToBufferResources ) { var srcBufferResources = ( (D3D9HardwarePixelBuffer)rsrc ).GetBufferResources( it.Key ); var dstBufferResources = it.Value; if ( srcBufferResources == null ) { throw new AxiomException( "There are no matching resources attached to the source pixel buffer !!" ); } Blit( it.Key, rsrc, srcBox, dstBox, srcBufferResources, dstBufferResources ); } //Leaving critical section UnlockDeviceAccess(); }
public override void BlitFromMemory( PixelBox src, BasicBox dstBox ) { //Entering critical section LockDeviceAccess(); foreach ( var it in this.mapDeviceToBufferResources ) { BlitFromMemory( src, dstBox, it.Value ); } //Leaving critical section UnlockDeviceAccess(); }
protected static System.Drawing.Rectangle ToD3DRectangle( BasicBox lockBox ) { Debug.Assert( lockBox.Depth == 1 ); var r = new System.Drawing.Rectangle(); r.X = lockBox.Left; r.Width = lockBox.Width; r.Y = lockBox.Top; r.Height = lockBox.Height; return r; }
protected override PixelBox LockImpl( BasicBox lockBox, BufferLocking options ) { //Entering critical section LockDeviceAccess(); // Check for misuse if ( ( (int)usage & (int)TextureUsage.RenderTarget ) != 0 ) { throw new AxiomException( "DirectX does not allow locking of or directly writing to RenderTargets. Use BlitFromMemory if you need the contents." ); } // Set locking flags according to options var flags = D3D9Helper.ConvertEnum( options, usage ); if ( this.mapDeviceToBufferResources.Count == 0 ) { throw new AxiomException( "There are no resources attached to this pixel buffer !!" ); } lockedBox = lockBox; this.lockFlags = flags; var bufferResources = this.mapDeviceToBufferResources.First().Value; // Lock the source buffer. var lockedBuf = LockBuffer( bufferResources, lockBox, flags ); //Leaving critical section UnlockDeviceAccess(); return lockedBuf; }
/// <summary> /// /// </summary> /// <param name="data"></param> /// <param name="dest"></param> protected virtual void Upload( PixelBox data, BasicBox dest ) { throw new AxiomException( "Upload not possible for this pixelbuffer type" ); }
/// <summary> /// /// </summary> /// <param name="srcBox"></param> /// <param name="dst"></param> public override void BlitToMemory( BasicBox srcBox, PixelBox dst ) { if ( !_buffer.Contains( srcBox ) ) { throw new ArgumentOutOfRangeException( "source boux out of range" ); } if ( srcBox.Left == 0 && srcBox.Right == Width && srcBox.Top == 0 && srcBox.Bottom == Height && srcBox.Front == 0 && srcBox.Back == Depth && dst.Width == Width && dst.Height == Height && dst.Depth == Depth && GLESPixelUtil.GetGLOriginFormat( dst.Format ) != 0 ) { // The direct case: the user wants the entire texture in a format supported by GL // so we don't need an intermediate buffer Download( dst ); } else { // Use buffer for intermediate copy AllocateBuffer(); //download entire buffer Download( _buffer ); if ( srcBox.Width != dst.Width || srcBox.Height != dst.Height || srcBox.Depth != dst.Depth ) { // we need scaling Image.Scale( _buffer.GetSubVolume( srcBox ), dst, ImageFilter.Bilinear ); } else { // Just copy the bit that we need PixelConverter.BulkPixelConversion( _buffer.GetSubVolume( srcBox ), dst ); } FreeBuffer(); } }
public override void BlitFromMemory( PixelBox src, BasicBox dstBox ) { // Fall back to normal GLHardwarePixelBuffer::blitFromMemory in case // - FBO is not supported // - Either source or target is luminance due doesn't looks like supported by hardware // - the source dimensions match the destination ones, in which case no scaling is needed //Ogre TODO: Check that extension is NOT available if ( PixelUtil.IsLuminance( src.Format ) || PixelUtil.IsLuminance( this.format ) || ( src.Width == dstBox.Width && src.Height == dstBox.Height && src.Depth == dstBox.Depth ) ) { base.BlitFromMemory( src, dstBox ); return; } if ( !Buffer.Contains( dstBox ) ) { throw new ArgumentOutOfRangeException( "dstBox", "Destination box out of range" ); } //For scoped deletion of conversion buffer PixelBox srcPB; BufferBase buf; //first, convert the srcbox to a OpenGL compatible pixel format if ( GLES2PixelUtil.GetGLOriginFormat( src.Format ) == 0 ) { //Conver to buffer intenral format buf = BufferBase.Wrap( new byte[ PixelUtil.GetMemorySize( src.Width, src.Height, src.Depth, this.format ) ] ); srcPB = new PixelBox( src.Width, src.Height, src.Depth, this.format, buf ); PixelConverter.BulkPixelConversion( src, srcPB ); } else { //No conversion needed srcPB = src; } //Create temporary texture to store source data int id = 0; All target = All.Texture2D; int width = GLES2PixelUtil.OptionalPO2( src.Width ); int height = GLES2PixelUtil.OptionalPO2( src.Height ); All format = GLES2PixelUtil.GetClosestGLInternalFormat( src.Format ); All datatype = GLES2PixelUtil.GetGLOriginDataType( src.Format ); //Generate texture name GL.GenTextures( 1, ref id ); GLES2Config.GlCheckError( this ); //Set texture type GL.BindTexture( target, id ); GLES2Config.GlCheckError( this ); //Allocate texture memory GL.TexImage2D( target, 0, (int) format, width, height, 0, format, datatype, IntPtr.Zero ); GLES2Config.GlCheckError( this ); var tex = new GLES2TextureBuffer( string.Empty, target, id, width, height, format, (All) src.Format, 0, 0, BufferUsage.StaticWriteOnly, false, false, 0 ); //Upload data to 0,0,0 in temprary texture var tempTarget = new BasicBox( 0, 0, 0, srcPB.Width, srcPB.Height, srcPB.Depth ); tex.Upload( srcPB, tempTarget ); //Blit this.BlitFromTexture( tex, tempTarget, dstBox ); GLES2Config.GlCheckError( this ); }
///<summary> /// // Very fast texture-to-texture blitter and hardware bi/trilinear scaling implementation using FBO Destination texture must be 1D, 2D, 3D, or Cube Source texture must be 1D, 2D or 3D Supports compressed formats as both source and destination format, it will use the hardware DXT compressor if available. @author W.J. van der Laan ///</summary> ///<param name="src"> </param> ///<param name="srcBox"> </param> ///<param name="dstBox"> </param> private void BlitFromTexture( GLES2TextureBuffer src, BasicBox srcBox, BasicBox dstBox ) { /*Port notes * Ogre immediately returns void, yet much code is provided below * The remaining code will ported if/when Ogre makes use of it */ return; //Ogre todo add a shader attach... }
///<summary> /// Return true if the other box is a part of this one ///</summary> public bool Contains(BasicBox def) { return(def.Left >= this.left && def.top >= this.top && def.front >= this.front && def.right <= this.right && def.bottom <= this.bottom && def.back <= this.back); }
///<summary> /// Copies a region of this pixelbuffer to normal memory. ///</summary> ///<param name="srcBox">BasicBox describing the source region of this buffer</param> ///<param name="dst">PixelBox describing the destination pixels and format in memory</param> ///<remarks> /// The source and destination regions don't have to match, in which /// case scaling is done. /// Only call this function when the buffer is unlocked. ///</remarks> public override void BlitToMemory( BasicBox srcBox, PixelBox dst ) { }
/** Return a subvolume of this PixelBox. @param def Defines the bounds of the subregion to return @returns A pixel box describing the region and the data in it @remarks This function does not copy any data, it just returns a PixelBox object with a data pointer pointing somewhere inside the data of object. @throws Exception(ERR_INVALIDPARAMS) if def is not fully contained */ public PixelBox GetSubVolume(BasicBox def) { if(Compressed(format)) { if(def.Left == left && def.Top == top && def.Front == front && def.Right == right && def.Bottom == bottom && def.Back == back) // Entire buffer is being queried return this; throw new Exception("Cannot return subvolume of compressed PixelBuffer, in PixelBox.GetSubVolume"); } if(!Contains(def)) throw new Exception("Bounds out of range, in PixelBox.GetSubVolume"); int elemSize = PixelUtil.GetNumElemBytes(format); // Calculate new data origin PixelBox rval = new PixelBox(def, format, data); rval.offset = (((def.Left - left)*elemSize) + ((def.Top - top)*rowPitch*elemSize) + ((def.Front - front)*slicePitch*elemSize)); rval.rowPitch = rowPitch; rval.slicePitch = slicePitch; rval.format = format; return rval; }
///<summary> /// Internal implementation of <see cref="HardwareBuffer.Lock"/>. ///</summary> protected override PixelBox LockImpl( BasicBox lockBox, BufferLocking options ) { _lockedBox = lockBox; // Set extents and format var rval = new PixelBox( lockBox, Format ); var sizeInBytes = PixelUtil.GetMemorySize( lockBox.Width, lockBox.Height, lockBox.Depth, XnaHelper.Convert( surface.Format ) ); if ( _bufferBytes == null || _bufferBytes.Length != sizeInBytes ) { _bufferBytes = new byte[sizeInBytes]; #if !SILVERLIGHT if ( surface != null ) surface.GetData( mipLevel, XnaHelper.ToRectangle( lockBox ), _bufferBytes, 0, _bufferBytes.Length ); else if ( cube != null ) cube.GetData( face, mipLevel, XnaHelper.ToRectangle( lockBox ), _bufferBytes, 0, _bufferBytes.Length ); else volume.GetData( mipLevel, lockBox.Left, lockBox.Top, lockBox.Right, lockBox.Bottom, lockBox.Front, lockBox.Back, _bufferBytes, 0, _bufferBytes.Length ); #endif } rval.Data = BufferBase.Wrap( _bufferBytes ); return rval; }
/// <summary> /// /// </summary> /// <param name="lockBox"></param> /// <param name="options"></param> /// <returns></returns> protected override PixelBox LockImpl( BasicBox lockBox, BufferLocking options ) { AllocateBuffer(); if ( options != BufferLocking.Discard && ( Usage & BufferUsage.WriteOnly ) == 0 ) { // Download the old contents of the texture Download( _buffer ); } _currentLocking = options; return _buffer.GetSubVolume( lockBox ); }
protected abstract PixelBox LockImpl( BasicBox lockBox, BufferLocking options );
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(); }
public abstract void BlitFromMemory( PixelBox src, BasicBox dstBox );
protected static D3D9.Box ToD3DBox( BasicBox lockBox ) { var pbox = new D3D9.Box(); pbox.Left = lockBox.Left; pbox.Right = lockBox.Right; pbox.Top = lockBox.Top; pbox.Bottom = lockBox.Bottom; pbox.Front = lockBox.Front; pbox.Back = lockBox.Back; return pbox; }
public abstract void BlitToMemory( BasicBox srcBox, PixelBox dst );
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; }
protected override BufferBase LockImpl( int offset, int length, BufferLocking options ) { Debug.Assert( !IsLocked, "Cannot lock this buffer, it is already locked!" ); Debug.Assert( offset == 0 && length == sizeInBytes, "Cannot lock memory region, must lock box or entire buffer" ); var myBox = new BasicBox( 0, 0, 0, Width, Height, Depth ); var rv = Lock( myBox, options ); return rv.Data; }
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 ); } }
public virtual PixelBox Lock( BasicBox lockBox, BufferLocking options ) { if ( useShadowBuffer ) { if ( options != BufferLocking.ReadOnly ) { // we have to assume a read / write lock so we use the shadow buffer // and tag for sync on unlock() shadowUpdated = true; } this.currentLock = ( (HardwarePixelBuffer)shadowBuffer ).Lock( lockBox, options ); } else { // Lock the real buffer if there is no shadow buffer this.currentLock = LockImpl( lockBox, options ); isLocked = true; } return this.currentLock; }
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 virtual void Blit( HardwarePixelBuffer src, BasicBox srcBox, BasicBox dstBox ) { if ( IsLocked || src.IsLocked ) { throw new AxiomException( "Source and destination buffer may not be locked!" ); } if ( src == this ) { throw new AxiomException( "Source must not be the same object." ); } var srclock = src.Lock( srcBox, BufferLocking.ReadOnly ); var method = BufferLocking.Normal; if ( dstBox.Left == 0 && dstBox.Top == 0 && dstBox.Front == 0 && dstBox.Right == this.width && dstBox.Bottom == this.height && dstBox.Back == this.depth ) { // Entire buffer -- we can discard the previous contents method = BufferLocking.Discard; } var dstlock = Lock( dstBox, method ); if ( dstlock.Width != srclock.Width || dstlock.Height != srclock.Height || dstlock.Depth != srclock.Depth ) { // Scaling desired Image.Scale( srclock, dstlock ); } else { // No scaling needed PixelConverter.BulkPixelConversion( srclock, dstlock ); } Unlock(); src.Unlock(); }
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(); } }
///<summary> /// Return true if the other box is a part of this one ///</summary> public bool Contains(BasicBox def) { return (def.Left >= left && def.top >= top && def.front >= front && def.right <= right && def.bottom <= bottom && def.back <= back); }