зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1290323. Write alpha values for plugin surfaces when using the Skia backend. r=jrmuizel
This commit is contained in:
Родитель
82b2646797
Коммит
21793bcce5
|
@ -954,8 +954,9 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
|
|||
updatedRect.bottom - updatedRect.top);
|
||||
surface->MarkDirty(ur);
|
||||
|
||||
bool isPlugin = true;
|
||||
RefPtr<gfx::SourceSurface> sourceSurface =
|
||||
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, surface);
|
||||
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, surface, isPlugin);
|
||||
RefPtr<SourceSurfaceImage> image = new SourceSurfaceImage(surface->GetSize(), sourceSurface);
|
||||
|
||||
AutoTArray<ImageContainer::NonOwningImage,1> imageList;
|
||||
|
|
|
@ -1037,6 +1037,9 @@ public:
|
|||
* aSourceSurface or some other existing surface.
|
||||
*/
|
||||
virtual already_AddRefed<SourceSurface> OptimizeSourceSurface(SourceSurface *aSurface) const = 0;
|
||||
virtual already_AddRefed<SourceSurface> OptimizeSourceSurfaceForUnknownAlpha(SourceSurface *aSurface) const {
|
||||
return OptimizeSourceSurface(aSurface);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SourceSurface for a type of NativeSurface. This may fail if the
|
||||
|
|
|
@ -103,6 +103,31 @@ ReleaseTemporarySurface(void* aPixels, void* aContext)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
WriteRGBXFormat(uint8_t* aData, const IntSize &aSize,
|
||||
const int32_t aStride, SurfaceFormat aFormat)
|
||||
{
|
||||
if (aFormat != SurfaceFormat::B8G8R8X8 || aSize.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int height = aSize.height;
|
||||
int width = aSize.width * 4;
|
||||
|
||||
for (int row = 0; row < height; ++row) {
|
||||
for (int column = 0; column < width; column += 4) {
|
||||
#ifdef IS_BIG_ENDIAN
|
||||
aData[column] = 0xFF;
|
||||
#else
|
||||
aData[column + 3] = 0xFF;
|
||||
#endif
|
||||
}
|
||||
aData += aStride;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool
|
||||
VerifyRGBXFormat(uint8_t* aData, const IntSize &aSize, const int32_t aStride, SurfaceFormat aFormat)
|
||||
|
@ -1377,43 +1402,76 @@ DrawTargetSkia::UsingSkiaGPU() const
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_SKIA_GPU
|
||||
already_AddRefed<SourceSurface>
|
||||
DrawTargetSkia::OptimizeGPUSourceSurface(SourceSurface *aSurface) const
|
||||
{
|
||||
// Check if the underlying SkBitmap already has an associated GrTexture.
|
||||
if (aSurface->GetType() == SurfaceType::SKIA &&
|
||||
static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap().getTexture()) {
|
||||
RefPtr<SourceSurface> surface(aSurface);
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
SkBitmap bitmap = GetBitmapForSurface(aSurface);
|
||||
|
||||
// Upload the SkBitmap to a GrTexture otherwise.
|
||||
SkAutoTUnref<GrTexture> texture(
|
||||
GrRefCachedBitmapTexture(mGrContext.get(), bitmap, GrTextureParams::ClampBilerp()));
|
||||
|
||||
if (texture) {
|
||||
// Create a new SourceSurfaceSkia whose SkBitmap contains the GrTexture.
|
||||
RefPtr<SourceSurfaceSkia> surface = new SourceSurfaceSkia();
|
||||
if (surface->InitFromGrTexture(texture, aSurface->GetSize(), aSurface->GetFormat())) {
|
||||
return surface.forget();
|
||||
}
|
||||
}
|
||||
|
||||
// The data was too big to fit in a GrTexture.
|
||||
if (aSurface->GetType() == SurfaceType::SKIA) {
|
||||
// It is already a Skia source surface, so just reuse it as-is.
|
||||
RefPtr<SourceSurface> surface(aSurface);
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
// Wrap it in a Skia source surface so that can do tiled uploads on-demand.
|
||||
RefPtr<SourceSurfaceSkia> surface = new SourceSurfaceSkia();
|
||||
surface->InitFromBitmap(bitmap);
|
||||
return surface.forget();
|
||||
}
|
||||
#endif
|
||||
|
||||
already_AddRefed<SourceSurface>
|
||||
DrawTargetSkia::OptimizeSourceSurfaceForUnknownAlpha(SourceSurface *aSurface) const
|
||||
{
|
||||
#ifdef USE_SKIA_GPU
|
||||
if (UsingSkiaGPU()) {
|
||||
return OptimizeGPUSourceSurface(aSurface);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (aSurface->GetType() == SurfaceType::SKIA) {
|
||||
RefPtr<SourceSurface> surface(aSurface);
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
|
||||
|
||||
// For plugins, GDI can sometimes just write 0 to the alpha channel
|
||||
// even for RGBX formats. In this case, we have to manually write
|
||||
// the alpha channel to make Skia happy with RGBX and in case GDI
|
||||
// writes some bad data. Luckily, this only happens on plugins.
|
||||
WriteRGBXFormat(dataSurface->GetData(), dataSurface->GetSize(),
|
||||
dataSurface->Stride(), dataSurface->GetFormat());
|
||||
return dataSurface.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<SourceSurface>
|
||||
DrawTargetSkia::OptimizeSourceSurface(SourceSurface *aSurface) const
|
||||
{
|
||||
#ifdef USE_SKIA_GPU
|
||||
if (UsingSkiaGPU()) {
|
||||
// Check if the underlying SkBitmap already has an associated GrTexture.
|
||||
if (aSurface->GetType() == SurfaceType::SKIA &&
|
||||
static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap().getTexture()) {
|
||||
RefPtr<SourceSurface> surface(aSurface);
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
SkBitmap bitmap = GetBitmapForSurface(aSurface);
|
||||
|
||||
// Upload the SkBitmap to a GrTexture otherwise.
|
||||
SkAutoTUnref<GrTexture> texture(
|
||||
GrRefCachedBitmapTexture(mGrContext.get(), bitmap, GrTextureParams::ClampBilerp()));
|
||||
|
||||
if (texture) {
|
||||
// Create a new SourceSurfaceSkia whose SkBitmap contains the GrTexture.
|
||||
RefPtr<SourceSurfaceSkia> surface = new SourceSurfaceSkia();
|
||||
if (surface->InitFromGrTexture(texture, aSurface->GetSize(), aSurface->GetFormat())) {
|
||||
return surface.forget();
|
||||
}
|
||||
}
|
||||
|
||||
// The data was too big to fit in a GrTexture.
|
||||
if (aSurface->GetType() == SurfaceType::SKIA) {
|
||||
// It is already a Skia source surface, so just reuse it as-is.
|
||||
RefPtr<SourceSurface> surface(aSurface);
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
// Wrap it in a Skia source surface so that can do tiled uploads on-demand.
|
||||
RefPtr<SourceSurfaceSkia> surface = new SourceSurfaceSkia();
|
||||
surface->InitFromBitmap(bitmap);
|
||||
return surface.forget();
|
||||
return OptimizeGPUSourceSurface(aSurface);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -116,6 +116,7 @@ public:
|
|||
int32_t aStride,
|
||||
SurfaceFormat aFormat) const override;
|
||||
virtual already_AddRefed<SourceSurface> OptimizeSourceSurface(SourceSurface *aSurface) const override;
|
||||
virtual already_AddRefed<SourceSurface> OptimizeSourceSurfaceForUnknownAlpha(SourceSurface *aSurface) const override;
|
||||
virtual already_AddRefed<SourceSurface>
|
||||
CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const override;
|
||||
virtual already_AddRefed<DrawTarget>
|
||||
|
@ -141,6 +142,8 @@ public:
|
|||
SurfaceFormat aFormat) override {
|
||||
return InitWithGrContext(aGrContext, aSize, aFormat, false);
|
||||
}
|
||||
|
||||
already_AddRefed<SourceSurface> OptimizeGPUSourceSurface(SourceSurface *aSurface) const;
|
||||
#endif
|
||||
|
||||
// Skia assumes that texture sizes fit in 16-bit signed integers.
|
||||
|
|
|
@ -1006,7 +1006,9 @@ gfxPlatform::ClearSourceSurfaceForSurface(gfxASurface *aSurface)
|
|||
}
|
||||
|
||||
/* static */ already_AddRefed<SourceSurface>
|
||||
gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurface)
|
||||
gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget,
|
||||
gfxASurface *aSurface,
|
||||
bool aIsPlugin)
|
||||
{
|
||||
if (!aSurface->CairoSurface() || aSurface->CairoStatus()) {
|
||||
return nullptr;
|
||||
|
@ -1064,7 +1066,9 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
|
|||
// the same data, then optimize it for aTarget:
|
||||
RefPtr<DataSourceSurface> surf = GetWrappedDataSourceSurface(aSurface);
|
||||
if (surf) {
|
||||
srcBuffer = aTarget->OptimizeSourceSurface(surf);
|
||||
srcBuffer = aIsPlugin ? aTarget->OptimizeSourceSurfaceForUnknownAlpha(surf)
|
||||
: aTarget->OptimizeSourceSurface(surf);
|
||||
|
||||
if (srcBuffer == surf) {
|
||||
// GetWrappedDataSourceSurface returns a SourceSurface that holds a
|
||||
// strong reference to aSurface since it wraps aSurface's data and
|
||||
|
|
|
@ -210,9 +210,14 @@ public:
|
|||
* This function is static so that it can be accessed from
|
||||
* PluginInstanceChild (where we can't call gfxPlatform::GetPlatform()
|
||||
* because the prefs service can only be accessed from the main process).
|
||||
*
|
||||
* aIsPlugin is used to tell the backend that they can optimize this surface
|
||||
* specifically because it's used for a plugin. This is mostly for Skia.
|
||||
*/
|
||||
static already_AddRefed<SourceSurface>
|
||||
GetSourceSurfaceForSurface(mozilla::gfx::DrawTarget *aTarget, gfxASurface *aSurface);
|
||||
GetSourceSurfaceForSurface(mozilla::gfx::DrawTarget *aTarget,
|
||||
gfxASurface *aSurface,
|
||||
bool aIsPlugin = false);
|
||||
|
||||
static void ClearSourceSurfaceForSurface(gfxASurface *aSurface);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче