public override void WriteData(int offset, int length, BufferBase src, bool discardWholeBuffer)
        {
            Debug.Assert((offset + length) <= base.sizeInBytes);

            using (var pIntData = BufferBase.Wrap(_mpData, length).Offset(offset))
                Memory.Copy(src, pIntData, length);
        }
Esempio n. 2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="val"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public void Write(System.Array val, int offset, int count)
        {
            // can't write to unlocked buffers
            if (!this.owner.IsLocked)
            {
                throw new AxiomException("Cannot write to a buffer stream when the buffer is not locked.");
            }

            var newOffset = this.position + offset;

            // ensure we won't go past the end of the stream
            if (newOffset + count > Length)
            {
                throw new AxiomException("Unable to write data past the end of a BufferStream");
            }

            // pin the array so we can get a pointer to it
            using (var handle = BufferBase.Wrap(val, count))
            {
#if !AXIOM_SAFE_ONLY
                unsafe
#endif
                {
                    // get byte pointers for the source and target
                    var b       = handle.ToBytePointer();
                    var dataPtr = this.data.ToBytePointer();

                    // copy the data from the source to the target
                    for (var i = 0; i < count; i++)
                    {
                        dataPtr[(int)(i + newOffset)] = b[i];
                    }
                }
            }
        }
Esempio n. 3
0
        protected static void FromD3DLock(PixelBox rval, DX.DataBox lbox)
        {
            var bpp  = PixelUtil.GetNumElemBytes(rval.Format);
            var size = 0;

            if (bpp != 0)
            {
                rval.RowPitch   = lbox.RowPitch / bpp;
                rval.SlicePitch = lbox.SlicePitch / bpp;
                Debug.Assert((lbox.RowPitch % bpp) == 0);
                Debug.Assert((lbox.SlicePitch % bpp) == 0);
                size = lbox.RowPitch * rval.Height;
            }
            else if (PixelUtil.IsCompressed(rval.Format))
            {
                rval.RowPitch   = rval.Width;
                rval.SlicePitch = rval.Width * rval.Height;
                size            = rval.Width * rval.Height;
            }
            else
            {
                throw new AxiomException("Invalid pixel format");
            }

            rval.Data = BufferBase.Wrap(lbox.DataPointer, size);
        }
        public override void ReadData(int offset, int length, BufferBase dest)
        {
            Debug.Assert((offset + length) <= base.sizeInBytes);

            using (var data = BufferBase.Wrap(_mpData).Offset(offset))
                Memory.Copy(dest, data, length);
        }
Esempio n. 5
0
        ///<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);
        }
Esempio n. 6
0
        public override Stream Encode(Stream input, Codec.CodecData pData)
        {
            var fiBitmap = _encode(input, pData);

            // open memory chunk allocated by FreeImage
            var mem = FI.FreeImage.OpenMemory(IntPtr.Zero, 0);

            // write data into memory
            FI.FreeImage.SaveToMemory((FI.FREE_IMAGE_FORMAT) this._freeImageType, fiBitmap, mem, FI.FREE_IMAGE_SAVE_FLAGS.DEFAULT);
            // Grab data information
            var  data = IntPtr.Zero;
            uint size = 0;

            FI.FreeImage.AcquireMemory(mem, ref data, ref size);
            // Copy data into our own buffer
            // Because we're asking MemoryDataStream to free this, must create in a compatible way
            var ourData = new byte[size];

            using (var src = BufferBase.Wrap(data, (int)size))
            {
                using (var dest = BufferBase.Wrap(ourData))
                {
                    Memory.Copy(src, dest, (int)size);
                }
            }
            // Wrap data in stream, tell it to free on close
            var outstream = new MemoryStream(ourData);

            // Now free FreeImage memory buffers
            FI.FreeImage.CloseMemory(mem);
            // Unload bitmap
            FI.FreeImage.Unload(fiBitmap);

            return(outstream);
        }
Esempio n. 7
0
        protected void Download()
        {
#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                using (var pDst = BufferBase.Wrap(this.mData, mData.Length * sizeof(float)))
                {
                    var pDstPtr = pDst.ToFloatPointer();
                    var pDstIdx = 0;
                    //download data
                    var box     = new BasicBox(0, 0, this.mBuffer.Width, this.mBuffer.Height);
                    var pBox    = this.mBuffer.Lock(box, BufferLocking.ReadOnly);
                    var pSrc    = pBox.Data.ToBytePointer();
                    var pSrcIdx = (int)this.mChannelOffset;
                    var srcInc  = PixelUtil.GetNumElemBytes(this.mBuffer.Format);
                    for (var y = box.Top; y < box.Bottom; ++y)
                    {
                        for (var x = box.Left; x < box.Right; ++x)
                        {
                            pDstPtr[pDstIdx++] = (float)((pSrc[pSrcIdx]) / 255.0f);
                            pSrcIdx           += srcInc;
                        }
                    }
                    this.mBuffer.Unlock();
                }
            }
        }
Esempio n. 8
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="offset"></param>
 /// <param name="length"></param>
 /// <param name="locking"></param>
 /// <returns></returns>
 protected override BufferBase LockImpl(int offset, int length, BufferLocking locking)
 {
     _offset  = offset;
     _length  = length;
     _locking = locking;
     return(BufferBase.Wrap(_bufferBytes).Offset(offset));
 }
Esempio n. 9
0
        public override void CopyContentsToMemory(PixelBox dst, FrameBuffer buffer)
        {
            if ((dst.Left < 0) || (dst.Right > Width) ||
                (dst.Top < 0) || (dst.Bottom > Height) ||
                (dst.Front != 0) || (dst.Back != 1))
            {
                throw new Exception("Invalid box.");
            }
            if (buffer == RenderTarget.FrameBuffer.Auto)
            {
                buffer = IsFullScreen ? RenderTarget.FrameBuffer.Front : RenderTarget.FrameBuffer.Back;
            }

            int format = GLPixelUtil.GetGLOriginFormat(dst.Format);
            int type   = GLPixelUtil.GetGLOriginDataType(dst.Format);

            if ((format == Gl.GL_NONE) || (type == 0))
            {
                throw new Exception("Unsupported format.");
            }


            // Switch context if different from current one
            RenderSystem rsys = Root.Instance.RenderSystem;

            rsys.Viewport = this.GetViewport(0);

            // Must change the packing to ensure no overruns!
            Gl.glPixelStorei(Gl.GL_PACK_ALIGNMENT, 1);

            Gl.glReadBuffer((buffer == RenderTarget.FrameBuffer.Front) ? Gl.GL_FRONT : Gl.GL_BACK);
            Gl.glReadPixels(dst.Left, dst.Top, dst.Width, dst.Height, format, type, dst.Data);

            // restore default alignment
            Gl.glPixelStorei(Gl.GL_PACK_ALIGNMENT, 4);

            //vertical flip

            {
                int    rowSpan = dst.Width * PixelUtil.GetNumElemBytes(dst.Format);
                int    height  = dst.Height;
                byte[] tmpData = new byte[rowSpan * height];
                unsafe
                {
                    var dataPtr = dst.Data.ToBytePointer();
                    //int *srcRow = (uchar *)dst.data, *tmpRow = tmpData + (height - 1) * rowSpan;

                    for (int row = height - 1, tmpRow = 0; row >= 0; row--, tmpRow++)
                    {
                        for (int col = 0; col < rowSpan; col++)
                        {
                            tmpData[tmpRow * rowSpan + col] = dataPtr[row * rowSpan + col];
                        }
                    }
                }
                var tmpDataHandle = BufferBase.Wrap(tmpData);
                Memory.Copy(tmpDataHandle, dst.Data, rowSpan * height);
            }
        }
Esempio n. 10
0
        private void _unpackDXTColor(PixelFormat pf, DXTColorBlock block, ColorEx[] pCol)
        {
            // Note - we assume all values have already been endian swapped

            // Colour lookup table
            var derivedColours = new ColorEx[4];

            using (var src = BufferBase.Wrap(block.colour_0, 1))
            {
                derivedColours[0] = PixelConverter.UnpackColor(PixelFormat.R5G6B5, src);
            }

            using (var src = BufferBase.Wrap(block.colour_1, 1))
            {
                derivedColours[1] = PixelConverter.UnpackColor(PixelFormat.R5G6B5, src);
            }

            if (pf == PixelFormat.DXT1 && block.colour_0 <= block.colour_1)
            {
                // 1-bit alpha

                // one intermediate colour, half way between the other two
                derivedColours[2] = (derivedColours[0] + derivedColours[1]) / 2;
                // transparent colour
                derivedColours[3] = new ColorEx(0, 0, 0, 0);
            }
            else
            {
                // first interpolated colour, 1/3 of the way along
                derivedColours[2] = (derivedColours[0] * 2 + derivedColours[1]) / 3;
                // second interpolated colour, 2/3 of the way along
                derivedColours[3] = (derivedColours[0] + derivedColours[1] * 2) / 3;
            }

            // Process 4x4 block of texels
            for (var row = 0; row < 4; ++row)
            {
                for (var x = 0; x < 4; ++x)
                {
                    // LSB come first
                    var colIdx = (byte)block.indexRow[row] >> (x * 2) & 0x3;
                    if (pf == PixelFormat.DXT1)
                    {
                        // Overwrite entire colour
                        pCol[(row * 4) + x] = derivedColours[colIdx];
                    }
                    else
                    {
                        // alpha has already been read (alpha precedes colour)
                        var col = pCol[(row * 4) + x];
                        col.r = derivedColours[colIdx].r;
                        col.g = derivedColours[colIdx].g;
                        col.b = derivedColours[colIdx].b;
                    }
                }
            }
        }
Esempio n. 11
0
        private void AllocateBuffer()
        {
            if (this.Buffer.Data != null)
            {
                //already allocated
                return;
            }

            this.Buffer.Data = BufferBase.Wrap(new byte[sizeInBytes]);
        }
Esempio n. 12
0
        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();
        }
Esempio n. 13
0
        private void BuildMipmaps(PixelBox data)
        {
            int width, height, logW, logH, level;

            PixelBox scaled = data;

            scaled.Data   = data.Data;
            scaled.Left   = data.Left;
            scaled.Right  = data.Right;
            scaled.Top    = data.Top;
            scaled.Bottom = data.Bottom;
            scaled.Front  = data.Front;
            scaled.Back   = data.Back;

            width  = data.Width;
            height = data.Height;

            logW  = (int)System.Math.Log(width);
            logH  = (int)System.Math.Log(height);
            level = (logW > logH ? logW : logH);

            for (int mip = 0; mip < level; mip++)
            {
                All glFormat = GLES2PixelUtil.GetGLOriginFormat(scaled.Format);
                All dataType = GLES2PixelUtil.GetGLOriginDataType(scaled.Format);

                GL.TexImage2D(this.faceTarget, mip, (int)glFormat, width, height, 0, glFormat, dataType, scaled.Data.Pin());
                GLES2Config.GlCheckError(this);

                if (mip != 0)
                {
                    scaled.Data = null;
                }

                if (width > 1)
                {
                    width /= 2;
                }
                if (height > 1)
                {
                    height /= 2;
                }

                int sizeInBytes = PixelUtil.GetMemorySize(width, height, 1, data.Format);
                scaled      = new PixelBox(width, height, 1, data.Format);
                scaled.Data = BufferBase.Wrap(new byte[sizeInBytes]);
                Image.Scale(data, scaled, ImageFilter.Linear);
            }

            //Delete the scaled data for the last level
            if (level > 0)
            {
                scaled.Data = null;
            }
        }
Esempio n. 14
0
        /// <summary>
        /// </summary>
        /// <param name="idxType"> </param>
        /// <param name="numIndexes"> </param>
        /// <param name="usage"> </param>
        public GLESDefaultHardwareIndexBuffer(IndexType idxType, int numIndexes, BufferUsage usage)
            : base(null, idxType, numIndexes, usage, true, false)               // always software, never shadowed
        {
            if (idxType == IndexType.Size32)
            {
                throw new AxiomException("32 bit hardware buffers are not allowed in OpenGL ES.");
            }

            this._data    = new byte[sizeInBytes];
            this._dataPtr = BufferBase.Wrap(this._data);
        }
Esempio n. 15
0
        public void WriteContentsToFile(string fileName)
        {
            var pf = SuggestPixelFormat();

            var data = new byte[Width * Height * PixelUtil.GetNumElemBytes(pf)];
            var buf  = BufferBase.Wrap(data);
            var pb   = new PixelBox(Width, Height, 1, pf, buf);

            CopyContentsToMemory(pb);

            (new Image()).FromDynamicImage(data, Width, Height, 1, pf, false, 1, 0).Save(fileName);
            buf.Dispose();
        }
Esempio n. 16
0
 protected void SetBuffer(byte[] newBuffer)
 {
     if (this.buffer != null)
     {
         this.bufPtr = null;
         this.buffer = null;
     }
     if (newBuffer != null)
     {
         this.buffer = newBuffer;
         this.bufPtr = BufferBase.Wrap(newBuffer);
     }
 }
Esempio n. 17
0
        protected void allocateBuffer()
        {
            if (buffer.Data != null)
            {
                // Already allocated
                return;
            }

            // Allocate storage
            this._data  = new byte[sizeInBytes];
            buffer.Data = BufferBase.Wrap(this._data);
            // TODO: use PBO if we're HBU_DYNAMIC
        }
Esempio n. 18
0
        ///<summary>
        ///</summary>
        ///<param name="offset"> </param>
        ///<param name="length"> </param>
        ///<param name="locking"> </param>
        ///<returns> </returns>
        protected override BufferBase LockImpl(int offset, int length, BufferLocking locking)
        {
            int access = 0;

            if (isLocked)
            {
                throw new Exception("Invalid attempt to lock an index buffer that has already been locked.");
            }

            // bind this buffer
            Gl.glBindBufferARB(Gl.GL_ELEMENT_ARRAY_BUFFER_ARB, this._bufferId);

            if (locking == BufferLocking.Discard)
            {
                // commented out to fix ATI issues

                /*Gl.glBufferDataARB(Gl.GL_ELEMENT_ARRAY_BUFFER_ARB,
                 *       sizeInBytes,
                 *       IntPtr.Zero,
                 *       GLHelper.ConvertEnum(usage));
                 */

                // find out how we shall access this buffer
                access = (usage == BufferUsage.Dynamic) ? Gl.GL_READ_WRITE_ARB : Gl.GL_WRITE_ONLY_ARB;
            }
            else if (locking == BufferLocking.ReadOnly)
            {
                if (usage == BufferUsage.WriteOnly)
                {
                    LogManager.Instance.Write("OGL : Invalid attempt to lock a write-only vertex buffer as read-only.");
                }

                access = Gl.GL_READ_ONLY_ARB;
            }
            else if (locking == BufferLocking.Normal || locking == BufferLocking.NoOverwrite)
            {
                access = (usage == BufferUsage.Dynamic) ? Gl.GL_READ_WRITE_ARB : Gl.GL_WRITE_ONLY_ARB;
            }

            IntPtr ptr = Gl.glMapBufferARB(Gl.GL_ELEMENT_ARRAY_BUFFER_ARB, access);

            if (ptr == IntPtr.Zero)
            {
                throw new Exception("OGL: Vertex Buffer: Out of memory");
            }

            isLocked = true;

            return(BufferBase.Wrap(new IntPtr(ptr.ToInt64() + offset), length));
        }
Esempio n. 19
0
        public override void EncodeToFile(Stream input, string outFileName, Codec.CodecData codecData)
        {
            int imageID;

            // create and bind a new image
            Il.ilGenImages(1, out imageID);
            Il.ilBindImage(imageID);

            var buffer = new byte[input.Length];

            input.Read(buffer, 0, buffer.Length);

            var imgData = (ImageData)codecData;

            PixelBox src;

            using (var bufHandle = BufferBase.Wrap(buffer))
            {
                src = new PixelBox(imgData.width, imgData.height, imgData.depth, imgData.format, bufHandle);
            }

            try
            {
                // Convert image from Axiom to current IL image
                ILUtil.ConvertToIL(src);
            }
            catch (Exception ex)
            {
                LogManager.Instance.Write("IL Failed image conversion :", ex.Message);
            }

            // flip the image
            Ilu.iluFlipImage();

            // save the image to file
            Il.ilSaveImage(outFileName);

            var error = Il.ilGetError();

            if (error != Il.IL_NO_ERROR)
            {
                LogManager.Instance.Write("IL Error, could not save file: {0} : {1}", outFileName, Ilu.iluErrorString(error));
            }

            Il.ilDeleteImages(1, ref imageID);
        }
Esempio n. 20
0
        ///<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();
            }
        }
Esempio n. 21
0
        public override string MagicNumberToFileExt(byte[] magicNumberBuf, int maxbytes)
        {
            if (maxbytes >= sizeof(int))
            {
                var fileType = BitConverter.ToInt32(magicNumberBuf, 0);
                using (var data = BufferBase.Wrap(fileType, 2))
                {
                    _flipEndian(data, sizeof(int), 1);
                }

                if (this.PVR_MAGIC == fileType)
                {
                    return("pvr");
                }
            }

            return(string.Empty);
        }
Esempio n. 22
0
        public void Update()
        {
            if (this.mData != null && this.mDirty)
            {
                using (var mDataBuf = BufferBase.Wrap(this.mData, mData.Length * sizeof(float)))
                {
                    var pSrcBase = mDataBuf + (this.mDirtyBox.Top * this.mBuffer.Width + this.mDirtyBox.Left);
                    var pDstBase = this.mBuffer.Lock(this.mDirtyBox, BufferLocking.Normal).Data;
                    pDstBase += this.mChannelOffset;
                    var dstInc = PixelUtil.GetNumElemBytes(this.mBuffer.Format);

#if !AXIOM_SAFE_ONLY
                    unsafe
#endif
                    {
                        for (int y = 0; y < this.mDirtyBox.Height; ++y)
                        {
                            var pSrc = (pSrcBase + (y * this.mBuffer.Width) * sizeof(float)).ToFloatPointer();
                            var pDst = pDstBase + (y * this.mBuffer.Width * dstInc);
                            for (int x = 0; x < this.mDirtyBox.Width; ++x)
                            {
                                pDst.ToBytePointer()[0] = (byte)(pSrc[x] * 255);
                                pDst += dstInc;
                            }
                        }
                    }

                    this.mBuffer.Unlock();
                    this.mDirty = false;
                }

                // make sure composite map is updated
                // mDirtyBox is in image space, convert to terrain units
                var compositeMapRect = new Rectangle();
                var blendToTerrain   = (float)this.mParent.Size / (float)this.mBuffer.Width;
                compositeMapRect.Left   = (long)(this.mDirtyBox.Left * blendToTerrain);
                compositeMapRect.Right  = (long)(this.mDirtyBox.Right * blendToTerrain + 1);
                compositeMapRect.Top    = (long)((this.mBuffer.Height - this.mDirtyBox.Bottom) * blendToTerrain);
                compositeMapRect.Bottom = (long)((this.mBuffer.Height - this.mDirtyBox.Top) * blendToTerrain + 1);
                this.mParent.DirtyCompositeMapRect(compositeMapRect);
                this.mParent.UpdateCompositeMapWithDelay();
            }
        }
Esempio n. 23
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);
        }
Esempio n. 24
0
        public override string MagicNumberToFileExt(byte[] magicBuf, int maxbytes)
        {
            FI.FIMEMORY          fiMem;
            FI.FREE_IMAGE_FORMAT fif;

            using (var ptr = BufferBase.Wrap(magicBuf))
            {
                fiMem = FI.FreeImage.OpenMemory(ptr.Pin(), (uint)maxbytes);
                ptr.UnPin();
                fif = FI.FreeImage.GetFileTypeFromMemory(fiMem, maxbytes);
                FI.FreeImage.CloseMemory(fiMem);
            }

            if (fif != FI.FREE_IMAGE_FORMAT.FIF_UNKNOWN)
            {
                return(FI.FreeImage.GetFormatFromFIF(fif).ToLower());
            }
            else
            {
                return(string.Empty);
            }
        }
Esempio n. 25
0
        public D3D9HardwareVertexBuffer(HardwareBufferManagerBase manager, VertexDeclaration vertexDeclaration,
                                        int numVertices, BufferUsage usage, bool useSystemMemory, bool useShadowBuffer)
            : base(manager, vertexDeclaration, numVertices, usage, useSystemMemory, useShadowBuffer)
        {
            //Entering critical section
            this.LockDeviceAccess();

            this._mapDeviceToBufferResources = new Dictionary <D3D9.Device, BufferResources>();

#if AXIOM_D3D_MANAGE_BUFFERS
            var eResourcePool = useSystemMemory
                                                                        ? D3D9.Pool.SystemMemory
                                                                        : // If not system mem, use managed pool UNLESS buffer is discardable
                                                                          // if discardable, keeping the software backing is expensive
                                ((usage & BufferUsage.Discardable) != 0) ? D3D9.Pool.Default : D3D9.Pool.Managed;
#else
            var eResourcePool = useSystemMemory ? D3D9.Pool.SystemMemory : D3D9.Pool.Default;
#endif

            // Set the desired memory pool.
            this._bufferDesc.Pool = eResourcePool;

            // Allocate the system memory buffer.
            this._systemMemoryBuffer = BufferBase.Wrap(new byte[sizeInBytes]);

            // Case we have to create this buffer resource on loading.
            if (D3D9RenderSystem.ResourceManager.CreationPolicy == D3D9ResourceManager.ResourceCreationPolicy.CreateOnAllDevices)
            {
                foreach (var d3d9Device in D3D9RenderSystem.ResourceCreationDevices)
                {
                    CreateBuffer(d3d9Device, this._bufferDesc.Pool);
                }
            }

            D3D9RenderSystem.ResourceManager.NotifyResourceCreated(this);

            //Leaving critical section
            this.UnlockDeviceAccess();
        }
Esempio n. 26
0
        /// <summary>
        /// </summary>
        /// <param name="offset"> </param>
        /// <param name="length"> </param>
        /// <param name="locking"> </param>
        /// <returns> </returns>
        protected override BufferBase LockImpl(int offset, int length, BufferLocking locking)
        {
            All access = 0;

            if (isLocked)
            {
                throw new AxiomException("Invalid attempt to lock an index buffer that has already been locked");
            }

            BufferBase retPtr = null;

            if (length < MapBufferThreshold)
            {
                retPtr = ((GLESHardwareBufferManager)HardwareBufferManager.Instance).AllocateScratch(length);
                if (retPtr != null)
                {
                    this._lockedToScratch       = true;
                    this._scratchOffset         = offset;
                    this._scratchSize           = length;
                    this._scratchPtr            = retPtr;
                    this._scratchUploadOnUnlock = (locking != BufferLocking.ReadOnly);

                    if (locking != BufferLocking.Discard)
                    {
                        this.ReadData(offset, length, retPtr);
                    }
                }
            }
            else
            {
                throw new AxiomException("Invalid Buffer lockSize");
            }

            if (retPtr == null)
            {
                OpenGL.BindBuffer(All.ElementArrayBuffer, this._bufferId);
                GLESConfig.GlCheckError(this);
                // Use glMapBuffer
                if (locking == BufferLocking.Discard)
                {
                    OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLESHardwareBufferManager.GetGLUsage(usage));
                    GLESConfig.GlCheckError(this);
                }
                if ((usage & BufferUsage.WriteOnly) != 0)
                {
                    access = All.WriteOnlyOes;
                }

                IntPtr pBuffer = OpenGLOES.MapBuffer(All.ElementArrayBuffer, access);
                GLESConfig.GlCheckError(this);
                if (pBuffer == IntPtr.Zero)
                {
                    throw new AxiomException("Index Buffer: Out of memory");
                }
                unsafe
                {
                    // return offset
                    retPtr = BufferBase.Wrap(pBuffer, sizeInBytes);
                }

                this._lockedToScratch = false;
            }
            isLocked = true;

            return(retPtr);
        }
Esempio n. 27
0
        public override Codec.DecodeResult Decode(Stream input)
        {
            // Buffer stream into memory (TODO: override IO functions instead?)
            var data = new byte[(int)input.Length];

            input.Read(data, 0, data.Length);
            FI.FIMEMORY          fiMem;
            FI.FREE_IMAGE_FORMAT ff;
            FI.FIBITMAP          fiBitmap;
            using (var datPtr = BufferBase.Wrap(data))
            {
                fiMem = FI.FreeImage.OpenMemory(datPtr.Pin(), (uint)data.Length);
                datPtr.UnPin();
                ff       = (FI.FREE_IMAGE_FORMAT) this._freeImageType;
                fiBitmap = FI.FreeImage.LoadFromMemory((FI.FREE_IMAGE_FORMAT) this._freeImageType, fiMem,
                                                       FI.FREE_IMAGE_LOAD_FLAGS.DEFAULT);
            }

            if (fiBitmap.IsNull)
            {
                throw new AxiomException("Error decoding image");
            }

            var imgData = new ImageData();

            imgData.depth      = 1; // only 2D formats handled by this codec
            imgData.width      = (int)FI.FreeImage.GetWidth(fiBitmap);
            imgData.height     = (int)FI.FreeImage.GetHeight(fiBitmap);
            imgData.numMipMaps = 0; // no mipmaps in non-DDS

            // Must derive format first, this may perform conversions
            var imageType = FI.FreeImage.GetImageType(fiBitmap);
            var colorType = FI.FreeImage.GetColorType(fiBitmap);
            var bpp       = (int)FI.FreeImage.GetBPP(fiBitmap);

            switch (imageType)
            {
            case FI.FREE_IMAGE_TYPE.FIT_UNKNOWN:
            case FI.FREE_IMAGE_TYPE.FIT_COMPLEX:
            case FI.FREE_IMAGE_TYPE.FIT_UINT32:
            case FI.FREE_IMAGE_TYPE.FIT_INT32:
            case FI.FREE_IMAGE_TYPE.FIT_DOUBLE:
            default:
                throw new AxiomException("Unknown or unsupported image format");

            case FI.FREE_IMAGE_TYPE.FIT_BITMAP:
                // Standard image type
                // Perform any colour conversions for greyscale
                if (colorType == FI.FREE_IMAGE_COLOR_TYPE.FIC_MINISWHITE || colorType == FI.FREE_IMAGE_COLOR_TYPE.FIC_MINISBLACK)
                {
                    var newBitmap = FI.FreeImage.ConvertToGreyscale(fiBitmap);
                    // free old bitmap and replace
                    FI.FreeImage.Unload(fiBitmap);
                    fiBitmap = newBitmap;
                    // get new formats
                    bpp       = (int)FI.FreeImage.GetBPP(fiBitmap);
                    colorType = FI.FreeImage.GetColorType(fiBitmap);
                }
                // Perform any colour conversions for RGB
                else if (bpp < 8 || colorType == FI.FREE_IMAGE_COLOR_TYPE.FIC_PALETTE ||
                         colorType == FI.FREE_IMAGE_COLOR_TYPE.FIC_CMYK)
                {
                    var newBitmap = FI.FreeImage.ConvertTo24Bits(fiBitmap);
                    // free old bitmap and replace
                    FI.FreeImage.Unload(fiBitmap);
                    fiBitmap = newBitmap;
                    // get new formats
                    bpp       = (int)FI.FreeImage.GetBPP(fiBitmap);
                    colorType = FI.FreeImage.GetColorType(fiBitmap);
                }

                // by this stage, 8-bit is greyscale, 16/24/32 bit are RGB[A]
                switch (bpp)
                {
                case 8:
                    imgData.format = PixelFormat.L8;
                    break;

                case 16:
                    // Determine 555 or 565 from green mask
                    // cannot be 16-bit greyscale since that's FIT_UINT16
                    if (FI.FreeImage.GetGreenMask(fiBitmap) == FI.FreeImage.FI16_565_GREEN_MASK)
                    {
                        imgData.format = PixelFormat.R5G6B5;
                    }
                    else
                    {
                        // FreeImage doesn't support 4444 format so must be 1555
                        imgData.format = PixelFormat.A1R5G5B5;
                    }
                    break;

                case 24:
                    // FreeImage differs per platform
                    //     PixelFormat.BYTE_BGR[A] for little endian (== PixelFormat.ARGB native)
                    //     PixelFormat.BYTE_RGB[A] for big endian (== PixelFormat.RGBA native)
                    if (FI.FreeImage.IsLittleEndian())
                    {
                        imgData.format = PixelFormat.BYTE_BGR;
                    }
                    else
                    {
                        imgData.format = PixelFormat.BYTE_RGB;
                    }
                    break;

                case 32:
                    if (FI.FreeImage.IsLittleEndian())
                    {
                        imgData.format = PixelFormat.BYTE_BGRA;
                    }
                    else
                    {
                        imgData.format = PixelFormat.BYTE_RGBA;
                    }
                    break;
                }
                ;
                break;

            case FI.FREE_IMAGE_TYPE.FIT_UINT16:
            case FI.FREE_IMAGE_TYPE.FIT_INT16:
                // 16-bit greyscale
                imgData.format = PixelFormat.L16;
                break;

            case FI.FREE_IMAGE_TYPE.FIT_FLOAT:
                // Single-component floating point data
                imgData.format = PixelFormat.FLOAT32_R;
                break;

            case FI.FREE_IMAGE_TYPE.FIT_RGB16:
                imgData.format = PixelFormat.SHORT_RGB;
                break;

            case FI.FREE_IMAGE_TYPE.FIT_RGBA16:
                imgData.format = PixelFormat.SHORT_RGBA;
                break;

            case FI.FREE_IMAGE_TYPE.FIT_RGBF:
                imgData.format = PixelFormat.FLOAT32_RGB;
                break;

            case FI.FREE_IMAGE_TYPE.FIT_RGBAF:
                imgData.format = PixelFormat.FLOAT32_RGBA;
                break;
            }

            var srcPitch = (int)FI.FreeImage.GetPitch(fiBitmap);

            // Final data - invert image and trim pitch at the same time
            var dstPitch = imgData.width * PixelUtil.GetNumElemBytes(imgData.format);

            imgData.size = dstPitch * imgData.height;
            // Bind output buffer
            var outputData = new byte[imgData.size];

            using (var srcData = BufferBase.Wrap(FI.FreeImage.GetBits(fiBitmap), imgData.height * srcPitch))
            {
                var pDst = BufferBase.Wrap(outputData);

                for (var y = 0; y < imgData.height; ++y)
                {
                    using (var pSrc = srcData + (imgData.height - y - 1) * srcPitch)
                    {
                        Memory.Copy(pSrc, pDst, dstPitch);
                        pDst += dstPitch;
                    }
                }

                pDst.Dispose();
            }

            FI.FreeImage.Unload(fiBitmap);
            FI.FreeImage.CloseMemory(fiMem);

            return(new Codec.DecodeResult(new MemoryStream(outputData), imgData));
        }
Esempio n. 28
0
        private FI.FIBITMAP _encode(Stream input, CodecData codecData)
        {
            var ret = new FI.FIBITMAP();

            ret.SetNull();
            var imgData = codecData as ImageData;

            if (imgData != null)
            {
                var data = new byte[(int)input.Length];
                input.Read(data, 0, data.Length);
                var dataPtr = BufferBase.Wrap(data);
                var src     = new PixelBox(imgData.width, imgData.height, imgData.depth, imgData.format, dataPtr);

                // The required format, which will adjust to the format
                // actually supported by FreeImage.
                var requiredFormat = imgData.format;

                // determine the settings
                var imageType         = FI.FREE_IMAGE_TYPE.FIT_UNKNOWN;
                var determiningFormat = imgData.format;

                switch (determiningFormat)
                {
                case PixelFormat.R5G6B5:
                case PixelFormat.B5G6R5:
                case PixelFormat.R8G8B8:
                case PixelFormat.B8G8R8:
                case PixelFormat.A8R8G8B8:
                case PixelFormat.X8R8G8B8:
                case PixelFormat.A8B8G8R8:
                case PixelFormat.X8B8G8R8:
                case PixelFormat.B8G8R8A8:
                case PixelFormat.R8G8B8A8:
                case PixelFormat.A4L4:
                case PixelFormat.BYTE_LA:
                case PixelFormat.R3G3B2:
                case PixelFormat.A4R4G4B4:
                case PixelFormat.A1R5G5B5:
                case PixelFormat.A2R10G10B10:
                case PixelFormat.A2B10G10R10:
                    // I'd like to be able to use r/g/b masks to get FreeImage to load the data
                    // in it's existing format, but that doesn't work, FreeImage needs to have
                    // data in RGB[A] (big endian) and BGR[A] (little endian), always.
                    if (PixelUtil.HasAlpha(determiningFormat))
                    {
                        if (FI.FreeImageEngine.IsLittleEndian)
                        {
                            requiredFormat = PixelFormat.BYTE_BGRA;
                        }
                        else
                        {
                            requiredFormat = PixelFormat.BYTE_RGBA;
                        }
                    }
                    else
                    {
                        if (FI.FreeImageEngine.IsLittleEndian)
                        {
                            requiredFormat = PixelFormat.BYTE_BGR;
                        }
                        else
                        {
                            requiredFormat = PixelFormat.BYTE_RGB;
                        }
                    }
                    imageType = FI.FREE_IMAGE_TYPE.FIT_BITMAP;
                    break;

                case PixelFormat.L8:
                case PixelFormat.A8:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_BITMAP;
                    break;

                case PixelFormat.L16:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_UINT16;
                    break;

                case PixelFormat.SHORT_GR:
                    requiredFormat = PixelFormat.SHORT_RGB;
                    break;

                case PixelFormat.SHORT_RGB:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_RGB16;
                    break;

                case PixelFormat.SHORT_RGBA:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_RGBA16;
                    break;

                case PixelFormat.FLOAT16_R:
                    requiredFormat = PixelFormat.FLOAT32_R;
                    break;

                case PixelFormat.FLOAT32_R:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_FLOAT;
                    break;

                case PixelFormat.FLOAT16_GR:
                case PixelFormat.FLOAT16_RGB:
                case PixelFormat.FLOAT32_GR:
                    requiredFormat = PixelFormat.FLOAT32_RGB;
                    break;

                case PixelFormat.FLOAT32_RGB:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_RGBF;
                    break;

                case PixelFormat.FLOAT16_RGBA:
                    requiredFormat = PixelFormat.FLOAT32_RGBA;
                    break;

                case PixelFormat.FLOAT32_RGBA:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_RGBAF;
                    break;

                default:
                    throw new AxiomException("Not Supported image format :{0}", determiningFormat.ToString());
                } //end switch

                // Check support for this image type & bit depth
                if (!FI.FreeImage.FIFSupportsExportType((FI.FREE_IMAGE_FORMAT) this._freeImageType, imageType) ||
                    !FI.FreeImage.FIFSupportsExportBPP((FI.FREE_IMAGE_FORMAT) this._freeImageType,
                                                       PixelUtil.GetNumElemBits(requiredFormat)))
                {
                    // Ok, need to allocate a fallback
                    // Only deal with RGBA . RGB for now
                    switch (requiredFormat)
                    {
                    case PixelFormat.BYTE_RGBA:
                        requiredFormat = PixelFormat.BYTE_RGB;
                        break;

                    case PixelFormat.BYTE_BGRA:
                        requiredFormat = PixelFormat.BYTE_BGR;
                        break;

                    default:
                        break;
                    }
                }

                var conversionRequired = false;
                input.Position = 0;
                var srcData = new byte[(int)input.Length];
                input.Read(srcData, 0, srcData.Length);
                var srcDataPtr = BufferBase.Wrap(srcData);

                // Check BPP
                var bpp = PixelUtil.GetNumElemBits(requiredFormat);
                if (!FI.FreeImage.FIFSupportsExportBPP((FI.FREE_IMAGE_FORMAT) this._freeImageType, bpp))
                {
                    if (bpp == 32 && PixelUtil.HasAlpha(imgData.format) &&
                        FI.FreeImage.FIFSupportsExportBPP((FI.FREE_IMAGE_FORMAT) this._freeImageType, 24))
                    {
                        // drop to 24 bit (lose alpha)
                        if (FI.FreeImage.IsLittleEndian())
                        {
                            requiredFormat = PixelFormat.BYTE_BGR;
                        }
                        else
                        {
                            requiredFormat = PixelFormat.BYTE_RGB;
                        }

                        bpp = 24;
                    }
                    else if (bpp == 128 && PixelUtil.HasAlpha(imgData.format) &&
                             FI.FreeImage.FIFSupportsExportBPP((FI.FREE_IMAGE_FORMAT) this._freeImageType, 96))
                    {
                        // drop to 96-bit floating point
                        requiredFormat = PixelFormat.FLOAT32_RGB;
                    }
                }

                var convBox = new PixelBox(imgData.width, imgData.height, 1, requiredFormat);
                if (requiredFormat != imgData.format)
                {
                    conversionRequired = true;
                    // Allocate memory
                    var convData = new byte[convBox.ConsecutiveSize];
                    convBox.Data = BufferBase.Wrap(convData);
                    // perform conversion and reassign source
                    var newSrc = new PixelBox(imgData.width, imgData.height, 1, imgData.format, dataPtr);
                    PixelConverter.BulkPixelConversion(newSrc, convBox);
                    srcDataPtr = convBox.Data;
                }

                ret = FI.FreeImage.AllocateT(imageType, imgData.width, imgData.height, bpp);
                if (ret.IsNull)
                {
                    if (conversionRequired)
                    {
                        srcDataPtr.SafeDispose();
                        convBox = null;
                    }

                    throw new AxiomException("FreeImage.AllocateT failed - possibly out of memory. ");
                }

                if (requiredFormat == PixelFormat.L8 || requiredFormat == PixelFormat.A8)
                {
                    // Must explicitly tell FreeImage that this is greyscale by setting
                    // a "grey" palette (otherwise it will save as a normal RGB
                    // palettized image).
                    var tmp = FI.FreeImage.ConvertToGreyscale(ret);
                    FI.FreeImage.Unload(ret);
                    ret = tmp;
                }

                var dstPitch = (int)FI.FreeImage.GetPitch(ret);
                var srcPitch = imgData.width * PixelUtil.GetNumElemBytes(requiredFormat);

                // Copy data, invert scanlines and respect FreeImage pitch
                var pSrc = srcDataPtr;
                using (var pDest = BufferBase.Wrap(FI.FreeImage.GetBits(ret), imgData.height * srcPitch))
                {
                    var byteSrcData = pSrc;
                    var byteDstData = pDest;
                    for (var y = 0; y < imgData.height; ++y)
                    {
                        byteSrcData += (imgData.height - y - 1) * srcPitch;
                        Memory.Copy(pSrc, pDest, srcPitch);
                        byteDstData += dstPitch;
                    }
                }

                if (conversionRequired)
                {
                    // delete temporary conversion area
                    srcDataPtr.SafeDispose();
                    convBox = null;
                }
            }
            return(ret);
        }
Esempio n. 29
0
        public override Codec.DecodeResult Decode(Stream input)
        {
            using (var br = new BinaryReader(input))
            {
                var numFaces = 1;                 // Assume one face until we know otherwise
                var imgData  = new ImageData();

                // Read the PVRTC header
                var header = PVRTCTexHeader.Read(br);

                // Get the file type identifier
                var pvrTag = header.pvrTag;

                if (this.PVR_MAGIC != pvrTag)
                {
                    throw new AxiomException("This is not a PVR file!");
                }

                // Get format flags
                var flags = header.flags;
                using (var wrap = BufferBase.Wrap(flags, 2))
                {
                    _flipEndian(wrap, sizeof(int));
                }
                var formatFlags = flags & PVR_TEXTURE_FLAG_TYPE_MASK;

                var bitmaskAlpha = header.bitmaskAlpha;
                using (var wrap = BufferBase.Wrap(bitmaskAlpha, 2))
                {
                    _flipEndian(wrap, sizeof(int));
                }

                if (formatFlags == kPVRTextureFlagTypePVRTC_4 || formatFlags == kPVRTextureFlagTypePVRTC_2)
                {
                    if (formatFlags == kPVRTextureFlagTypePVRTC_4)
                    {
                        imgData.format = bitmaskAlpha != 0 ? PixelFormat.PVRTC_RGBA4 : PixelFormat.PVRTC_RGB4;
                    }
                    else if (formatFlags == kPVRTextureFlagTypePVRTC_2)
                    {
                        imgData.format = bitmaskAlpha != 0 ? PixelFormat.PVRTC_RGBA2 : PixelFormat.PVRTC_RGB2;
                    }

                    imgData.depth      = 1;
                    imgData.width      = header.width;
                    imgData.height     = header.height;
                    imgData.numMipMaps = header.numMipmaps;

                    // PVRTC is a compressed format
                    imgData.flags |= ImageFlags.Compressed;
                }

                // Calculate total size from number of mipmaps, faces and size
                imgData.size = Image.CalculateSize(imgData.numMipMaps, numFaces, imgData.width, imgData.height, imgData.depth,
                                                   imgData.format);

                // Now deal with the data
                var dest = br.ReadBytes(imgData.size);
                return(new DecodeResult(new MemoryStream(dest), imgData));
            }
        }
Esempio n. 30
0
        public void Blit(ref PixelBox src, BasicBox dstBox)
        {
            var srcBox = src;

            if (srcBox.Width != dstBox.Width || srcBox.Height != dstBox.Height)
            {
                // we need to rescale src to dst size first (also confvert format)
                var tmpData = new float[dstBox.Width * dstBox.Height];
                srcBox = new PixelBox(dstBox.Width, dstBox.Height, 1, PixelFormat.L8, BufferBase.Wrap(tmpData, tmpData.Length * sizeof(float)));
                Image.Scale(src, srcBox);
            }

            //pixel conversion
            var dstMemBox = new PixelBox(dstBox.Width, dstBox.Height, dstBox.Depth, PixelFormat.L8, BufferBase.Wrap(this.mData, mData.Length * sizeof(float)));

            PixelConverter.BulkPixelConversion(src, dstMemBox);

            if (srcBox != src)
            {
                // free temp
                srcBox = null;
            }
            var dRect = new Rectangle(dstBox.Left, dstBox.Top, dstBox.Right, dstBox.Bottom);

            DirtyRect(dRect);
        }