зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
26885f876b
Коммит
884bf5ce92
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче