Bug 1213429 - Recycle e10s D3D9 textures and add partial upload support. r=Bas

This commit is contained in:
Benoit Girard 2016-01-25 14:58:46 -08:00
parent e5dc52e823
commit 9096fb900f

View File

@ -339,12 +339,14 @@ DataTextureSourceD3D9::Update(gfx::DataSourceSurface* aSurface,
NS_WARNING("No D3D device to update the texture.");
return false;
}
mSize = aSurface->GetSize();
uint32_t bpp = 0;
uint32_t bpp = BytesPerPixel(aSurface->GetFormat());
DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
mSize = aSurface->GetSize();
mFormat = aSurface->GetFormat();
_D3DFORMAT format = D3DFMT_A8R8G8B8;
mFormat = aSurface->GetFormat();
switch (mFormat) {
case SurfaceFormat::B8G8R8X8:
format = D3DFMT_X8R8G8B8;
@ -364,18 +366,100 @@ DataTextureSourceD3D9::Update(gfx::DataSourceSurface* aSurface,
}
int32_t maxSize = mCompositor->GetMaxTextureSize();
DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
if ((mSize.width <= maxSize && mSize.height <= maxSize) ||
(mFlags & TextureFlags::DISALLOW_BIGIMAGE)) {
mTexture = DataToTexture(deviceManager,
aSurface->GetData(), aSurface->Stride(),
IntSize(mSize), format, bpp);
(mFlags & TextureFlags::DISALLOW_BIGIMAGE)) {
mIsTiled = false;
if (mTexture) {
D3DSURFACE_DESC currentDesc;
mTexture->GetLevelDesc(0, &currentDesc);
// Make sure there's no size mismatch, if there is, recreate.
if (currentDesc.Width != mSize.width || currentDesc.Height != mSize.height ||
currentDesc.Format != format) {
mTexture = nullptr;
// Make sure we upload the whole surface.
aDestRegion = nullptr;
}
}
if (!mTexture) {
NS_WARNING("Could not upload texture");
// TODO Improve: Reallocating this texture is costly enough
// that it causes us to skip frames on scrolling
// important pages like Facebook.
mTexture = deviceManager->CreateTexture(mSize, format, D3DPOOL_DEFAULT, this);
mIsTiled = false;
if (!mTexture) {
Reset();
return false;
}
if (mFlags & TextureFlags::COMPONENT_ALPHA) {
aDestRegion = nullptr;
}
}
DataSourceSurface::MappedSurface map;
if (!aSurface->Map(DataSourceSurface::MapType::READ, &map)) {
gfxCriticalError() << "Failed to map surface.";
Reset();
return false;
}
mIsTiled = false;
nsIntRegion regionToUpdate = aDestRegion ? *aDestRegion : nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height));
RefPtr<IDirect3DTexture9> srcTexture;
RefPtr<IDirect3DSurface9> srcSurface;
if (mFormat == SurfaceFormat::A8) {
// A8 doesn't appear to work with CreateOffscreenPlainSurface
srcTexture = deviceManager->CreateTexture(mSize, format, D3DPOOL_SYSTEMMEM, this);
if (!srcTexture) {
aSurface->Unmap();
return false;
}
srcTexture->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
} else {
HRESULT hr = mCompositor->device()->CreateOffscreenPlainSurface(mSize.width, mSize.height, format, D3DPOOL_SYSTEMMEM, getter_AddRefs(srcSurface), nullptr);
if (FAILED(hr)) {
aSurface->Unmap();
return false;
}
}
RefPtr<IDirect3DSurface9> destSurface;
mTexture->GetSurfaceLevel(0, getter_AddRefs(destSurface));
D3DLOCKED_RECT rect;
srcSurface->LockRect(&rect, nullptr, 0);
for (auto iter = regionToUpdate.RectIter(); !iter.Done(); iter.Next()) {
const nsIntRect& iterRect = iter.Get();
uint8_t* src = map.mData + map.mStride * iterRect.y + BytesPerPixel(aSurface->GetFormat()) * iterRect.x;
uint8_t* dest = reinterpret_cast<uint8_t*>(rect.pBits) + rect.Pitch * iterRect.y + BytesPerPixel(aSurface->GetFormat()) * iterRect.x;
for (int y = 0; y < iterRect.height; y++) {
memcpy(dest + rect.Pitch * y,
src + map.mStride * y,
iterRect.width * bpp);
}
}
srcSurface->UnlockRect();
aSurface->Unmap();
for (auto iter = regionToUpdate.RectIter(); !iter.Done(); iter.Next()) {
const nsIntRect& iterRect = iter.Get();
RECT updateRect;
updateRect.left = iterRect.x;
updateRect.top = iterRect.y;
updateRect.right = iterRect.XMost();
updateRect.bottom = iterRect.YMost();
POINT point = { updateRect.left, updateRect.top };
mCompositor->device()->UpdateSurface(srcSurface, &updateRect, destSurface, &point);
}
} else {
mIsTiled = true;
uint32_t tileCount = GetRequiredTilesD3D9(mSize.width, maxSize) *