void* GLESHardwareIndexBuffer::lockImpl(size_t offset,
                                            size_t length,
                                            LockOptions options)
    {
        if(mIsLocked)
        {
            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
                        "Invalid attempt to lock an index buffer that has already been locked",
                        "GLESHardwareIndexBuffer::lock");
        }

        void* retPtr = 0;
        GLenum access = 0;
		GLESHardwareBufferManager* glBufManager = static_cast<GLESHardwareBufferManager*>(HardwareBufferManager::getSingletonPtr());

        if(length < glBufManager->getGLMapBufferThreshold())
        {
            retPtr = glBufManager->allocateScratch((uint32)length);
            if (retPtr)
            {
                mLockedToScratch = true;
                mScratchOffset = offset;
                mScratchSize = length;
                mScratchPtr = retPtr;
                mScratchUploadOnUnlock = (options != HBL_READ_ONLY);

                if (options != HBL_DISCARD)
                {
                    readData(offset, length, retPtr);
                }
            }
        }
        else
        {
            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
                        "Invalid Buffer lockSize",
                        "GLESHardwareIndexBuffer::lock");
        }

#if defined(GL_GLEXT_PROTOTYPES)
        if (!retPtr)
		{
			glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mBufferId );
			// Use glMapBuffer
			if(options == HBL_DISCARD)
			{
				// Discard the buffer
				glBufferData(GL_ELEMENT_ARRAY_BUFFER, mSizeInBytes, NULL, 
                                GLESHardwareBufferManager::getGLUsage(mUsage));
			}
			if (mUsage & HBU_WRITE_ONLY)
				access = GL_WRITE_ONLY_OES;
            
			void* pBuffer = glMapBufferOES( GL_ELEMENT_ARRAY_BUFFER, access );
            
			if(pBuffer == 0)
			{
				OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
                            "Index Buffer: Out of memory", 
                            "GLESHardwareIndexBuffer::lock");
			}
            
			// return offsetted
			retPtr = static_cast<void*>(static_cast<unsigned char*>(pBuffer) + offset);
            
			mLockedToScratch = false;
		}
		mIsLocked = true;
#endif
        
        return retPtr;
    }
    void* GLESHardwareVertexBuffer::lockImpl(size_t offset,
                                           size_t length,
                                           LockOptions options)
    {
        GLenum access = 0;

        if (mIsLocked)
        {
            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
                        "Invalid attempt to lock an index buffer that has already been locked",
                        "GLESHardwareVertexBuffer::lock");
        }

        void* retPtr = 0;

		GLESHardwareBufferManager* glBufManager = static_cast<GLESHardwareBufferManager*>(HardwareBufferManager::getSingletonPtr());

		// Try to use scratch buffers for smaller buffers
        if (length < glBufManager->getGLMapBufferThreshold())
        {
			// if this fails, we fall back on mapping
            retPtr = glBufManager->allocateScratch((uint32)length);

            if (retPtr)
            {
                mLockedToScratch = true;
                mScratchOffset = offset;
                mScratchSize = length;
                mScratchPtr = retPtr;
                mScratchUploadOnUnlock = (options != HBL_READ_ONLY);

                if (options != HBL_DISCARD)
                {
					// have to read back the data before returning the pointer
                    readData(offset, length, retPtr);
                }
            }
        }
        else
        {
            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
                        "Invalid Buffer lockSize",
                        "GLESHardwareVertexBuffer::lock");
        }

#if GL_OES_mapbuffer
        if (!retPtr)
		{
			// Use glMapBuffer
			glBindBuffer( GL_ARRAY_BUFFER, mBufferId );
			// Use glMapBuffer
			if(options == HBL_DISCARD)
			{
				// Discard the buffer
				glBufferData(GL_ARRAY_BUFFER, mSizeInBytes, NULL, 
                                GLESHardwareBufferManager::getGLUsage(mUsage));
                
			}
			if (mUsage & HBU_WRITE_ONLY)
				access = GL_WRITE_ONLY_OES;
            
			void* pBuffer = glMapBufferOES( GL_ARRAY_BUFFER, access);
            
			if(pBuffer == 0)
			{
				OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
                            "Vertex Buffer: Out of memory", "GLESHardwareVertexBuffer::lock");
			}
            
			// return offsetted
			retPtr = static_cast<void*>(
				static_cast<unsigned char*>(pBuffer) + offset);
            
			mLockedToScratch = false;
		}
#endif
		mIsLocked = true;
        return retPtr;
    }