Bug 1097776 - Use Skia for unaccelerated rendering of 3D transforms. r=jrmuizel

This commit is contained in:
Markus Stange
2014-11-18 11:36:17 -05:00
parent 7cc873dce5
commit dd7dbf7578
4 changed files with 101 additions and 128 deletions

View File

@@ -46,9 +46,8 @@
#include "nsRect.h" // for nsIntRect
#include "nsRegion.h" // for nsIntRegion, etc
#include "nsTArray.h" // for nsAutoTArray
#define PIXMAN_DONT_DEFINE_STDINT
#include "pixman.h" // for pixman_f_transform, etc
#include "skia/SkCanvas.h" // for SkCanvas
#include "skia/SkBitmapDevice.h" // for SkBitmapDevice
class nsIWidget;
namespace mozilla {
@@ -605,75 +604,62 @@ BasicLayerManager::SetRoot(Layer* aLayer)
mRoot = aLayer;
}
static pixman_transform
BasicLayerManager_Matrix3DToPixman(const gfx3DMatrix& aMatrix)
static SkMatrix
BasicLayerManager_Matrix3DToSkia(const gfx3DMatrix& aMatrix)
{
pixman_f_transform transform;
SkMatrix transform;
transform.setAll(aMatrix._11,
aMatrix._21,
aMatrix._41,
aMatrix._12,
aMatrix._22,
aMatrix._42,
aMatrix._14,
aMatrix._24,
aMatrix._44);
transform.m[0][0] = aMatrix._11;
transform.m[0][1] = aMatrix._21;
transform.m[0][2] = aMatrix._41;
transform.m[1][0] = aMatrix._12;
transform.m[1][1] = aMatrix._22;
transform.m[1][2] = aMatrix._42;
transform.m[2][0] = aMatrix._14;
transform.m[2][1] = aMatrix._24;
transform.m[2][2] = aMatrix._44;
pixman_transform result;
pixman_transform_from_pixman_f_transform(&result, &transform);
return result;
return transform;
}
static void
PixmanTransform(const gfxImageSurface* aDest,
RefPtr<DataSourceSurface> aSrc,
const gfx3DMatrix& aTransform,
gfxPoint aDestOffset)
SkiaTransform(const gfxImageSurface* aDest,
RefPtr<DataSourceSurface> aSrc,
const gfx3DMatrix& aTransform,
gfxPoint aDestOffset)
{
IntSize destSize = ToIntSize(aDest->GetSize());
pixman_image_t* dest = pixman_image_create_bits(aDest->Format() == gfxImageFormat::ARGB32 ? PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8,
destSize.width,
destSize.height,
(uint32_t*)aDest->Data(),
aDest->Stride());
IntSize srcSize = aSrc->GetSize();
pixman_image_t* src = pixman_image_create_bits(aSrc->GetFormat() == SurfaceFormat::B8G8R8A8 ? PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8,
srcSize.width,
srcSize.height,
(uint32_t*)aSrc->GetData(),
aSrc->Stride());
NS_ABORT_IF_FALSE(src && dest, "Failed to create pixman images?");
pixman_transform pixTransform = BasicLayerManager_Matrix3DToPixman(aTransform);
pixman_transform pixTransformInverted;
// If the transform is singular then nothing would be drawn anyway, return here
if (!pixman_transform_invert(&pixTransformInverted, &pixTransform)) {
pixman_image_unref(dest);
pixman_image_unref(src);
if (aTransform.IsSingular()) {
return;
}
pixman_image_set_transform(src, &pixTransformInverted);
pixman_image_composite32(PIXMAN_OP_SRC,
src,
nullptr,
dest,
aDestOffset.x,
aDestOffset.y,
0,
0,
0,
0,
destSize.width,
destSize.height);
IntSize destSize = ToIntSize(aDest->GetSize());
SkImageInfo destInfo = SkImageInfo::Make(destSize.width,
destSize.height,
kBGRA_8888_SkColorType,
kPremul_SkAlphaType);
SkBitmap destBitmap;
destBitmap.setInfo(destInfo, aDest->Stride());
destBitmap.setPixels((uint32_t*)aDest->Data());
SkCanvas destCanvas(new SkBitmapDevice(destBitmap));
pixman_image_unref(dest);
pixman_image_unref(src);
IntSize srcSize = aSrc->GetSize();
SkImageInfo srcInfo = SkImageInfo::Make(srcSize.width,
srcSize.height,
kBGRA_8888_SkColorType,
kPremul_SkAlphaType);
SkBitmap src;
src.setInfo(srcInfo, aSrc->Stride());
src.setPixels((uint32_t*)aSrc->GetData());
gfx3DMatrix transform = aTransform;
transform.TranslatePost(Point3D(-aDestOffset.x, -aDestOffset.y, 0));
destCanvas.setMatrix(BasicLayerManager_Matrix3DToSkia(transform));
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
paint.setAntiAlias(true);
paint.setFilterLevel(SkPaint::kLow_FilterLevel);
SkRect destRect = SkRect::MakeXYWH(0, 0, srcSize.width, srcSize.height);
destCanvas.drawBitmapRectToRect(src, nullptr, destRect, &paint);
}
/**
@@ -716,7 +702,7 @@ Transform3D(RefPtr<SourceSurface> aSource,
gfx3DMatrix translation = gfx3DMatrix::Translation(aBounds.x, aBounds.y, 0);
// Transform the content and offset it such that the content begins at the origin.
PixmanTransform(destImage, aSource->GetDataSurface(), translation * aTransform, offset);
SkiaTransform(destImage, aSource->GetDataSurface(), translation * aTransform, offset);
// If we haven't actually drawn to aDest then return our temporary image so
// that the caller can do this.