/// <summary>
 /// </summary>
 protected override void UnlockImpl()
 {
     if (this._lockedToScratch)
     {
         if (this._scratchUploadOnUnlock)
         {
             // have to write the data back to vertex buffer
             this.WriteData(this._scratchOffset, this._scratchSize, this._scratchPtr, this._scratchOffset == 0 && this._scratchSize == sizeInBytes);
         }
         // deallocate from scratch buffer
         ((GLES2HardwareBufferManager)HardwareBufferManager.Instance).DeallocateScratch(this._scratchPtr);
         this._lockedToScratch = false;
     }
     else
     {
         OpenGL.BindBuffer(All.ElementArrayBuffer, this._bufferId);
         GLES2Config.GlCheckError(this);
         if (!OpenGLOES.UnmapBuffer(All.ElementArrayBuffer))
         {
             throw new AxiomException("Buffer data corrupted, please reload");
         }
     }
     isLocked = false;
 }
        /// <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 = ((GLES2HardwareBufferManager)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);
                GLES2Config.GlCheckError(this);
                // Use glMapBuffer
                if (locking == BufferLocking.Discard)
                {
                    OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLES2HardwareBufferManager.GetGLUsage(usage));
                    GLES2Config.GlCheckError(this);
                }
                if ((usage & BufferUsage.WriteOnly) != 0)
                {
                    access = All.WriteOnlyOes;
                }

                IntPtr pBuffer = OpenGLOES.MapBuffer(All.ElementArrayBuffer, access);
                GLES2Config.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);
        }