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 );
		}
		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 );
		}
		/// <summary>
		/// </summary>
		/// <param name="idxType"> </param>
		/// <param name="numIndexes"> </param>
		/// <param name="usage"> </param>
		public GLES2DefaultHardwareIndexBuffer( 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 );
		}
            public void Convert(BufferBase input, BufferBase output, int offset)
            {
#if !AXIOM_SAFE_ONLY
                unsafe
#endif
                {
                    var inputPtr  = input.ToBytePointer();
                    var outputPtr = output.ToUIntPointer();
                    var inp       = inputPtr[offset];

                    outputPtr[offset] = 0xFF000000 | (((uint)inp) << 0) | (((uint)inp) << 8) | (((uint)inp) << 16);
                }
            }
 /// <summary>
 /// </summary>
 /// <param name="offset"> </param>
 /// <param name="length"> </param>
 /// <param name="dest"> </param>
 public override void ReadData(int offset, int length, BufferBase dest)
 {
     if (useShadowBuffer)
     {
         var srcData = shadowBuffer.Lock(offset, length, BufferLocking.ReadOnly);
         Memory.Copy(srcData, dest, length);
         shadowBuffer.Unlock();
     }
     else
     {
         throw new AxiomException("Reading hardware buffer is not supported.");
     }
 }
Exemple #6
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();
        }
Exemple #7
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);
     }
 }
Exemple #8
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
        }
            public void Convert(BufferBase input, BufferBase output, int offset)
            {
#if !AXIOM_SAFE_ONLY
                unsafe
#endif
                {
                    var inputPtr  = input.ToUIntPointer();
                    var outputPtr = output.ToUIntPointer();
                    var inp       = inputPtr[offset];

                    outputPtr[offset] = ((inp & 0x0000FF00) << 16) | (inp & 0x00FF00FF) | ((inp & 0xFF000000) >> 16);
                }
            }
            public void Convert(BufferBase input, BufferBase output, int offset)
            {
#if !AXIOM_SAFE_ONLY
                unsafe
#endif
                {
                    var inputPtr  = input.ToUIntPointer();
                    var outputPtr = output.ToBytePointer();
                    var inp       = inputPtr[offset];

                    outputPtr[offset] = (byte)(inp & 0x000000FF);
                }
            }
Exemple #11
0
            public static byte[] GetBuffer(string _src)
            {
                byte[] strbyte = Encoding.UTF8.GetBytes(_src);
                byte[] lenbyte = BufferBase.GetBuffer((short)strbyte.Length);
                byte[] ret     = new byte[strbyte.Length + lenbyte.Length];

                lenbyte.CopyTo(ret, 0);
                if (strbyte.Length > 0)
                {
                    strbyte.CopyTo(ret, lenbyte.Length);
                }

                return(ret);
            }
        public override void WriteData(int offset, int length, BufferBase src, bool discardWholeBuffer)
        {
            // There is no functional interface in D3D, just do via manual
            // lock, copy & unlock

            // lock the buffer real quick
            var dest = Lock(offset, length, discardWholeBuffer ? BufferLocking.Discard : BufferLocking.Normal);

            // copy that data in there
            Memory.Copy(src, dest, length);

            // unlock the buffer
            Unlock();
        }
Exemple #13
0
        /// <summary>
        ///		Writes a specified number of floats.
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="count">Number of values to write.</param>
        /// <param name="src">Pointer that holds the values.</param>
        protected void WriteFloats(BinaryWriter writer, int count, BufferBase src)
        {
#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                var pointer = src.ToFloatPointer();

                for (var i = 0; i < count; i++)
                {
                    writer.Write(pointer[i]);
                }
            }
        }
Exemple #14
0
        /// <summary>
        ///		Reads a specified number of shorts and copies them into the destination pointer.
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="count">Number of values to read.</param>
        /// <param name="dest">Pointer to copy the values into.</param>
        protected void ReadShorts(BinaryReader reader, int count, BufferBase dest)
        {
            // blast the data into the buffer
#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                var pointer = dest.ToShortPointer();
                for (var i = 0; i < count; i++)
                {
                    pointer[i] = ReadShort(reader);
                }
            }
        }
Exemple #15
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));
        }
        public override void ReadData(int offset, int length, BufferBase dest)
        {
            // There is no functional interface in D3D, just do via manual
            // lock, copy & unlock

            // lock the buffer for reading
            var src = Lock(offset, length, BufferLocking.ReadOnly);

            // copy that data in there
            Memory.Copy(src, dest, length);

            // unlock the buffer
            Unlock();
        }
Exemple #17
0
        /// <summary>
        ///		Writes a specified number of shorts.
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="count">Number of values to write.</param>
        /// <param name="src">Pointer that holds the values.</param>
        protected void WriteShorts(BinaryWriter writer, int count, BufferBase src)
        {
            // blast the data into the buffer
#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                var pointer = src.ToShortPointer();

                for (var i = 0; i < count; i++)
                {
                    writer.Write(pointer[i]);
                }
            }
        }
        ///<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();
            }
        }
Exemple #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);
        }
Exemple #20
0
        /// <summary>
        ///		Reads a specified number of floats and copies them into the destination pointer.
        /// </summary>
        /// <remarks>This overload will also copy the values into the specified destination array.</remarks>
        /// <param name="reader"></param>
        /// <param name="count">Number of values to read.</param>
        /// <param name="dest">Pointer to copy the values into.</param>
        /// <param name="destArray">A float array that is to have the values copied into it at the same time as 'dest'.</param>
        protected void ReadFloats(BinaryReader reader, int count, BufferBase dest, float[] destArray)
        {
            // blast the data into the buffer
#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                var pointer = dest.ToFloatPointer();

                for (var i = 0; i < count; i++)
                {
                    var val = ReadFloat(reader);
                    pointer[i]   = val;
                    destArray[i] = val;
                }
            }
        }
Exemple #21
0
        public override void ReadData(int offset, int length, BufferBase dest)
        {
            //Debug.Assert(!isLocked, "Cannot lock this buffer because it is already locked."); //imitating render system specific hardware buffer behaviour
            Debug.Assert(offset >= 0 && (offset + length) <= sizeInBytes, "Buffer overrun while trying to read a software buffer.");

            unsafe
            {
                // get a pointer to the destination intptr
                byte *pDest = (byte *)dest.Ptr;

                // copy the src data to the destination buffer
                for (int i = 0; i < length; i++)
                {
                    pDest[offset + i] = data[offset + i];
                }
            }
        }
Exemple #22
0
        public override void WriteData(int offset, int length, BufferBase src, bool discardWholeBuffer)
        {
            //Debug.Assert( !isLocked, "Cannot lock this buffer because it is already locked." ); //imitating render system specific hardware buffer behaviour
            Debug.Assert(offset >= 0 && (offset + length) <= sizeInBytes, "Buffer overrun while trying to write to a software buffer.");

            unsafe
            {
                // get a pointer to the destination intptr
                byte *pSrc = (byte *)src.Ptr;

                // copy the src data to the destination buffer
                for (int i = 0; i < length; i++)
                {
                    data[offset + i] = pSrc[offset + i];
                }
            }
        }
            public void Convert(BufferBase input, BufferBase output, int offset)
            {
#if !AXIOM_SAFE_ONLY
                unsafe
#endif
                {
                    var inputPtr  = input.ToUIntPointer();
                    var outputPtr = output.ToCol3BPointer();
                    var inp       = inputPtr[offset];

                    outputPtr[offset] = new Col3b
                    {
                        x = (byte)((inp >> 0) & 0xFF),
                        y = (byte)((inp >> 8) & 0xFF),
                        z = (byte)((inp >> 16) & 0xFF),
                    };
                }
            }
Exemple #24
0
        private void _flipEndian(BufferBase pData, int size)
        {
#if AXIOM_BIG_ENDIAN
            byte swapByte;
#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                var ptr = pData.ToBytePointer();
                for (var byteIndex = 0; byteIndex < size / 2; byteIndex++)
                {
                    swapByte                  = ptr[byteIndex];
                    ptr[byteIndex]            = ptr[size - byteIndex - 1];
                    ptr[size - byteIndex - 1] = swapByte;
                }
            }
#endif
        }
Exemple #25
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);
        }
Exemple #26
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();
            }
        }
Exemple #27
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);
        }
Exemple #28
0
        ///<summary>
        ///</summary>
        ///<param name="offset"> </param>
        ///<param name="length"> </param>
        ///<param name="dest"> </param>
        public override void ReadData(int offset, int length, BufferBase dest)
        {
            if (useShadowBuffer)
            {
                // lock the buffer for reading
                var src = shadowBuffer.Lock(offset, length, BufferLocking.ReadOnly);

                // copy that data in there
                Memory.Copy(src, dest, length);

                // unlock the buffer
                shadowBuffer.Unlock();
            }
            else
            {
                Gl.glBindBufferARB(Gl.GL_ELEMENT_ARRAY_BUFFER_ARB, this._bufferId);
                Gl.glGetBufferSubDataARB(Gl.GL_ELEMENT_ARRAY_BUFFER_ARB, new IntPtr(offset), new IntPtr(length), dest.Pin());
                dest.UnPin();
            }
        }
Exemple #29
0
            public void SetBuffer(byte[] _buffer, int _offset)
            {
                DataUsed    = false;
                mCSLEObject = null;
                mIndex      = 0;
                int tindex = _offset;

                mLen    = BufferBase.SReadShort(_buffer, tindex);
                tindex += sizeof(short);
                mCmd    = BufferBase.SReadShort(_buffer, tindex);
                tindex += sizeof(short);
                if (mData == null || mLen > mData.Length)
                {
                    mData = new byte[mLen];
                }
                else
                {
                    mData.Initialize();
                }
                Array.Copy(_buffer, tindex, mData, 0, mLen);
            }
            public void Convert(BufferBase input, BufferBase output, int offset)
            {
#if !AXIOM_SAFE_ONLY
                unsafe
#endif
                {
                    var inputPtr  = input.ToCol3BPointer();
                    var outputPtr = output.ToUIntPointer();
                    var inp       = inputPtr[offset];

                    int xshift = 8, yshift = 16, zshift = 24, ashift = 0;

#if AXIOM_BIG_ENDIAN
                    outputPtr[offset] = ((uint)(0xFF << ashift)) | (((uint)inp.x) << xshift) |
                                        (((uint)inp.y) << yshift) | (((uint)inp.z) << zshift);
#else
                    outputPtr[offset] = ((uint)(0xFF << ashift)) | (((uint)inp.x) << zshift) | (((uint)inp.y) << yshift) |
                                        (((uint)inp.z) << xshift);
#endif
                }
            }
        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();
        }
Exemple #32
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);
            }
        }
        /// <summary>
        /// </summary>
        /// <param name="offset"> </param>
        /// <param name="length"> </param>
        /// <param name="src"> </param>
        /// <param name="discardWholeBuffer"> </param>
        public override void WriteData(int offset, int length, BufferBase src, bool discardWholeBuffer)
        {
            OpenGL.BindBuffer(All.ElementArrayBuffer, this._bufferId);
            GLESConfig.GlCheckError(this);
            // Update the shadow buffer
            if (useShadowBuffer)
            {
                var destData = shadowBuffer.Lock(offset, length, discardWholeBuffer ? BufferLocking.Discard : BufferLocking.Normal);
                Memory.Copy(src, destData, length);
                shadowBuffer.Unlock();
            }

            var srcPtr = src.Ptr;

            if (offset == 0 && length == sizeInBytes)
            {
                OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), ref srcPtr, GLESHardwareBufferManager.GetGLUsage(usage));
                GLESConfig.GlCheckError(this);
            }
            else
            {
                if (discardWholeBuffer)
                {
                    OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLESHardwareBufferManager.GetGLUsage(usage));
                    GLESConfig.GlCheckError(this);
                }
                // Now update the real buffer
                OpenGL.BufferSubData(All.ElementArrayBuffer, new IntPtr(offset), new IntPtr(length), ref srcPtr);
                GLESConfig.GlCheckError(this);
            }

            if (src.Ptr != srcPtr)
            {
                LogManager.Instance.Write("[GLES2] HardwareIndexBuffer.WriteData - buffer pointer modified by GL.BufferData.");
            }
        }
Exemple #34
0
		/// <summary>
		///     Constructor.
		/// </summary>
		/// <param name="owner">Reference to the hardware buffer who owns this stream.</param>
		/// <param name="data">Pointer to the raw data we will be writing to.</param>
		internal BufferStream( HardwareBuffer owner, BufferBase data )
		{
			this.data = data;
			this.owner = owner;
		}
		private void Unpack( ref ColorEx dst, int x, int y, int z, PixelFormat format, BufferBase src, PixelBox srcbox,
		                     int elemsize )
		{
			var data = src + ( elemsize*( ( x ) + ( y )*srcbox.RowPitch + ( z )*srcbox.SlicePitch ) );
			dst = PixelConverter.UnpackColor( format, data );
		}
		/// <summary>
		///		Caches a face group and calculates texture lighting coordinates.
		/// </summary>
		protected int CacheLightGeometry( TextureLight light, BufferBase pIndexesBuf, BufferBase pTexLightMapsBuf,
		                                  BufferBase pVerticesBuf, BspStaticFaceGroup faceGroup )
		{
#if !AXIOM_SAFE_ONLY
			unsafe
#endif
			{
				// Skip sky always
				if ( faceGroup.isSky )
				{
					return 0;
				}

				int idxStart = 0;
				int numIdx = 0;
				int vertexStart = 0;

				if ( faceGroup.type == FaceGroup.FaceList )
				{
					idxStart = faceGroup.elementStart;
					numIdx = faceGroup.numElements;
					vertexStart = faceGroup.vertexStart;
				}
				else if ( faceGroup.type == FaceGroup.Patch )
				{
					idxStart = faceGroup.patchSurf.IndexOffset;
					numIdx = faceGroup.patchSurf.CurrentIndexCount;
					vertexStart = faceGroup.patchSurf.VertexOffset;
				}
				else
				{
					// Unsupported face type
					return 0;
				}

				var idxSize = this.level.Indexes.IndexSize;
				var idxSrc = this.level.Indexes.Lock( idxStart*idxSize, numIdx*idxSize, BufferLocking.ReadOnly );
#if SILVERLIGHT
				var src = idxSrc.ToUShortPointer();
#else
				var src = idxSrc.ToUIntPointer();
#endif

				int maxIndex = 0;
				for ( int i = 0; i < numIdx; i++ )
				{
					var index = (int)src[ i ];
					if ( index > maxIndex )
					{
						maxIndex = index;
					}
				}

				var vertexPos = new Vector3[maxIndex + 1];
				var vertexIsStored = new bool[maxIndex + 1];

				for ( int i = 0; i < numIdx; i++ )
				{
					var index = (int)src[ i ];
					var pVertices = pVerticesBuf.ToBspVertexPointer();
					if ( !vertexIsStored[ index ] )
					{
						vertexPos[ index ] = pVertices[ vertexStart + index ].position;
						vertexIsStored[ index ] = true;
					}
					pVerticesBuf.UnPin();
				}

				Vector2[] texCoors;
				ColorEx[] colors;

				bool res = light.CalculateTexCoordsAndColors( faceGroup.plane, vertexPos, out texCoors, out colors );

				if ( res )
				{
					var pTexLightMaps = pTexLightMapsBuf.ToTextureLightMapPointer();
					for ( int i = 0; i <= maxIndex; i++ )
					{
						pTexLightMaps[ vertexStart + i ] = new TextureLightMap
						                                   {
						                                   	color = Root.Instance.RenderSystem.ConvertColor( colors[ i ] ),
						                                   	textureLightMap = texCoors[ i ]
						                                   };
					}
					pTexLightMapsBuf.UnPin();

					// Offset the indexes here
					// we have to do this now rather than up-front because the
					// indexes are sometimes reused to address different vertex chunks
					if ( this.level.Indexes.Type == IndexType.Size16 )
					{
						var pIndexes = pIndexesBuf.ToUShortPointer();
						for ( int i = 0; i < numIdx; i++ )
						{
							pIndexes[ i ] = (ushort)( src[ i ] + vertexStart );
						}
					}
					else
					{
						var pIndexes = pIndexesBuf.ToUIntPointer();
						for ( int i = 0; i < numIdx; i++ )
						{
							pIndexes[ i ] = (uint)( src[ i ] + vertexStart );
						}
					}
					this.level.Indexes.Unlock();

					// return number of elements
					return numIdx;
				}
				else
				{
					this.level.Indexes.Unlock();

					return 0;
				}
			}
		}
Exemple #37
0
		/// <summary>
		///		Writes a specified number of shorts.
		/// </summary>
		/// <param name="writer"></param>
		/// <param name="count">Number of values to write.</param>
		/// <param name="src">Pointer that holds the values.</param>
		protected void WriteShorts( BinaryWriter writer, int count, BufferBase src )
		{
			// blast the data into the buffer
#if !AXIOM_SAFE_ONLY
			unsafe
#endif
			{
				var pointer = src.ToShortPointer();

				for ( var i = 0; i < count; i++ )
				{
					writer.Write( pointer[ i ] );
				}
			}
		}
		public override void WriteData( int offset, int length, BufferBase src, bool discardWholeBuffer )
		{
			//Update the shadow buffer
			if ( useShadowBuffer )
			{
				var destData = shadowBuffer.Lock( offset, length, discardWholeBuffer ? BufferLocking.Discard : BufferLocking.Normal );
				src = destData;
				shadowBuffer.Unlock();
			}
			
			if ( offset == 0 && length == sizeInBytes )
			{
				GL.BufferData( GLenum.ArrayBuffer, new IntPtr( sizeInBytes ), src.Pin(), GLESHardwareBufferManager.GetGLUsage( usage ) );
				GLESConfig.GlCheckError( this );
			}
			else
			{
				if ( discardWholeBuffer )
				{
					GL.BufferData( GLenum.ArrayBuffer, new IntPtr( sizeInBytes ), IntPtr.Zero, GLESHardwareBufferManager.GetGLUsage( usage ) );
					GLESConfig.GlCheckError( this );
				}
				GL.BufferSubData( GLenum.ArrayBuffer, new IntPtr( offset ), new IntPtr( length ), src.Pin() );
				GLESConfig.GlCheckError( this );
			}
		}
		/// <summary>
		/// </summary>
		/// <param name="offset"> </param>
		/// <param name="length"> </param>
		/// <param name="src"> </param>
		/// <param name="discardWholeBuffer"> </param>
		public override void WriteData( int offset, int length, BufferBase src, bool discardWholeBuffer )
		{
			OpenGL.BindBuffer( All.ElementArrayBuffer, this._bufferId );
			GLESConfig.GlCheckError( this );
			// Update the shadow buffer
			if ( useShadowBuffer )
			{
				var destData = shadowBuffer.Lock( offset, length, discardWholeBuffer ? BufferLocking.Discard : BufferLocking.Normal );
				Memory.Copy( src, destData, length );
				shadowBuffer.Unlock();
			}
			
			var srcPtr = src.Ptr;
			if ( offset == 0 && length == sizeInBytes )
			{
				OpenGL.BufferData( All.ElementArrayBuffer, new IntPtr( sizeInBytes ), ref srcPtr, GLESHardwareBufferManager.GetGLUsage( usage ) );
				GLESConfig.GlCheckError( this );
			}
			else
			{
				if ( discardWholeBuffer )
				{
					OpenGL.BufferData( All.ElementArrayBuffer, new IntPtr( sizeInBytes ), IntPtr.Zero, GLESHardwareBufferManager.GetGLUsage( usage ) );
					GLESConfig.GlCheckError( this );
				}
				// Now update the real buffer
				OpenGL.BufferSubData( All.ElementArrayBuffer, new IntPtr( offset ), new IntPtr( length ), ref srcPtr );
				GLESConfig.GlCheckError( this );
			}
			
			if ( src.Ptr != srcPtr )
			{
				LogManager.Instance.Write( "[GLES2] HardwareIndexBuffer.WriteData - buffer pointer modified by GL.BufferData." );
			}
		}
		/// <summary>
		/// </summary>
		/// <param name="vertexSize"> </param>
		/// <param name="numVertices"> </param>
		/// <param name="usage"> </param>
		public GLDefaultHardwareVertexBuffer(VertexDeclaration declaration, int numVertices, BufferUsage usage)
			: base( null, declaration, numVertices, usage, true, false )
		{
			this._data = new byte[ declaration.GetVertexSize() * numVertices ];
			this._dataPtr = BufferBase.Wrap( this._data );
		}
		protected override BufferBase LockImpl( int offset, int length, BufferLocking locking )
		{
			if ( IsLocked )
			{
				throw new AxiomException( "Invalid attempt to lock an index buffer that has already been locked." );
			}
			BufferBase retPtr;
			var glBufManager = ( HardwareBufferManager.Instance as GLESHardwareBufferManager );
			
			//Try to use scratch buffers for smaller buffers
			if ( length < glBufManager.MapBufferThreshold )
			{
				retPtr = glBufManager.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 )
					{
						//have to read back the data before returning the pointer
						this.ReadData( offset, length, retPtr );
					}
				}
			}
			else
			{
				throw new AxiomException( "Invalid Buffer lockSize" );
			}
			
			if ( retPtr == null )
			{
				GLenum access = GLenum.Zero;
				( Root.Instance.RenderSystem as GLESRenderSystem ).BindGLBuffer( GLenum.ArrayBuffer, this._bufferID );
				
				if ( locking == BufferLocking.Discard )
				{
					//Discard the buffer
					GL.BufferData( GLenum.ArrayBuffer, new IntPtr( sizeInBytes ), IntPtr.Zero, GLESHardwareBufferManager.GetGLUsage( usage ) );
					GLESConfig.GlCheckError( this );
				}
				if ( ( usage & BufferUsage.WriteOnly ) == BufferUsage.WriteOnly )
				{
					access = GLenum.WriteOnlyOes;
				}
				
				var pbuffer = GL.Oes.MapBuffer( GLenum.ArrayBuffer, access );
				GLESConfig.GlCheckError( this );
				
				if ( pbuffer == IntPtr.Zero )
				{
					throw new AxiomException( "Vertex Buffer: Out of memory" );
				}
				
				//return offsetted
				retPtr = BufferBase.Wrap( pbuffer, sizeInBytes ) + offset;
				this._lockedToScratch = false;
			}
			isLocked = true;
			return retPtr;
		}
		public override void WriteData( int offset, int length, BufferBase source, bool discardWholeBuffer )
		{
			throw new AxiomException( "Writing a byte range is not implemented. Use BlitToMemory." );
		}
		public override void WriteData( int offset, int length, BufferBase src, bool discardWholeBuffer )
		{
			// There is no functional interface in D3D, just do via manual 
			// lock, copy & unlock

			// lock the buffer real quick
			var dest = Lock( offset, length, discardWholeBuffer ? BufferLocking.Discard : BufferLocking.Normal );

			// copy that data in there
			Memory.Copy( src, dest, length );

			// unlock the buffer
			Unlock();
		}
		public override void ReadData( int offset, int length, BufferBase dest )
		{
			throw new AxiomException( "Reading a byte range is not implemented. Use BlitToMemory." );
		}
		/// <summary>
		///
		/// </summary>
		/// <param name="offset"></param>
		/// <param name="length"></param>
		/// <param name="dest"></param>
		public override void ReadData( int offset, int length, BufferBase dest )
		{
			if ( useShadowBuffer )
			{
				// lock the buffer for reading
				var src = shadowBuffer.Lock( offset, length, BufferLocking.ReadOnly );

				// copy that data in there
				Memory.Copy( src, dest, length );

				// unlock the buffer
				shadowBuffer.Unlock();
			}
			else
			{
				Gl.glBindBufferARB( Gl.GL_ARRAY_BUFFER_ARB, this.bufferID );

				Gl.glGetBufferSubDataARB( Gl.GL_ARRAY_BUFFER_ARB, new IntPtr( offset ), new IntPtr( length ), dest.Pin() );
				// TAO 2.0
				dest.UnPin();
				//Gl.glGetBufferSubDataARB(
				//    Gl.GL_ARRAY_BUFFER_ARB,
				//    offset,
				//    length,
				//    dest );
			}
		}
		/// <summary>
		///
		/// </summary>
		/// <param name="offset"></param>
		/// <param name="length"></param>
		/// <param name="src"></param>
		/// <param name="discardWholeBuffer"></param>
		public override void WriteData( int offset, int length, BufferBase src, bool discardWholeBuffer )
		{
			Gl.glBindBufferARB( Gl.GL_ARRAY_BUFFER_ARB, this.bufferID );

			if ( useShadowBuffer )
			{
				// lock the buffer for reading
				var dest = shadowBuffer.Lock( offset, length, discardWholeBuffer ? BufferLocking.Discard : BufferLocking.Normal );

				// copy that data in there
				Memory.Copy( src, dest, length );

				// unlock the buffer
				shadowBuffer.Unlock();
			}

			if ( discardWholeBuffer )
			{
				Gl.glBufferDataARB( Gl.GL_ARRAY_BUFFER_ARB, new IntPtr( sizeInBytes ), IntPtr.Zero, GLHelper.ConvertEnum( usage ) );
				// TAO 2.0
				//Gl.glBufferDataARB( Gl.GL_ARRAY_BUFFER_ARB,
				//    sizeInBytes,
				//    IntPtr.Zero,
				//    GLHelper.ConvertEnum( usage ) );
			}

			Gl.glBufferSubDataARB( Gl.GL_ARRAY_BUFFER_ARB, new IntPtr( offset ), new IntPtr( length ), src.Pin() ); // TAO 2.0
			src.UnPin();
			//Gl.glBufferSubDataARB(
			//    Gl.GL_ARRAY_BUFFER_ARB,
			//    offset,
			//    length,
			//    src );
		}
		protected void WriteGeometryVertexBufferData( BinaryWriter writer, int count, BufferBase buf )
		{
			var start_offset = writer.Seek( 0, SeekOrigin.Current );
			WriteChunk( writer, MeshChunkID.GeometryVertexBufferData, 0 );

			WriteBytes( writer, count, buf );

			var end_offset = writer.Seek( 0, SeekOrigin.Current );
			writer.Seek( (int)start_offset, SeekOrigin.Begin );
			WriteChunk( writer, MeshChunkID.GeometryVertexBufferData, (int)( end_offset - start_offset ) );
			writer.Seek( (int)end_offset, SeekOrigin.Begin );
		}
		/// <summary>
		/// </summary>
		/// <param name="offset"> </param>
		/// <param name="length"> </param>
		/// <param name="src"> </param>
		/// <param name="discardWholeBuffer"> </param>
		public override void WriteData( int offset, int length, BufferBase src, bool discardWholeBuffer )
		{
			Contract.Requires( ( offset + length ) <= sizeInBytes );
			// ignore discard, memory is not guaranteed to be zeroised
			Memory.Copy( src, this._dataPtr + offset, length );
		}
		public int StitchEdge( Neighbor neighbor, int hiLOD, int loLOD, bool omitFirstTri, bool omitLastTri, BufferBase ppIdx )
#endif
		{
			Debug.Assert( loLOD > hiLOD, "TerrainZoneRenderable.StitchEdge" );
			/*
			Now do the stitching; we can stitch from any level to any level.
			The stitch pattern is like this for each pair of vertices in the lower LOD
			(excuse the poor ascii art):

			lower LOD
			*-----------*
			|\  \ 3 /  /|
			|1\2 \ / 4/5|
			*--*--*--*--*
			higher LOD

			The algorithm is, for each pair of lower LOD vertices:
			1. Iterate over the higher LOD vertices, generating tris connected to the
			first lower LOD vertex, up to and including 1/2 the span of the lower LOD
			over the higher LOD (tris 1-2). Skip the first tri if it is on the edge
			of the tile and that edge is to be stitched itself.
			2. Generate a single tri for the middle using the 2 lower LOD vertices and
			the middle vertex of the higher LOD (tri 3).
			3. Iterate over the higher LOD vertices from 1/2 the span of the lower LOD
			to the end, generating tris connected to the second lower LOD vertex
			(tris 4-5). Skip the last tri if it is on the edge of a tile and that
			edge is to be stitched itself.

			The same algorithm works for all edges of the patch; stitching is done
			clockwise so that the origin and steps used change, but the general
			approach does not.
			*/

			// Get pointer to be updated
			var pIdx = ppIdx.ToUShortPointer();
			var idx = 0;

			// Work out the steps ie how to increment indexes
			// Step from one vertex to another in the high detail version
			var step = 1 << hiLOD;
			// Step from one vertex to another in the low detail version
			var superstep = 1 << loLOD;
			// Step half way between low detail steps
			var halfsuperstep = superstep >> 1;

			// Work out the starting points and sign of increments
			// We always work the strip clockwise
			int startx, starty, endx, rowstep;
			startx = starty = endx = rowstep = 0;
			var horizontal = false;
			switch ( neighbor )
			{
				case Neighbor.NORTH:
					startx = starty = 0;
					endx = this.mOptions.tileSize - 1;
					rowstep = step;
					horizontal = true;
					break;
				case Neighbor.SOUTH:
					// invert x AND y direction, helps to keep same winding
					startx = starty = this.mOptions.tileSize - 1;
					endx = 0;
					rowstep = -step;
					step = -step;
					superstep = -superstep;
					halfsuperstep = -halfsuperstep;
					horizontal = true;
					break;
				case Neighbor.EAST:
					startx = 0;
					endx = this.mOptions.tileSize - 1;
					starty = this.mOptions.tileSize - 1;
					rowstep = -step;
					horizontal = false;
					break;
				case Neighbor.WEST:
					startx = this.mOptions.tileSize - 1;
					endx = 0;
					starty = 0;
					rowstep = step;
					step = -step;
					superstep = -superstep;
					halfsuperstep = -halfsuperstep;
					horizontal = false;
					break;
			}

			var numIndexes = 0;

			for ( var j = startx; j != endx; j += superstep )
			{
				int k;
				for ( k = 0; k != halfsuperstep; k += step )
				{
					var jk = j + k;
					//skip the first bit of the corner?
					if ( j != startx || k != 0 || !omitFirstTri )
					{
						if ( horizontal )
						{
							pIdx[ idx++ ] = Index( jk, starty + rowstep );
							numIndexes++; // original order: 2
							pIdx[ idx++ ] = Index( jk + step, starty + rowstep );
							numIndexes++; // original order: 3
							pIdx[ idx++ ] = Index( j, starty );
							numIndexes++; // original order: 1
						}
						else
						{
							pIdx[ idx++ ] = Index( starty + rowstep, jk );
							numIndexes++; // original order: 2
							pIdx[ idx++ ] = Index( starty + rowstep, jk + step );
							numIndexes++; // original order: 3
							pIdx[ idx++ ] = Index( starty, j );
							numIndexes++; // original order: 1
						}
					}
				}

				// Middle tri
				if ( horizontal )
				{
					pIdx[ idx++ ] = Index( j + halfsuperstep, starty + rowstep );
					numIndexes++; // original order: 2
					pIdx[ idx++ ] = Index( j + superstep, starty );
					numIndexes++; // original order: 3
					pIdx[ idx++ ] = Index( j, starty );
					numIndexes++; // original order: 1
				}
				else
				{
					pIdx[ idx++ ] = Index( starty + rowstep, j + halfsuperstep );
					numIndexes++; // original order: 2
					pIdx[ idx++ ] = Index( starty, j + superstep );
					numIndexes++; // original order: 3
					pIdx[ idx++ ] = Index( starty, j );
					numIndexes++; // original order: 1
				}

				for ( k = halfsuperstep; k != superstep; k += step )
				{
					var jk = j + k;
					if ( j != endx - superstep || k != superstep - step || !omitLastTri )
					{
						if ( horizontal )
						{
							pIdx[ idx++ ] = Index( jk, starty + rowstep );
							numIndexes++; // original order: 2
							pIdx[ idx++ ] = Index( jk + step, starty + rowstep );
							numIndexes++; // original order: 3
							pIdx[ idx++ ] = Index( j + superstep, starty );
							numIndexes++; // original order: 1
						}
						else
						{
							pIdx[ idx++ ] = Index( starty + rowstep, jk );
							numIndexes++; // original order: 2
							pIdx[ idx++ ] = Index( starty + rowstep, jk + step );
							numIndexes++; // original order: 3
							pIdx[ idx++ ] = Index( starty, j + superstep );
							numIndexes++; // original order: 1
						}
					}
				}
			}

			ppIdx.Ptr += idx*sizeof ( ushort );

			return numIndexes;
		}
		/// <summary>
		/// </summary>
		/// <param name="offset"> </param>
		/// <param name="length"> </param>
		/// <param name="dest"> </param>
		public override void ReadData( int offset, int length, BufferBase dest )
		{
			Contract.Requires( ( offset + length ) <= sizeInBytes );
			Memory.Copy( this._dataPtr + offset, dest, length );
		}
		public override void ReadData( int offset, int length, BufferBase dest )
		{
			if ( useShadowBuffer )
			{
				var srcData = shadowBuffer.Lock( offset, length, BufferLocking.ReadOnly );
				dest = srcData;
				shadowBuffer.Unlock();
			}
			else
			{
				throw new AxiomException( "Read hardware buffer is not supported" );
			}
		}
Exemple #52
0
		private void _flipEndian( BufferBase pData, int size, int count )
		{
#if AXIOM_BIG_ENDIAN
			for ( var index = 0; index < count; index++ )
			{
				using ( var data = pData + ( index * size ) )
					_flipEndian( data, size );
			}
#endif
		}
		unsafe public int StitchEdge( Neighbor neighbor, int hiLOD, int loLOD, bool omitFirstTri, bool omitLastTri, BufferBase ppIdx )
Exemple #54
0
		private void _flipEndian( BufferBase pData, int size )
		{
#if AXIOM_BIG_ENDIAN
			byte swapByte;
#if !AXIOM_SAFE_ONLY
			unsafe
#endif
			{
				var ptr = pData.ToBytePointer();
				for ( var byteIndex = 0; byteIndex < size / 2; byteIndex++ )
				{
					swapByte = ptr[ byteIndex ];
					ptr[ byteIndex ] = ptr[ size - byteIndex - 1 ];
					ptr[ size - byteIndex - 1 ] = swapByte;
				}
			}
#endif
		}
		/// <summary>
		///		Caches a face group for imminent rendering.
		/// </summary>
		protected int CacheGeometry( BufferBase indexes, BspStaticFaceGroup faceGroup )
		{
			// Skip sky always
			if ( faceGroup.isSky )
			{
				return 0;
			}

			int idxStart = 0;
			int numIdx = 0;
			int vertexStart = 0;

			if ( faceGroup.type == FaceGroup.FaceList )
			{
				idxStart = faceGroup.elementStart;
				numIdx = faceGroup.numElements;
				vertexStart = faceGroup.vertexStart;
			}
			else if ( faceGroup.type == FaceGroup.Patch )
			{
				idxStart = faceGroup.patchSurf.IndexOffset;
				numIdx = faceGroup.patchSurf.CurrentIndexCount;
				vertexStart = faceGroup.patchSurf.VertexOffset;
			}
			else
			{
				// Unsupported face type
				return 0;
			}

#if !AXIOM_SAFE_ONLY
			unsafe
#endif
			{
				// Offset the indexes here
				// we have to do this now rather than up-front because the
				// indexes are sometimes reused to address different vertex chunks
				var idxSize = this.level.Indexes.IndexSize;
				var idxSrc = this.level.Indexes.Lock( idxStart*idxSize, numIdx*idxSize, BufferLocking.ReadOnly );
				if ( this.level.Indexes.Type == IndexType.Size16 )
				{
					var src = idxSrc.ToUShortPointer();
					var pIndexes = indexes.ToUShortPointer();
					for ( int i = 0; i < numIdx; i++ )
					{
						pIndexes[ i ] = (ushort)( src[ i ] + vertexStart );
					}
				}
				else
				{
					var src = idxSrc.ToUIntPointer();
					var pIndexes = indexes.ToUIntPointer();
					for ( int i = 0; i < numIdx; i++ )
					{
						pIndexes[ i ] = (uint)( src[ i ] + vertexStart );
					}
				}
				this.level.Indexes.Unlock();
			}

			// return number of elements
			return numIdx;
		}
		public override void ReadData( int offset, int length, BufferBase dest )
		{
			// There is no functional interface in D3D, just do via manual 
			// lock, copy & unlock

			// lock the buffer for reading
			var src = Lock( offset, length, BufferLocking.ReadOnly );

			// copy that data in there
			Memory.Copy( src, dest, length );

			// unlock the buffer
			Unlock();
		}
		/// <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;
		}
		/// <summary>
		/// </summary>
		/// <param name="idxType"> </param>
		/// <param name="numIndexes"> </param>
		/// <param name="usage"> </param>
		public GLDefaultHardwareIndexBuffer( IndexType idxType, int numIndexes, BufferUsage usage )
			: base( null, idxType, numIndexes, usage, true, false ) // always software, never shadowed
		{
			this._data = new byte[ sizeInBytes ];
			this._dataPtr = BufferBase.Wrap( this._data );
		}
		public D3D9HardwareIndexBuffer( HardwareBufferManagerBase manager, IndexType type, int numIndices, BufferUsage usage,
		                                bool useSystemMemory, bool useShadowBuffer )
			: base( manager, type, numIndices, 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();
		}
		/// <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;
		}