mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1213429 - Recycle e10s D3D9 textures and add partial upload support. r=Bas
This commit is contained in:
parent
e5dc52e823
commit
9096fb900f
@ -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, ¤tDesc);
|
||||
|
||||
// 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) *
|
||||
|
Loading…
Reference in New Issue
Block a user