Bug 611595 - Prevent a crash when D3D9 texture creation fails because the screen is locked. In CairoImageD3D9::SetData, save the surface as a member. Try to create the texture immediately, but also try to create the texture again when painting if it failed the first time. r=bas a=blocker-topcrash

This commit is contained in:
Benjamin Smedberg 2010-11-18 13:47:59 -05:00
Родитель 26885f876b
Коммит 884bf5ce92
2 изменённых файлов: 62 добавлений и 24 удалений

Просмотреть файл

@ -104,7 +104,7 @@ ImageContainerD3D9::GetCurrentAsSurface(gfxIntSize *aSize)
} else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) { } else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
CairoImageD3D9 *cairoImage = CairoImageD3D9 *cairoImage =
static_cast<CairoImageD3D9*>(mActiveImage.get()); static_cast<CairoImageD3D9*>(mActiveImage.get());
*aSize = cairoImage->mSize; *aSize = cairoImage->GetSize();
} }
return static_cast<ImageD3D9*>(mActiveImage->GetImplData())->GetAsSurface(); return static_cast<ImageD3D9*>(mActiveImage->GetImplData())->GetAsSurface();
@ -128,7 +128,7 @@ ImageContainerD3D9::GetCurrentSize()
} else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) { } else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
CairoImageD3D9 *cairoImage = CairoImageD3D9 *cairoImage =
static_cast<CairoImageD3D9*>(mActiveImage.get()); static_cast<CairoImageD3D9*>(mActiveImage.get());
return cairoImage->mSize; return cairoImage->GetSize();
} }
return gfxIntSize(0,0); return gfxIntSize(0,0);
@ -208,15 +208,15 @@ ImageLayerD3D9::RenderLayer()
device()->SetVertexShaderConstantF(CBvLayerQuad, device()->SetVertexShaderConstantF(CBvLayerQuad,
ShaderConstantRect(0, ShaderConstantRect(0,
0, 0,
cairoImage->mSize.width, cairoImage->GetSize().width,
cairoImage->mSize.height), cairoImage->GetSize().height),
1); 1);
SetShaderTransformAndOpacity(); SetShaderTransformAndOpacity();
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER); mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER);
device()->SetTexture(0, cairoImage->mTexture); device()->SetTexture(0, cairoImage->GetOrCreateTexture());
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
} }
} }
@ -454,58 +454,87 @@ void
CairoImageD3D9::SetData(const CairoImage::Data &aData) CairoImageD3D9::SetData(const CairoImage::Data &aData)
{ {
mSize = aData.mSize; mSize = aData.mSize;
mCachedSurface = aData.mSurface;
mTexture = NULL;
// Try to upload the surface immediately, so that we don't block the
// rendering pipeline at paint time.
(void) GetOrCreateTexture();
}
IDirect3DTexture9*
CairoImageD3D9::GetOrCreateTexture()
{
if (mTexture)
return mTexture;
nsRefPtr<gfxImageSurface> imageSurface = nsRefPtr<gfxImageSurface> imageSurface =
new gfxImageSurface(aData.mSize, gfxASurface::ImageFormatARGB32); new gfxImageSurface(mSize, gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxContext> context = new gfxContext(imageSurface); nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
context->SetSource(aData.mSurface); context->SetSource(mCachedSurface);
context->Paint(); context->Paint();
if (mManager->deviceManager()->IsD3D9Ex()) { if (mManager->deviceManager()->IsD3D9Ex()) {
// D3D9Ex doesn't support managed textures. We could use dynamic textures // D3D9Ex doesn't support managed textures. We could use dynamic textures
// here but since Images are immutable that probably isn't such a great // here but since Images are immutable that probably isn't such a great
// idea. // idea.
mManager->device()->CreateTexture(aData.mSize.width, aData.mSize.height, if (FAILED(mManager->device()->
1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, CreateTexture(mSize.width, mSize.height,
getter_AddRefs(mTexture), NULL); 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
getter_AddRefs(mTexture), NULL)))
return NULL;
nsRefPtr<IDirect3DSurface9> surface; nsRefPtr<IDirect3DSurface9> surface;
mManager->device()->CreateOffscreenPlainSurface(aData.mSize.width, if (FAILED(mManager->device()->
aData.mSize.height, CreateOffscreenPlainSurface(mSize.width,
D3DFMT_A8R8G8B8, mSize.height,
D3DPOOL_SYSTEMMEM, D3DFMT_A8R8G8B8,
getter_AddRefs(surface), D3DPOOL_SYSTEMMEM,
NULL); getter_AddRefs(surface),
NULL))) {
mTexture = NULL;
return NULL;
}
D3DLOCKED_RECT lockedRect; D3DLOCKED_RECT lockedRect;
surface->LockRect(&lockedRect, NULL, 0); surface->LockRect(&lockedRect, NULL, 0);
for (int y = 0; y < aData.mSize.height; y++) { for (int y = 0; y < mSize.height; y++) {
memcpy((char*)lockedRect.pBits + lockedRect.Pitch * y, memcpy((char*)lockedRect.pBits + lockedRect.Pitch * y,
imageSurface->Data() + imageSurface->Stride() * y, imageSurface->Data() + imageSurface->Stride() * y,
aData.mSize.width * 4); mSize.width * 4);
} }
surface->UnlockRect(); surface->UnlockRect();
nsRefPtr<IDirect3DSurface9> dstSurface; nsRefPtr<IDirect3DSurface9> dstSurface;
mTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface)); mTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
mManager->device()->UpdateSurface(surface, NULL, dstSurface, NULL); mManager->device()->UpdateSurface(surface, NULL, dstSurface, NULL);
} else { } else {
mManager->device()->CreateTexture(aData.mSize.width, aData.mSize.height, if (FAILED(mManager->device()->
1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, CreateTexture(mSize.width, mSize.height,
getter_AddRefs(mTexture), NULL); 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
getter_AddRefs(mTexture), NULL)))
return NULL;
D3DLOCKED_RECT lockrect; D3DLOCKED_RECT lockrect;
/* lock the entire texture */ /* lock the entire texture */
mTexture->LockRect(0, &lockrect, NULL, 0); mTexture->LockRect(0, &lockrect, NULL, 0);
// copy over data. If we don't need to do any swaping we can // copy over data. If we don't need to do any swaping we can
// use memcpy // use memcpy
for (int y = 0; y < aData.mSize.height; y++) { for (int y = 0; y < mSize.height; y++) {
memcpy((char*)lockrect.pBits + lockrect.Pitch * y, memcpy((char*)lockrect.pBits + lockrect.Pitch * y,
imageSurface->Data() + imageSurface->Stride() * y, imageSurface->Data() + imageSurface->Stride() * y,
aData.mSize.width * 4); mSize.width * 4);
} }
mTexture->UnlockRect(0); mTexture->UnlockRect(0);
} }
NS_ASSERTION(mTexture, "Should have succeeded by now.");
// Release our no-longer-needed mCachedSurface
mCachedSurface = NULL;
return mTexture;
} }
already_AddRefed<gfxASurface> already_AddRefed<gfxASurface>

Просмотреть файл

@ -148,8 +148,17 @@ public:
virtual already_AddRefed<gfxASurface> GetAsSurface(); virtual already_AddRefed<gfxASurface> GetAsSurface();
nsRefPtr<IDirect3DTexture9> mTexture; /**
* Uploading a texture may fail if the screen is locked. If this happens,
* we need to save the backing surface and retry when we are asked to paint.
*/
virtual IDirect3DTexture9* GetOrCreateTexture();
const gfxIntSize& GetSize() { return mSize; }
private:
gfxIntSize mSize; gfxIntSize mSize;
nsRefPtr<gfxASurface> mCachedSurface;
nsRefPtr<IDirect3DTexture9> mTexture;
LayerManagerD3D9 *mManager; LayerManagerD3D9 *mManager;
}; };