gfx/2d/DrawTargetSkia.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "DrawTargetSkia.h"
     7 #include "SourceSurfaceSkia.h"
     8 #include "ScaledFontBase.h"
     9 #include "ScaledFontCairo.h"
    10 #include "skia/SkGpuDevice.h"
    11 #include "skia/SkBitmapDevice.h"
    12 #include "FilterNodeSoftware.h"
    14 #ifdef USE_SKIA_GPU
    15 #include "skia/SkGpuDevice.h"
    16 #include "skia/GrGLInterface.h"
    17 #endif
    19 #include "skia/SkTypeface.h"
    20 #include "skia/SkGradientShader.h"
    21 #include "skia/SkBlurDrawLooper.h"
    22 #include "skia/SkBlurMaskFilter.h"
    23 #include "skia/SkColorFilter.h"
    24 #include "skia/SkDropShadowImageFilter.h"
    25 #include "skia/SkLayerRasterizer.h"
    26 #include "skia/SkLayerDrawLooper.h"
    27 #include "skia/SkDashPathEffect.h"
    28 #include "Logging.h"
    29 #include "HelpersSkia.h"
    30 #include "Tools.h"
    31 #include "DataSurfaceHelpers.h"
    32 #include <algorithm>
    34 namespace mozilla {
    35 namespace gfx {
    37 class GradientStopsSkia : public GradientStops
    38 {
    39 public:
    40   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsSkia)
    41   GradientStopsSkia(const std::vector<GradientStop>& aStops, uint32_t aNumStops, ExtendMode aExtendMode)
    42     : mCount(aNumStops)
    43     , mExtendMode(aExtendMode)
    44   {
    45     if (mCount == 0) {
    46       return;
    47     }
    49     // Skia gradients always require a stop at 0.0 and 1.0, insert these if
    50     // we don't have them.
    51     uint32_t shift = 0;
    52     if (aStops[0].offset != 0) {
    53       mCount++;
    54       shift = 1;
    55     }
    56     if (aStops[aNumStops-1].offset != 1) {
    57       mCount++;
    58     }
    59     mColors.resize(mCount);
    60     mPositions.resize(mCount);
    61     if (aStops[0].offset != 0) {
    62       mColors[0] = ColorToSkColor(aStops[0].color, 1.0);
    63       mPositions[0] = 0;
    64     }
    65     for (uint32_t i = 0; i < aNumStops; i++) {
    66       mColors[i + shift] = ColorToSkColor(aStops[i].color, 1.0);
    67       mPositions[i + shift] = SkFloatToScalar(aStops[i].offset);
    68     }
    69     if (aStops[aNumStops-1].offset != 1) {
    70       mColors[mCount-1] = ColorToSkColor(aStops[aNumStops-1].color, 1.0);
    71       mPositions[mCount-1] = SK_Scalar1;
    72     }
    73   }
    75   BackendType GetBackendType() const { return BackendType::SKIA; }
    77   std::vector<SkColor> mColors;
    78   std::vector<SkScalar> mPositions;
    79   int mCount;
    80   ExtendMode mExtendMode;
    81 };
    83 /**
    84  * When constructing a temporary SkBitmap via GetBitmapForSurface, we may also
    85  * have to construct a temporary DataSourceSurface, which must live as long as
    86  * the SkBitmap. So we return a pair of the SkBitmap and the (optional)
    87  * temporary surface.
    88  */
    89 struct TempBitmap
    90 {
    91   SkBitmap mBitmap;
    92   RefPtr<SourceSurface> mTmpSurface;
    93 };
    95 static TempBitmap
    96 GetBitmapForSurface(SourceSurface* aSurface)
    97 {
    98   TempBitmap result;
   100   if (aSurface->GetType() == SurfaceType::SKIA) {
   101     result.mBitmap = static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap();
   102     return result;
   103   }
   105   RefPtr<DataSourceSurface> surf = aSurface->GetDataSurface();
   106   if (!surf) {
   107     MOZ_CRASH("Non-skia SourceSurfaces need to be DataSourceSurfaces");
   108   }
   110   result.mBitmap.setConfig(GfxFormatToSkiaConfig(surf->GetFormat()),
   111                                  surf->GetSize().width, surf->GetSize().height,
   112                                  surf->Stride());
   113   result.mBitmap.setPixels(surf->GetData());
   114   result.mTmpSurface = surf.forget();
   115   return result;
   116 }
   118 DrawTargetSkia::DrawTargetSkia()
   119   : mTexture(0), mSnapshot(nullptr)
   120 {
   121 }
   123 DrawTargetSkia::~DrawTargetSkia()
   124 {
   125 }
   127 TemporaryRef<SourceSurface>
   128 DrawTargetSkia::Snapshot()
   129 {
   130   RefPtr<SourceSurfaceSkia> snapshot = mSnapshot;
   131   if (!snapshot) {
   132     snapshot = new SourceSurfaceSkia();
   133     mSnapshot = snapshot;
   134     if (!snapshot->InitFromCanvas(mCanvas.get(), mFormat, this))
   135       return nullptr;
   136   }
   138   return snapshot;
   139 }
   141 static void
   142 SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, TempBitmap& aTmpBitmap,
   143                 Float aAlpha = 1.0)
   144 {
   145   switch (aPattern.GetType()) {
   146     case PatternType::COLOR: {
   147       Color color = static_cast<const ColorPattern&>(aPattern).mColor;
   148       aPaint.setColor(ColorToSkColor(color, aAlpha));
   149       break;
   150     }
   151     case PatternType::LINEAR_GRADIENT: {
   152       const LinearGradientPattern& pat = static_cast<const LinearGradientPattern&>(aPattern);
   153       GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
   154       SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode);
   156       if (stops->mCount >= 2) {
   157         SkPoint points[2];
   158         points[0] = SkPoint::Make(SkFloatToScalar(pat.mBegin.x), SkFloatToScalar(pat.mBegin.y));
   159         points[1] = SkPoint::Make(SkFloatToScalar(pat.mEnd.x), SkFloatToScalar(pat.mEnd.y));
   161         SkShader* shader = SkGradientShader::CreateLinear(points, 
   162                                                           &stops->mColors.front(), 
   163                                                           &stops->mPositions.front(), 
   164                                                           stops->mCount, 
   165                                                           mode);
   167         if (shader) {
   168             SkMatrix mat;
   169             GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
   170             shader->setLocalMatrix(mat);
   171             SkSafeUnref(aPaint.setShader(shader));
   172         }
   174       } else {
   175         aPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
   176       }
   177       break;
   178     }
   179     case PatternType::RADIAL_GRADIENT: {
   180       const RadialGradientPattern& pat = static_cast<const RadialGradientPattern&>(aPattern);
   181       GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
   182       SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode);
   184       if (stops->mCount >= 2) {
   185         SkPoint points[2];
   186         points[0] = SkPoint::Make(SkFloatToScalar(pat.mCenter1.x), SkFloatToScalar(pat.mCenter1.y));
   187         points[1] = SkPoint::Make(SkFloatToScalar(pat.mCenter2.x), SkFloatToScalar(pat.mCenter2.y));
   189         SkShader* shader = SkGradientShader::CreateTwoPointConical(points[0], 
   190                                                                    SkFloatToScalar(pat.mRadius1),
   191                                                                    points[1], 
   192                                                                    SkFloatToScalar(pat.mRadius2),
   193                                                                    &stops->mColors.front(), 
   194                                                                    &stops->mPositions.front(), 
   195                                                                    stops->mCount, 
   196                                                                    mode);
   197         if (shader) {
   198             SkMatrix mat;
   199             GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
   200             shader->setLocalMatrix(mat);
   201             SkSafeUnref(aPaint.setShader(shader));
   202         }
   204       } else {
   205         aPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
   206       }
   207       break;
   208     }
   209     case PatternType::SURFACE: {
   210       const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
   211       aTmpBitmap = GetBitmapForSurface(pat.mSurface);
   212       const SkBitmap& bitmap = aTmpBitmap.mBitmap;
   214       SkShader::TileMode mode = ExtendModeToTileMode(pat.mExtendMode);
   215       SkShader* shader = SkShader::CreateBitmapShader(bitmap, mode, mode);
   216       SkMatrix mat;
   217       GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
   218       shader->setLocalMatrix(mat);
   219       SkSafeUnref(aPaint.setShader(shader));
   220       if (pat.mFilter == Filter::POINT) {
   221         aPaint.setFilterLevel(SkPaint::kNone_FilterLevel);
   222       }
   223       break;
   224     }
   225   }
   226 }
   228 static inline Rect
   229 GetClipBounds(SkCanvas *aCanvas)
   230 {
   231   SkRect clipBounds;
   232   aCanvas->getClipBounds(&clipBounds);
   233   return SkRectToRect(clipBounds);
   234 }
   236 struct AutoPaintSetup {
   237   AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions, const Pattern& aPattern, const Rect* aMaskBounds = nullptr)
   238     : mNeedsRestore(false), mAlpha(1.0)
   239   {
   240     Init(aCanvas, aOptions, aMaskBounds);
   241     SetPaintPattern(mPaint, aPattern, mTmpBitmap, mAlpha);
   242   }
   244   AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions, const Rect* aMaskBounds = nullptr)
   245     : mNeedsRestore(false), mAlpha(1.0)
   246   {
   247     Init(aCanvas, aOptions, aMaskBounds);
   248   }
   250   ~AutoPaintSetup()
   251   {
   252     if (mNeedsRestore) {
   253       mCanvas->restore();
   254     }
   255   }
   257   void Init(SkCanvas *aCanvas, const DrawOptions& aOptions, const Rect* aMaskBounds)
   258   {
   259     mPaint.setXfermodeMode(GfxOpToSkiaOp(aOptions.mCompositionOp));
   260     mCanvas = aCanvas;
   262     //TODO: Can we set greyscale somehow?
   263     if (aOptions.mAntialiasMode != AntialiasMode::NONE) {
   264       mPaint.setAntiAlias(true);
   265     } else {
   266       mPaint.setAntiAlias(false);
   267     }
   269     Rect clipBounds = GetClipBounds(aCanvas);
   270     bool needsGroup = !IsOperatorBoundByMask(aOptions.mCompositionOp) &&
   271                       (!aMaskBounds || !aMaskBounds->Contains(clipBounds));
   273     // TODO: We could skip the temporary for operator_source and just
   274     // clear the clip rect. The other operators would be harder
   275     // but could be worth it to skip pushing a group.
   276     if (needsGroup) {
   277       mPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
   278       SkPaint temp;
   279       temp.setXfermodeMode(GfxOpToSkiaOp(aOptions.mCompositionOp));
   280       temp.setAlpha(U8CPU(aOptions.mAlpha*255));
   281       //TODO: Get a rect here
   282       mCanvas->saveLayer(nullptr, &temp);
   283       mNeedsRestore = true;
   284     } else {
   285       mPaint.setAlpha(U8CPU(aOptions.mAlpha*255.0));
   286       mAlpha = aOptions.mAlpha;
   287     }
   288     mPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
   289   }
   291   // TODO: Maybe add an operator overload to access this easier?
   292   SkPaint mPaint;
   293   TempBitmap mTmpBitmap;
   294   bool mNeedsRestore;
   295   SkCanvas* mCanvas;
   296   Float mAlpha;
   297 };
   299 void
   300 DrawTargetSkia::Flush()
   301 {
   302   mCanvas->flush();
   303 }
   305 void
   306 DrawTargetSkia::DrawSurface(SourceSurface *aSurface,
   307                             const Rect &aDest,
   308                             const Rect &aSource,
   309                             const DrawSurfaceOptions &aSurfOptions,
   310                             const DrawOptions &aOptions)
   311 {
   312   RefPtr<SourceSurface> dataSurface;
   314   if (!(aSurface->GetType() == SurfaceType::SKIA || aSurface->GetType() == SurfaceType::DATA)) {
   315     dataSurface = aSurface->GetDataSurface();
   316     if (!dataSurface) {
   317       gfxDebug() << *this << ": DrawSurface() can't draw surface";
   318       return;
   319     }
   320     aSurface = dataSurface.get();
   321   }
   323   if (aSource.IsEmpty()) {
   324     return;
   325   }
   327   MarkChanged();
   329   SkRect destRect = RectToSkRect(aDest);
   330   SkRect sourceRect = RectToSkRect(aSource);
   332   TempBitmap bitmap = GetBitmapForSurface(aSurface);
   334   AutoPaintSetup paint(mCanvas.get(), aOptions, &aDest);
   335   if (aSurfOptions.mFilter == Filter::POINT) {
   336     paint.mPaint.setFilterLevel(SkPaint::kNone_FilterLevel);
   337   }
   339   mCanvas->drawBitmapRectToRect(bitmap.mBitmap, &sourceRect, destRect, &paint.mPaint);
   340 }
   342 void
   343 DrawTargetSkia::DrawFilter(FilterNode *aNode,
   344                            const Rect &aSourceRect,
   345                            const Point &aDestPoint,
   346                            const DrawOptions &aOptions)
   347 {
   348   FilterNodeSoftware* filter = static_cast<FilterNodeSoftware*>(aNode);
   349   filter->Draw(this, aSourceRect, aDestPoint, aOptions);
   350 }
   352 void
   353 DrawTargetSkia::DrawSurfaceWithShadow(SourceSurface *aSurface,
   354                                       const Point &aDest,
   355                                       const Color &aColor,
   356                                       const Point &aOffset,
   357                                       Float aSigma,
   358                                       CompositionOp aOperator)
   359 {
   360   if (!(aSurface->GetType() == SurfaceType::SKIA || aSurface->GetType() == SurfaceType::DATA)) {
   361     return;
   362   }
   364   MarkChanged();
   366   mCanvas->save(SkCanvas::kMatrix_SaveFlag);
   367   mCanvas->resetMatrix();
   369   TempBitmap bitmap = GetBitmapForSurface(aSurface);
   371   SkPaint paint;
   373   SkImageFilter* filter = SkDropShadowImageFilter::Create(aOffset.x, aOffset.y,
   374                                                           aSigma, ColorToSkColor(aColor, 1.0));
   376   paint.setImageFilter(filter);
   377   paint.setXfermodeMode(GfxOpToSkiaOp(aOperator));
   379   mCanvas->drawBitmap(bitmap.mBitmap, aDest.x, aDest.y, &paint);
   380   mCanvas->restore();
   381 }
   383 void
   384 DrawTargetSkia::FillRect(const Rect &aRect,
   385                          const Pattern &aPattern,
   386                          const DrawOptions &aOptions)
   387 {
   388   MarkChanged();
   389   SkRect rect = RectToSkRect(aRect);
   390   AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern, &aRect);
   392   mCanvas->drawRect(rect, paint.mPaint);
   393 }
   395 void
   396 DrawTargetSkia::Stroke(const Path *aPath,
   397                        const Pattern &aPattern,
   398                        const StrokeOptions &aStrokeOptions,
   399                        const DrawOptions &aOptions)
   400 {
   401   MarkChanged();
   402   MOZ_ASSERT(aPath, "Null path");
   403   if (aPath->GetBackendType() != BackendType::SKIA) {
   404     return;
   405   }
   407   const PathSkia *skiaPath = static_cast<const PathSkia*>(aPath);
   410   AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
   411   if (!StrokeOptionsToPaint(paint.mPaint, aStrokeOptions)) {
   412     return;
   413   }
   415   mCanvas->drawPath(skiaPath->GetPath(), paint.mPaint);
   416 }
   418 void
   419 DrawTargetSkia::StrokeRect(const Rect &aRect,
   420                            const Pattern &aPattern,
   421                            const StrokeOptions &aStrokeOptions,
   422                            const DrawOptions &aOptions)
   423 {
   424   MarkChanged();
   425   AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
   426   if (!StrokeOptionsToPaint(paint.mPaint, aStrokeOptions)) {
   427     return;
   428   }
   430   mCanvas->drawRect(RectToSkRect(aRect), paint.mPaint);
   431 }
   433 void 
   434 DrawTargetSkia::StrokeLine(const Point &aStart,
   435                            const Point &aEnd,
   436                            const Pattern &aPattern,
   437                            const StrokeOptions &aStrokeOptions,
   438                            const DrawOptions &aOptions)
   439 {
   440   MarkChanged();
   441   AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
   442   if (!StrokeOptionsToPaint(paint.mPaint, aStrokeOptions)) {
   443     return;
   444   }
   446   mCanvas->drawLine(SkFloatToScalar(aStart.x), SkFloatToScalar(aStart.y), 
   447                     SkFloatToScalar(aEnd.x), SkFloatToScalar(aEnd.y), 
   448                     paint.mPaint);
   449 }
   451 void
   452 DrawTargetSkia::Fill(const Path *aPath,
   453                     const Pattern &aPattern,
   454                     const DrawOptions &aOptions)
   455 {
   456   MarkChanged();
   457   if (aPath->GetBackendType() != BackendType::SKIA) {
   458     return;
   459   }
   461   const PathSkia *skiaPath = static_cast<const PathSkia*>(aPath);
   463   AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
   465   mCanvas->drawPath(skiaPath->GetPath(), paint.mPaint);
   466 }
   468 void
   469 DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
   470                            const GlyphBuffer &aBuffer,
   471                            const Pattern &aPattern,
   472                            const DrawOptions &aOptions,
   473                            const GlyphRenderingOptions *aRenderingOptions)
   474 {
   475   if (aFont->GetType() != FontType::MAC &&
   476       aFont->GetType() != FontType::SKIA &&
   477       aFont->GetType() != FontType::GDI) {
   478     return;
   479   }
   481   MarkChanged();
   483   ScaledFontBase* skiaFont = static_cast<ScaledFontBase*>(aFont);
   485   AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
   486   paint.mPaint.setTypeface(skiaFont->GetSkTypeface());
   487   paint.mPaint.setTextSize(SkFloatToScalar(skiaFont->mSize));
   488   paint.mPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
   490   if (aRenderingOptions && aRenderingOptions->GetType() == FontType::CAIRO) {
   491     switch (static_cast<const GlyphRenderingOptionsCairo*>(aRenderingOptions)->GetHinting()) {
   492       case FontHinting::NONE:
   493         paint.mPaint.setHinting(SkPaint::kNo_Hinting);
   494         break;
   495       case FontHinting::LIGHT:
   496         paint.mPaint.setHinting(SkPaint::kSlight_Hinting);
   497         break;
   498       case FontHinting::NORMAL:
   499         paint.mPaint.setHinting(SkPaint::kNormal_Hinting);
   500         break;
   501       case FontHinting::FULL:
   502         paint.mPaint.setHinting(SkPaint::kFull_Hinting);
   503         break;
   504     }
   506     if (static_cast<const GlyphRenderingOptionsCairo*>(aRenderingOptions)->GetAutoHinting()) {
   507       paint.mPaint.setAutohinted(true);
   508     }
   509   } else {
   510     paint.mPaint.setHinting(SkPaint::kNormal_Hinting);
   511   }
   513   std::vector<uint16_t> indices;
   514   std::vector<SkPoint> offsets;
   515   indices.resize(aBuffer.mNumGlyphs);
   516   offsets.resize(aBuffer.mNumGlyphs);
   518   for (unsigned int i = 0; i < aBuffer.mNumGlyphs; i++) {
   519     indices[i] = aBuffer.mGlyphs[i].mIndex;
   520     offsets[i].fX = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.x);
   521     offsets[i].fY = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.y);
   522   }
   524   mCanvas->drawPosText(&indices.front(), aBuffer.mNumGlyphs*2, &offsets.front(), paint.mPaint);
   525 }
   527 void
   528 DrawTargetSkia::Mask(const Pattern &aSource,
   529                      const Pattern &aMask,
   530                      const DrawOptions &aOptions)
   531 {
   532   MarkChanged();
   533   AutoPaintSetup paint(mCanvas.get(), aOptions, aSource);
   535   SkPaint maskPaint;
   536   TempBitmap tmpBitmap;
   537   SetPaintPattern(maskPaint, aMask, tmpBitmap);
   539   SkLayerRasterizer *raster = new SkLayerRasterizer();
   540   raster->addLayer(maskPaint);
   541   SkSafeUnref(paint.mPaint.setRasterizer(raster));
   543   mCanvas->drawRect(SkRectCoveringWholeSurface(), paint.mPaint);
   544 }
   546 void
   547 DrawTargetSkia::MaskSurface(const Pattern &aSource,
   548                             SourceSurface *aMask,
   549                             Point aOffset,
   550                             const DrawOptions &aOptions)
   551 {
   552   MarkChanged();
   553   AutoPaintSetup paint(mCanvas.get(), aOptions, aSource);
   555   SkPaint maskPaint;
   556   TempBitmap tmpBitmap;
   557   SetPaintPattern(maskPaint, SurfacePattern(aMask, ExtendMode::CLAMP), tmpBitmap);
   559   SkMatrix transform = maskPaint.getShader()->getLocalMatrix();
   560   transform.postTranslate(SkFloatToScalar(aOffset.x), SkFloatToScalar(aOffset.y));
   561   maskPaint.getShader()->setLocalMatrix(transform);
   563   SkLayerRasterizer *raster = new SkLayerRasterizer();
   564   raster->addLayer(maskPaint);
   565   SkSafeUnref(paint.mPaint.setRasterizer(raster));
   567   IntSize size = aMask->GetSize();
   568   Rect rect = Rect(aOffset.x, aOffset.y, size.width, size.height);
   569   mCanvas->drawRect(RectToSkRect(rect), paint.mPaint);
   570 }
   572 TemporaryRef<SourceSurface>
   573 DrawTargetSkia::CreateSourceSurfaceFromData(unsigned char *aData,
   574                                             const IntSize &aSize,
   575                                             int32_t aStride,
   576                                             SurfaceFormat aFormat) const
   577 {
   578   RefPtr<SourceSurfaceSkia> newSurf = new SourceSurfaceSkia();
   580   if (!newSurf->InitFromData(aData, aSize, aStride, aFormat)) {
   581     gfxDebug() << *this << ": Failure to create source surface from data. Size: " << aSize;
   582     return nullptr;
   583   }
   585   return newSurf;
   586 }
   588 TemporaryRef<DrawTarget>
   589 DrawTargetSkia::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
   590 {
   591   RefPtr<DrawTargetSkia> target = new DrawTargetSkia();
   592   if (!target->Init(aSize, aFormat)) {
   593     return nullptr;
   594   }
   595   return target;
   596 }
   598 TemporaryRef<SourceSurface>
   599 DrawTargetSkia::OptimizeSourceSurface(SourceSurface *aSurface) const
   600 {
   601   if (aSurface->GetType() == SurfaceType::SKIA) {
   602     return aSurface;
   603   }
   605   return aSurface->GetDataSurface();
   606 }
   608 TemporaryRef<SourceSurface>
   609 DrawTargetSkia::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
   610 {
   611   return nullptr;
   612 }
   614 void
   615 DrawTargetSkia::CopySurface(SourceSurface *aSurface,
   616                             const IntRect& aSourceRect,
   617                             const IntPoint &aDestination)
   618 {
   619   //TODO: We could just use writePixels() here if the sourceRect is the entire source
   621   if (aSurface->GetType() != SurfaceType::SKIA) {
   622     return;
   623   }
   625   MarkChanged();
   627   TempBitmap bitmap = GetBitmapForSurface(aSurface);
   629   mCanvas->save();
   630   mCanvas->resetMatrix();
   631   SkRect dest = IntRectToSkRect(IntRect(aDestination.x, aDestination.y, aSourceRect.width, aSourceRect.height)); 
   632   SkIRect source = IntRectToSkIRect(aSourceRect);
   633   mCanvas->clipRect(dest, SkRegion::kReplace_Op);
   634   SkPaint paint;
   636   if (mCanvas->getDevice()->config() == SkBitmap::kRGB_565_Config) {
   637     // Set the xfermode to SOURCE_OVER to workaround
   638     // http://code.google.com/p/skia/issues/detail?id=628
   639     // RGB565 is opaque so they're equivalent anyway
   640     paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
   641   } else {
   642     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
   643   }
   645   mCanvas->drawBitmapRect(bitmap.mBitmap, &source, dest, &paint);
   646   mCanvas->restore();
   647 }
   649 bool
   650 DrawTargetSkia::Init(const IntSize &aSize, SurfaceFormat aFormat)
   651 {
   652   SkAutoTUnref<SkBaseDevice> device(new SkBitmapDevice(GfxFormatToSkiaConfig(aFormat),
   653                                                        aSize.width, aSize.height,
   654                                                        aFormat == SurfaceFormat::B8G8R8X8));
   656   SkBitmap bitmap = device->accessBitmap(true);
   657   if (!bitmap.allocPixels()) {
   658     return false;
   659   }
   661   bitmap.eraseARGB(0, 0, 0, 0);
   663   SkAutoTUnref<SkCanvas> canvas(new SkCanvas(device.get()));
   664   mSize = aSize;
   666   mCanvas = canvas.get();
   667   mFormat = aFormat;
   668   return true;
   669 }
   671 #ifdef USE_SKIA_GPU
   672 bool
   673 DrawTargetSkia::InitWithGrContext(GrContext* aGrContext,
   674                                   const IntSize &aSize,
   675                                   SurfaceFormat aFormat)
   676 {
   677   MOZ_ASSERT(aGrContext, "null GrContext");
   679   mGrContext = aGrContext;
   681   mSize = aSize;
   682   mFormat = aFormat;
   684   GrTextureDesc targetDescriptor;
   686   targetDescriptor.fFlags = kRenderTarget_GrTextureFlagBit;
   687   targetDescriptor.fWidth = mSize.width;
   688   targetDescriptor.fHeight = mSize.height;
   689   targetDescriptor.fConfig = GfxFormatToGrConfig(mFormat);
   690   targetDescriptor.fOrigin = kBottomLeft_GrSurfaceOrigin;
   691   targetDescriptor.fSampleCnt = 0;
   693   SkAutoTUnref<GrTexture> skiaTexture(mGrContext->createUncachedTexture(targetDescriptor, NULL, 0));
   694   if (!skiaTexture) {
   695     return false;
   696   }
   698   mTexture = (uint32_t)skiaTexture->getTextureHandle();
   700   SkAutoTUnref<SkBaseDevice> device(new SkGpuDevice(mGrContext.get(), skiaTexture->asRenderTarget()));
   701   SkAutoTUnref<SkCanvas> canvas(new SkCanvas(device.get()));
   702   mCanvas = canvas.get();
   704   return true;
   705 }
   707 #endif
   709 void
   710 DrawTargetSkia::Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat)
   711 {
   712   SkAlphaType alphaType = kPremul_SkAlphaType;
   713   if (aFormat == SurfaceFormat::B8G8R8X8) {
   714     // We have to manually set the A channel to be 255 as Skia doesn't understand BGRX
   715     ConvertBGRXToBGRA(aData, aSize, aStride);
   716     alphaType = kOpaque_SkAlphaType;
   717   }
   719   SkBitmap bitmap;
   720   bitmap.setConfig(GfxFormatToSkiaConfig(aFormat), aSize.width, aSize.height, aStride, alphaType);
   721   bitmap.setPixels(aData);
   722   SkAutoTUnref<SkCanvas> canvas(new SkCanvas(new SkBitmapDevice(bitmap)));
   724   mSize = aSize;
   725   mCanvas = canvas.get();
   726   mFormat = aFormat;
   727 }
   729 void
   730 DrawTargetSkia::SetTransform(const Matrix& aTransform)
   731 {
   732   SkMatrix mat;
   733   GfxMatrixToSkiaMatrix(aTransform, mat);
   734   mCanvas->setMatrix(mat);
   735   mTransform = aTransform;
   736 }
   738 void*
   739 DrawTargetSkia::GetNativeSurface(NativeSurfaceType aType)
   740 {
   741   if (aType == NativeSurfaceType::OPENGL_TEXTURE) {
   742     return (void*)((uintptr_t)mTexture);
   743   }
   745   return nullptr;  
   746 }
   749 TemporaryRef<PathBuilder> 
   750 DrawTargetSkia::CreatePathBuilder(FillRule aFillRule) const
   751 {
   752   RefPtr<PathBuilderSkia> pb = new PathBuilderSkia(aFillRule);
   753   return pb;
   754 }
   756 void
   757 DrawTargetSkia::ClearRect(const Rect &aRect)
   758 {
   759   MarkChanged();
   760   SkPaint paint;
   761   mCanvas->save();
   762   mCanvas->clipRect(RectToSkRect(aRect), SkRegion::kIntersect_Op, true);
   763   paint.setColor(SkColorSetARGB(0, 0, 0, 0));
   764   paint.setXfermodeMode(SkXfermode::kSrc_Mode);
   765   mCanvas->drawPaint(paint);
   766   mCanvas->restore();
   767 }
   769 void
   770 DrawTargetSkia::PushClip(const Path *aPath)
   771 {
   772   if (aPath->GetBackendType() != BackendType::SKIA) {
   773     return;
   774   }
   776   const PathSkia *skiaPath = static_cast<const PathSkia*>(aPath);
   777   mCanvas->save(SkCanvas::kClip_SaveFlag);
   778   mCanvas->clipPath(skiaPath->GetPath(), SkRegion::kIntersect_Op, true);
   779 }
   781 void
   782 DrawTargetSkia::PushClipRect(const Rect& aRect)
   783 {
   784   SkRect rect = RectToSkRect(aRect);
   786   mCanvas->save(SkCanvas::kClip_SaveFlag);
   787   mCanvas->clipRect(rect, SkRegion::kIntersect_Op, true);
   788 }
   790 void
   791 DrawTargetSkia::PopClip()
   792 {
   793   mCanvas->restore();
   794 }
   796 TemporaryRef<GradientStops>
   797 DrawTargetSkia::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode) const
   798 {
   799   std::vector<GradientStop> stops;
   800   stops.resize(aNumStops);
   801   for (uint32_t i = 0; i < aNumStops; i++) {
   802     stops[i] = aStops[i];
   803   }
   804   std::stable_sort(stops.begin(), stops.end());
   806   return new GradientStopsSkia(stops, aNumStops, aExtendMode);
   807 }
   809 TemporaryRef<FilterNode>
   810 DrawTargetSkia::CreateFilter(FilterType aType)
   811 {
   812   return FilterNodeSoftware::Create(aType);
   813 }
   815 void
   816 DrawTargetSkia::MarkChanged()
   817 {
   818   if (mSnapshot) {
   819     mSnapshot->DrawTargetWillChange();
   820     mSnapshot = nullptr;
   821   }
   822 }
   824 // Return a rect (in user space) that covers the entire surface by applying
   825 // the inverse of GetTransform() to (0, 0, mSize.width, mSize.height).
   826 SkRect
   827 DrawTargetSkia::SkRectCoveringWholeSurface() const
   828 {
   829   return RectToSkRect(mTransform.TransformBounds(Rect(0, 0, mSize.width, mSize.height)));
   830 }
   832 void
   833 DrawTargetSkia::SnapshotDestroyed()
   834 {
   835   mSnapshot = nullptr;
   836 }
   838 }
   839 }

mercurial