//-----------------------------------------------------------------------------
void D3D11HardwarePixelBuffer::unlockImpl(void)
{
    if(mUsage == HBU_STATIC)
        _unmapstagingbuffer();
    else if(mUsage & HBU_DYNAMIC)
    {
        if(mCurrentLockOptions == HBL_READ_ONLY || mCurrentLockOptions == HBL_NORMAL || mCurrentLockOptions == HBL_WRITE_ONLY)
        {
            size_t sizeinbytes = D3D11Mappings::_getSizeInBytes(mParentTexture->getFormat(), mParentTexture->getWidth(), mParentTexture->getHeight());
            PixelBox box;
            _map(mParentTexture->getTextureResource(), D3D11_MAP_WRITE_DISCARD, box);
            void *data = box.data;

            memcpy(data, mCurrentLock.data, sizeinbytes);

            // unmap the texture and the staging buffer
            _unmap(mParentTexture->getTextureResource());

            _unmapstagingbuffer(false);
        }
        else
            _unmap(mParentTexture->getTextureResource());
    }
    else
        _unmapstaticbuffer();

    _genMipmaps();
}
	//-----------------------------------------------------------------------------  
	void D3D10HardwarePixelBuffer::blitFromMemory(const PixelBox &src, const Image::Box &dstBox)
	{
		bool isDds = false;
		switch(mFormat)
		{
		case PF_DXT1:
		case PF_DXT2:
		case PF_DXT3:
		case PF_DXT4:
		case PF_DXT5:
			isDds = true;
			break;
		default:

			break;
		}

		if (isDds && (dstBox.getWidth() % 4 != 0 || dstBox.getHeight() % 4 != 0 ))
		{
			return;
		}


		// for scoped deletion of conversion buffer
		MemoryDataStreamPtr buf;
		PixelBox converted = src;

		D3D10_BOX dstBoxDx10 = OgreImageBoxToDx10Box(dstBox);

		// convert to pixelbuffer's native format if necessary
		if (src.format != mFormat)
		{
			buf.bind(new MemoryDataStream(
				PixelUtil::getMemorySize(src.getWidth(), src.getHeight(), src.getDepth(),
				mFormat)));
			converted = PixelBox(src.getWidth(), src.getHeight(), src.getDepth(), mFormat, buf->getPtr());
			PixelUtil::bulkPixelConversion(src, converted);
		}

		// In d3d10 the Row Pitch is defined as: "The size of one row of the source data" and not 
		// the same as the OGRE row pitch - meaning that we need to multiple the OGRE row pitch 
		// with the size in bytes of the element to get the d3d10 row pitch. 
		UINT d3dRowPitch = static_cast<UINT>(converted.rowPitch) * static_cast<UINT>(PixelUtil::getNumElemBytes(mFormat));


		switch(mParentTexture->getTextureType()) {
		case TEX_TYPE_1D:
			{

				mDevice->UpdateSubresource( 
					mParentTexture->GetTex1D(), 
					0,
					&dstBoxDx10,
					converted.data,
					0,
					0 );
				if (mDevice.isError())
				{
					String errorDescription = mDevice.getErrorDescription();
					OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, 
						"D3D10 device cannot update 1d subresource\nError Description:" + errorDescription,
						"D3D10HardwarePixelBuffer::blitFromMemory");
				}
			}
			break;
		case TEX_TYPE_CUBE_MAP:
		case TEX_TYPE_2D:
			{
				mDevice->UpdateSubresource( 
					mParentTexture->GetTex2D(), 
					static_cast<UINT>(mSubresourceIndex),
					&dstBoxDx10,
					converted.data,
					d3dRowPitch,
					mFace );
				if (mDevice.isError())
				{
					String errorDescription = mDevice.getErrorDescription();
					OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, 
						"D3D10 device cannot update 2d subresource\nError Description:" + errorDescription,
						"D3D10HardwarePixelBuffer::blitFromMemory");
				}
			}
			break;
		case TEX_TYPE_3D:
			{
				mDevice->UpdateSubresource( 
					mParentTexture->GetTex2D(), 
					static_cast<UINT>(mSubresourceIndex),
					&dstBoxDx10,
					converted.data,
					d3dRowPitch,
					static_cast<UINT>(converted.slicePitch)
					);
				if (mDevice.isError())
				{
					String errorDescription = mDevice.getErrorDescription();
					OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, 
						"D3D10 device cannot update 3d subresource\nError Description:" + errorDescription,
						"D3D10HardwarePixelBuffer::blitFromMemory");
				}
			}
			break;
		}


		if (!isDds)
		{
			_genMipmaps();
		}

	}
	void D3D10HardwarePixelBuffer::blit(const HardwarePixelBufferSharedPtr &rsrc, const Image::Box &srcBox, const Image::Box &dstBox)
	{
		if (
			(srcBox.getWidth() != dstBox.getWidth())
			|| (srcBox.getHeight() != dstBox.getHeight())
			|| (srcBox.getDepth() != dstBox.getDepth())
			)
		{
			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, 
				"D3D10 device cannot copy a subresource - source and dest size are not the same and they have to be the same in DX10.",
				"D3D10HardwarePixelBuffer::blit");
		}

		D3D10_BOX srcBoxDx10 = OgreImageBoxToDx10Box(srcBox);


		D3D10HardwarePixelBuffer * rsrcDx10 = static_cast<D3D10HardwarePixelBuffer *>(rsrc.get());

		switch(mParentTexture->getTextureType()) {
		case TEX_TYPE_1D:
			{

				mDevice->CopySubresourceRegion(
					mParentTexture->GetTex1D(), 
					static_cast<UINT>(mSubresourceIndex),
					static_cast<UINT>(dstBox.left),
					0,
					0,
					rsrcDx10->mParentTexture->GetTex1D(),
					static_cast<UINT>(rsrcDx10->mSubresourceIndex),
					&srcBoxDx10);
				if (mDevice.isError())
				{
					String errorDescription = mDevice.getErrorDescription();
					OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, 
						"D3D10 device cannot copy 1d subresource Region\nError Description:" + errorDescription,
						"D3D10HardwarePixelBuffer::blit");
				}			
			}
			break;
		case TEX_TYPE_CUBE_MAP:
		case TEX_TYPE_2D:
			{
				mDevice->CopySubresourceRegion(
					mParentTexture->GetTex2D(), 
					static_cast<UINT>(mSubresourceIndex),
					static_cast<UINT>(dstBox.left),
					static_cast<UINT>(dstBox.top),
					mFace,
					rsrcDx10->mParentTexture->GetTex2D(),
					static_cast<UINT>(rsrcDx10->mSubresourceIndex),
					&srcBoxDx10);
				if (mDevice.isError())
				{
					String errorDescription = mDevice.getErrorDescription();
					OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, 
						"D3D10 device cannot copy 2d subresource Region\nError Description:" + errorDescription,
						"D3D10HardwarePixelBuffer::blit");
				}
			}
			break;
		case TEX_TYPE_3D:
			{
				mDevice->CopySubresourceRegion(
					mParentTexture->GetTex2D(), 
					static_cast<UINT>(mSubresourceIndex),
					static_cast<UINT>(dstBox.left),
					static_cast<UINT>(dstBox.top),
					static_cast<UINT>(dstBox.front),
					rsrcDx10->mParentTexture->GetTex2D(),
					static_cast<UINT>(rsrcDx10->mSubresourceIndex),
					&srcBoxDx10);
				if (mDevice.isError())
				{
					String errorDescription = mDevice.getErrorDescription();
					OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, 
						"D3D10 device cannot copy 3d subresource Region\nError Description:" + errorDescription,
						"D3D10HardwarePixelBuffer::blit");
				}
			}
			break;
		}


		_genMipmaps();

	}
//-----------------------------------------------------------------------------
void D3D11HardwarePixelBuffer::blitFromMemory(const PixelBox &src, const Image::Box &dstBox)
{
    bool isDds = false;
    switch(mFormat)
    {
    case PF_DXT1:
    case PF_DXT2:
    case PF_DXT3:
    case PF_DXT4:
    case PF_DXT5:
        isDds = true;
        break;
    default:

        break;
    }

    if (isDds && (dstBox.getWidth() % 4 != 0 || dstBox.getHeight() % 4 != 0 ))
    {
        return;
    }


    // for scoped deletion of conversion buffer
    MemoryDataStreamPtr buf;
    PixelBox converted = src;

    D3D11_BOX dstBoxDx11 = OgreImageBoxToDx11Box(dstBox);
    dstBoxDx11.front = 0;
    dstBoxDx11.back = converted.getDepth();

    // convert to pixelbuffer's native format if necessary
    if (src.format != mFormat)
    {
        buf.bind(new MemoryDataStream(
                     PixelUtil::getMemorySize(src.getWidth(), src.getHeight(), src.getDepth(),
                                              mFormat)));
        converted = PixelBox(src.getWidth(), src.getHeight(), src.getDepth(), mFormat, buf->getPtr());
        PixelUtil::bulkPixelConversion(src, converted);
    }

    if (mUsage & HBU_DYNAMIC)
    {
        size_t sizeinbytes;
        if (PixelUtil::isCompressed(converted.format))
        {
            // D3D wants the width of one row of cells in bytes
            if (converted.format == PF_DXT1)
            {
                // 64 bits (8 bytes) per 4x4 block
                sizeinbytes = std::max<size_t>(1, converted.getWidth() / 4) * std::max<size_t>(1, converted.getHeight() / 4) * 8;
            }
            else
            {
                // 128 bits (16 bytes) per 4x4 block
                sizeinbytes = std::max<size_t>(1, converted.getWidth() / 4) * std::max<size_t>(1, converted.getHeight() / 4) * 16;
            }
        }
        else
        {
            sizeinbytes = converted.getHeight() * converted.getWidth() * PixelUtil::getNumElemBytes(converted.format);
        }

        const Ogre::PixelBox &locked = lock(dstBox, HBL_DISCARD);

        memcpy(locked.data, converted.data, sizeinbytes);

        unlock();
    }
    else
    {
        size_t rowWidth;
        if (PixelUtil::isCompressed(converted.format))
        {
            // D3D wants the width of one row of cells in bytes
            if (converted.format == PF_DXT1)
            {
                // 64 bits (8 bytes) per 4x4 block
                rowWidth = (converted.rowPitch / 4) * 8;
            }
            else
            {
                // 128 bits (16 bytes) per 4x4 block
                rowWidth = (converted.rowPitch / 4) * 16;
            }
        }
        else
        {
            rowWidth = converted.rowPitch * PixelUtil::getNumElemBytes(converted.format);
        }

        switch(mParentTexture->getTextureType()) {
        case TEX_TYPE_1D:
        {
            D3D11RenderSystem* rsys = reinterpret_cast<D3D11RenderSystem*>(Root::getSingleton().getRenderSystem());
            if (rsys->_getFeatureLevel() >= D3D_FEATURE_LEVEL_10_0)
            {
                mDevice.GetImmediateContext()->UpdateSubresource(
                    mParentTexture->GetTex1D(),
                    0,
                    &dstBoxDx11,
                    converted.data,
                    rowWidth,
                    0 );
                if (mDevice.isError())
                {
                    String errorDescription = mDevice.getErrorDescription();
                    OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                                "D3D11 device cannot update 1d subresource\nError Description:" + errorDescription,
                                "D3D11HardwarePixelBuffer::blitFromMemory");
                }
                break; // For Feature levels that do not support 1D textures, revert to creating a 2D texture.
            }
        }
        case TEX_TYPE_CUBE_MAP:
        case TEX_TYPE_2D:
        {
            mDevice.GetImmediateContext()->UpdateSubresource(
                mParentTexture->GetTex2D(),
                D3D11CalcSubresource(static_cast<UINT>(mSubresourceIndex), mFace, mParentTexture->getNumMipmaps()+1),
                &dstBoxDx11,
                converted.data,
                rowWidth,
                0 );
            if (mDevice.isError())
            {
                String errorDescription = mDevice.getErrorDescription();
                OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                            "D3D11 device cannot update 2d subresource\nError Description:" + errorDescription,
                            "D3D11HardwarePixelBuffer::blitFromMemory");
            }
        }
        break;
        case TEX_TYPE_2D_ARRAY:
        {
            mDevice.GetImmediateContext()->UpdateSubresource(
                mParentTexture->GetTex2D(),
                D3D11CalcSubresource(static_cast<UINT>(mSubresourceIndex), src.front, mParentTexture->getNumMipmaps()+1),
                &dstBoxDx11,
                converted.data,
                rowWidth,
                0 );
            if (mDevice.isError())
            {
                String errorDescription = mDevice.getErrorDescription();
                OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                            "D3D11 device cannot update 2d array subresource\nError Description:" + errorDescription,
                            "D3D11HardwarePixelBuffer::blitFromMemory");
            }
        }
        break;
        case TEX_TYPE_3D:
        {
            // copied from dx9
            size_t sliceWidth;
            if (PixelUtil::isCompressed(converted.format))
            {
                // D3D wants the width of one slice of cells in bytes
                if (converted.format == PF_DXT1)
                {
                    // 64 bits (8 bytes) per 4x4 block
                    sliceWidth = (converted.slicePitch / 16) * 8;
                }
                else
                {
                    // 128 bits (16 bytes) per 4x4 block
                    sliceWidth = (converted.slicePitch / 16) * 16;
                }

            }
            else
            {
                sliceWidth = converted.slicePitch * PixelUtil::getNumElemBytes(converted.format);
            }

            mDevice.GetImmediateContext()->UpdateSubresource(
                mParentTexture->GetTex3D(),
                static_cast<UINT>(mSubresourceIndex),
                &dstBoxDx11,
                converted.data,
                rowWidth,
                sliceWidth
            );
            if (mDevice.isError())
            {
                String errorDescription = mDevice.getErrorDescription();
                OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                            "D3D11 device cannot update 3d subresource\nError Description:" + errorDescription,
                            "D3D11HardwarePixelBuffer::blitFromMemory");
            }
        }
        break;
        }

        if (!isDds)
        {
            _genMipmaps();
        }
    }

}