gfx/layers/basic/BasicCompositor.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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 "BasicCompositor.h"
     7 #include "BasicLayersImpl.h"            // for FillRectWithMask
     8 #include "TextureHostBasic.h"
     9 #include "mozilla/layers/Effects.h"
    10 #include "mozilla/layers/YCbCrImageDataSerializer.h"
    11 #include "nsIWidget.h"
    12 #include "gfx2DGlue.h"
    13 #include "mozilla/gfx/2D.h"
    14 #include "mozilla/gfx/Helpers.h"
    15 #include "gfxUtils.h"
    16 #include "YCbCrUtils.h"
    17 #include <algorithm>
    18 #include "ImageContainer.h"
    19 #include "gfxPrefs.h"
    20 #define PIXMAN_DONT_DEFINE_STDINT
    21 #include "pixman.h"                     // for pixman_f_transform, etc
    23 namespace mozilla {
    24 using namespace mozilla::gfx;
    26 namespace layers {
    28 class DataTextureSourceBasic : public DataTextureSource
    29                              , public TextureSourceBasic
    30 {
    31 public:
    33   virtual TextureSourceBasic* AsSourceBasic() MOZ_OVERRIDE { return this; }
    35   virtual gfx::SourceSurface* GetSurface(DrawTarget* aTarget) MOZ_OVERRIDE { return mSurface; }
    37   SurfaceFormat GetFormat() const MOZ_OVERRIDE
    38   {
    39     return mSurface->GetFormat();
    40   }
    42   virtual IntSize GetSize() const MOZ_OVERRIDE
    43   {
    44     return mSurface->GetSize();
    45   }
    47   virtual bool Update(gfx::DataSourceSurface* aSurface,
    48                       nsIntRegion* aDestRegion = nullptr,
    49                       gfx::IntPoint* aSrcOffset = nullptr) MOZ_OVERRIDE
    50   {
    51     // XXX - For this to work with IncrementalContentHost we will need to support
    52     // the aDestRegion and aSrcOffset parameters properly;
    53     mSurface = aSurface;
    54     return true;
    55   }
    57   virtual void DeallocateDeviceData() MOZ_OVERRIDE
    58   {
    59     mSurface = nullptr;
    60     SetUpdateSerial(0);
    61   }
    63 public:
    64   RefPtr<gfx::DataSourceSurface> mSurface;
    65 };
    67 BasicCompositor::BasicCompositor(nsIWidget *aWidget)
    68   : mWidget(aWidget)
    69 {
    70   MOZ_COUNT_CTOR(BasicCompositor);
    71   SetBackend(LayersBackend::LAYERS_BASIC);
    72 }
    74 BasicCompositor::~BasicCompositor()
    75 {
    76   MOZ_COUNT_DTOR(BasicCompositor);
    77 }
    79 void BasicCompositor::Destroy()
    80 {
    81   mWidget->CleanupRemoteDrawing();
    82   mWidget = nullptr;
    83 }
    85 TemporaryRef<CompositingRenderTarget>
    86 BasicCompositor::CreateRenderTarget(const IntRect& aRect, SurfaceInitMode aInit)
    87 {
    88   RefPtr<DrawTarget> target = mDrawTarget->CreateSimilarDrawTarget(aRect.Size(), SurfaceFormat::B8G8R8A8);
    90   RefPtr<BasicCompositingRenderTarget> rt = new BasicCompositingRenderTarget(target, aRect);
    92   return rt.forget();
    93 }
    95 TemporaryRef<CompositingRenderTarget>
    96 BasicCompositor::CreateRenderTargetFromSource(const IntRect &aRect,
    97                                               const CompositingRenderTarget *aSource,
    98                                               const IntPoint &aSourcePoint)
    99 {
   100   RefPtr<DrawTarget> target = mDrawTarget->CreateSimilarDrawTarget(aRect.Size(), SurfaceFormat::B8G8R8A8);
   101   RefPtr<BasicCompositingRenderTarget> rt = new BasicCompositingRenderTarget(target, aRect);
   103   DrawTarget *source;
   104   if (aSource) {
   105     const BasicCompositingRenderTarget* sourceSurface =
   106       static_cast<const BasicCompositingRenderTarget*>(aSource);
   107     source = sourceSurface->mDrawTarget;
   108   } else {
   109     source = mDrawTarget;
   110   }
   112   RefPtr<SourceSurface> snapshot = source->Snapshot();
   114   IntRect sourceRect(aSourcePoint, aRect.Size());
   115   rt->mDrawTarget->CopySurface(snapshot, sourceRect, IntPoint(0, 0));
   116   return rt.forget();
   117 }
   119 TemporaryRef<DataTextureSource>
   120 BasicCompositor::CreateDataTextureSource(TextureFlags aFlags)
   121 {
   122   RefPtr<DataTextureSource> result = new DataTextureSourceBasic();
   123   return result.forget();
   124 }
   126 bool
   127 BasicCompositor::SupportsEffect(EffectTypes aEffect)
   128 {
   129   return static_cast<EffectTypes>(aEffect) != EFFECT_YCBCR;
   130 }
   132 static void
   133 DrawSurfaceWithTextureCoords(DrawTarget *aDest,
   134                              const gfx::Rect& aDestRect,
   135                              SourceSurface *aSource,
   136                              const gfx::Rect& aTextureCoords,
   137                              gfx::Filter aFilter,
   138                              float aOpacity,
   139                              SourceSurface *aMask,
   140                              const Matrix* aMaskTransform)
   141 {
   142   // Convert aTextureCoords into aSource's coordinate space
   143   gfxRect sourceRect(aTextureCoords.x * aSource->GetSize().width,
   144                      aTextureCoords.y * aSource->GetSize().height,
   145                      aTextureCoords.width * aSource->GetSize().width,
   146                      aTextureCoords.height * aSource->GetSize().height);
   147   // Compute a transform that maps sourceRect to aDestRect.
   148   gfxMatrix transform =
   149     gfxUtils::TransformRectToRect(sourceRect,
   150                                   gfxPoint(aDestRect.x, aDestRect.y),
   151                                   gfxPoint(aDestRect.XMost(), aDestRect.y),
   152                                   gfxPoint(aDestRect.XMost(), aDestRect.YMost()));
   153   Matrix matrix = ToMatrix(transform);
   155   // Only use REPEAT if aTextureCoords is outside (0, 0, 1, 1).
   156   gfx::Rect unitRect(0, 0, 1, 1);
   157   ExtendMode mode = unitRect.Contains(aTextureCoords) ? ExtendMode::CLAMP : ExtendMode::REPEAT;
   159   FillRectWithMask(aDest, aDestRect, aSource, aFilter, DrawOptions(aOpacity),
   160                    mode, aMask, aMaskTransform, &matrix);
   161 }
   163 static pixman_transform
   164 Matrix3DToPixman(const gfx3DMatrix& aMatrix)
   165 {
   166   pixman_f_transform transform;
   168   transform.m[0][0] = aMatrix._11;
   169   transform.m[0][1] = aMatrix._21;
   170   transform.m[0][2] = aMatrix._41;
   171   transform.m[1][0] = aMatrix._12;
   172   transform.m[1][1] = aMatrix._22;
   173   transform.m[1][2] = aMatrix._42;
   174   transform.m[2][0] = aMatrix._14;
   175   transform.m[2][1] = aMatrix._24;
   176   transform.m[2][2] = aMatrix._44;
   178   pixman_transform result;
   179   pixman_transform_from_pixman_f_transform(&result, &transform);
   181   return result;
   182 }
   184 static void
   185 PixmanTransform(DataSourceSurface* aDest,
   186                 DataSourceSurface* aSource,
   187                 const gfx3DMatrix& aTransform,
   188                 gfxPoint aDestOffset)
   189 {
   190   IntSize destSize = aDest->GetSize();
   191   pixman_image_t* dest = pixman_image_create_bits(PIXMAN_a8r8g8b8,
   192                                                   destSize.width,
   193                                                   destSize.height,
   194                                                   (uint32_t*)aDest->GetData(),
   195                                                   aDest->Stride());
   197   IntSize srcSize = aSource->GetSize();
   198   pixman_image_t* src = pixman_image_create_bits(PIXMAN_a8r8g8b8,
   199                                                  srcSize.width,
   200                                                  srcSize.height,
   201                                                  (uint32_t*)aSource->GetData(),
   202                                                  aSource->Stride());
   204   NS_ABORT_IF_FALSE(src && dest, "Failed to create pixman images?");
   206   pixman_transform pixTransform = Matrix3DToPixman(aTransform);
   207   pixman_transform pixTransformInverted;
   209   // If the transform is singular then nothing would be drawn anyway, return here
   210   if (!pixman_transform_invert(&pixTransformInverted, &pixTransform)) {
   211     pixman_image_unref(dest);
   212     pixman_image_unref(src);
   213     return;
   214   }
   215   pixman_image_set_transform(src, &pixTransformInverted);
   217   pixman_image_composite32(PIXMAN_OP_SRC,
   218                            src,
   219                            nullptr,
   220                            dest,
   221                            aDestOffset.x,
   222                            aDestOffset.y,
   223                            0,
   224                            0,
   225                            0,
   226                            0,
   227                            destSize.width,
   228                            destSize.height);
   230   pixman_image_unref(dest);
   231   pixman_image_unref(src);
   232 }
   234 static inline IntRect
   235 RoundOut(Rect r)
   236 {
   237   r.RoundOut();
   238   return IntRect(r.x, r.y, r.width, r.height);
   239 }
   241 void
   242 BasicCompositor::DrawQuad(const gfx::Rect& aRect,
   243                           const gfx::Rect& aClipRect,
   244                           const EffectChain &aEffectChain,
   245                           gfx::Float aOpacity,
   246                           const gfx::Matrix4x4 &aTransform)
   247 {
   248   RefPtr<DrawTarget> buffer = mRenderTarget->mDrawTarget;
   250   // For 2D drawing, |dest| and |buffer| are the same surface. For 3D drawing,
   251   // |dest| is a temporary surface.
   252   RefPtr<DrawTarget> dest = buffer;
   254   buffer->PushClipRect(aClipRect);
   255   AutoSaveTransform autoSaveTransform(dest);
   257   Matrix newTransform;
   258   Rect transformBounds;
   259   gfx3DMatrix new3DTransform;
   260   IntPoint offset = mRenderTarget->GetOrigin();
   262   if (aTransform.Is2D()) {
   263     newTransform = aTransform.As2D();
   264   } else {
   265     // Create a temporary surface for the transform.
   266     dest = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(RoundOut(aRect).Size(), SurfaceFormat::B8G8R8A8);
   267     if (!dest) {
   268       return;
   269     }
   271     // Get the bounds post-transform.
   272     To3DMatrix(aTransform, new3DTransform);
   273     gfxRect bounds = new3DTransform.TransformBounds(ThebesRect(aRect));
   274     bounds.IntersectRect(bounds, gfxRect(offset.x, offset.y, buffer->GetSize().width, buffer->GetSize().height));
   276     transformBounds = ToRect(bounds);
   277     transformBounds.RoundOut();
   279     // Propagate the coordinate offset to our 2D draw target.
   280     newTransform.Translate(transformBounds.x, transformBounds.y);
   282     // When we apply the 3D transformation, we do it against a temporary
   283     // surface, so undo the coordinate offset.
   284     new3DTransform = new3DTransform * gfx3DMatrix::Translation(-transformBounds.x, -transformBounds.y, 0);
   286     transformBounds.MoveTo(0, 0);
   287   }
   289   newTransform.PostTranslate(-offset.x, -offset.y);
   290   buffer->SetTransform(newTransform);
   292   RefPtr<SourceSurface> sourceMask;
   293   Matrix maskTransform;
   294   if (aEffectChain.mSecondaryEffects[EFFECT_MASK]) {
   295     EffectMask *effectMask = static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EFFECT_MASK].get());
   296     sourceMask = effectMask->mMaskTexture->AsSourceBasic()->GetSurface(dest);
   297     MOZ_ASSERT(effectMask->mMaskTransform.Is2D(), "How did we end up with a 3D transform here?!");
   298     MOZ_ASSERT(!effectMask->mIs3D);
   299     maskTransform = effectMask->mMaskTransform.As2D();
   300     maskTransform.Translate(-offset.x, -offset.y);
   301   }
   303   switch (aEffectChain.mPrimaryEffect->mType) {
   304     case EFFECT_SOLID_COLOR: {
   305       EffectSolidColor* effectSolidColor =
   306         static_cast<EffectSolidColor*>(aEffectChain.mPrimaryEffect.get());
   308       FillRectWithMask(dest, aRect, effectSolidColor->mColor,
   309                        DrawOptions(aOpacity), sourceMask, &maskTransform);
   310       break;
   311     }
   312     case EFFECT_RGB: {
   313       TexturedEffect* texturedEffect =
   314           static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
   315       TextureSourceBasic* source = texturedEffect->mTexture->AsSourceBasic();
   317       DrawSurfaceWithTextureCoords(dest, aRect,
   318                                    source->GetSurface(dest),
   319                                    texturedEffect->mTextureCoords,
   320                                    texturedEffect->mFilter,
   321                                    aOpacity, sourceMask, &maskTransform);
   322       break;
   323     }
   324     case EFFECT_YCBCR: {
   325       NS_RUNTIMEABORT("Can't (easily) support component alpha with BasicCompositor!");
   326       break;
   327     }
   328     case EFFECT_RENDER_TARGET: {
   329       EffectRenderTarget* effectRenderTarget =
   330         static_cast<EffectRenderTarget*>(aEffectChain.mPrimaryEffect.get());
   331       RefPtr<BasicCompositingRenderTarget> surface
   332         = static_cast<BasicCompositingRenderTarget*>(effectRenderTarget->mRenderTarget.get());
   333       RefPtr<SourceSurface> sourceSurf = surface->mDrawTarget->Snapshot();
   335       DrawSurfaceWithTextureCoords(dest, aRect,
   336                                    sourceSurf,
   337                                    effectRenderTarget->mTextureCoords,
   338                                    effectRenderTarget->mFilter,
   339                                    aOpacity, sourceMask, &maskTransform);
   340       break;
   341     }
   342     case EFFECT_COMPONENT_ALPHA: {
   343       NS_RUNTIMEABORT("Can't (easily) support component alpha with BasicCompositor!");
   344       break;
   345     }
   346     default: {
   347       NS_RUNTIMEABORT("Invalid effect type!");
   348       break;
   349     }
   350   }
   352   if (!aTransform.Is2D()) {
   353     dest->Flush();
   355     RefPtr<SourceSurface> snapshot = dest->Snapshot();
   356     RefPtr<DataSourceSurface> source = snapshot->GetDataSurface();
   357     RefPtr<DataSourceSurface> temp =
   358       Factory::CreateDataSourceSurface(RoundOut(transformBounds).Size(), SurfaceFormat::B8G8R8A8);
   359     if (!temp) {
   360       return;
   361     }
   363     PixmanTransform(temp, source, new3DTransform, gfxPoint(0, 0));
   365     buffer->DrawSurface(temp, transformBounds, transformBounds);
   366   }
   368   buffer->PopClip();
   369 }
   371 void
   372 BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion,
   373                             const gfx::Rect *aClipRectIn,
   374                             const gfx::Matrix& aTransform,
   375                             const gfx::Rect& aRenderBounds,
   376                             gfx::Rect *aClipRectOut /* = nullptr */,
   377                             gfx::Rect *aRenderBoundsOut /* = nullptr */)
   378 {
   379   nsIntRect intRect;
   380   mWidget->GetClientBounds(intRect);
   381   mWidgetSize = gfx::ToIntSize(intRect.Size());
   383   // The result of GetClientBounds is shifted over by the size of the window
   384   // manager styling. We want to ignore that.
   385   intRect.MoveTo(0, 0);
   386   Rect rect = Rect(0, 0, intRect.width, intRect.height);
   388   // Sometimes the invalid region is larger than we want to draw.
   389   nsIntRegion invalidRegionSafe;
   390   invalidRegionSafe.And(aInvalidRegion, intRect);
   392   // FIXME: Redraw the whole screen in every frame to work around bug 972728.
   393   invalidRegionSafe = intRect;
   395   nsIntRect invalidRect = invalidRegionSafe.GetBounds();
   396   mInvalidRect = IntRect(invalidRect.x, invalidRect.y, invalidRect.width, invalidRect.height);
   397   mInvalidRegion = invalidRegionSafe;
   399   if (aRenderBoundsOut) {
   400     *aRenderBoundsOut = Rect();
   401   }
   403   if (mInvalidRect.width <= 0 || mInvalidRect.height <= 0) {
   404     return;
   405   }
   407   if (mCopyTarget) {
   408     // If we have a copy target, then we don't have a widget-provided mDrawTarget (currently). Create a dummy
   409     // placeholder so that CreateRenderTarget() works.
   410     mDrawTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(IntSize(1,1), SurfaceFormat::B8G8R8A8);
   411   } else {
   412     mDrawTarget = mWidget->StartRemoteDrawing();
   413   }
   414   if (!mDrawTarget) {
   415     return;
   416   }
   418   // Setup an intermediate render target to buffer all compositing. We will
   419   // copy this into mDrawTarget (the widget), and/or mCopyTarget in EndFrame()
   420   RefPtr<CompositingRenderTarget> target = CreateRenderTarget(mInvalidRect, INIT_MODE_CLEAR);
   421   SetRenderTarget(target);
   423   // We only allocate a surface sized to the invalidated region, so we need to
   424   // translate future coordinates.
   425   Matrix transform;
   426   transform.Translate(-invalidRect.x, -invalidRect.y);
   427   mRenderTarget->mDrawTarget->SetTransform(transform);
   429   gfxUtils::ClipToRegion(mRenderTarget->mDrawTarget, invalidRegionSafe);
   431   if (aRenderBoundsOut) {
   432     *aRenderBoundsOut = rect;
   433   }
   435   if (aClipRectIn) {
   436     mRenderTarget->mDrawTarget->PushClipRect(*aClipRectIn);
   437   } else {
   438     mRenderTarget->mDrawTarget->PushClipRect(rect);
   439     if (aClipRectOut) {
   440       *aClipRectOut = rect;
   441     }
   442   }
   443 }
   445 void
   446 BasicCompositor::EndFrame()
   447 {
   448   // Pop aClipRectIn/bounds rect
   449   mRenderTarget->mDrawTarget->PopClip();
   451   if (gfxPrefs::WidgetUpdateFlashing()) {
   452     float r = float(rand()) / RAND_MAX;
   453     float g = float(rand()) / RAND_MAX;
   454     float b = float(rand()) / RAND_MAX;
   455     // We're still clipped to mInvalidRegion, so just fill the bounds.
   456     mRenderTarget->mDrawTarget->FillRect(ToRect(mInvalidRegion.GetBounds()),
   457                                          ColorPattern(Color(r, g, b, 0.2f)));
   458   }
   460   // Pop aInvalidregion
   461   mRenderTarget->mDrawTarget->PopClip();
   463   // Note: Most platforms require us to buffer drawing to the widget surface.
   464   // That's why we don't draw to mDrawTarget directly.
   465   RefPtr<SourceSurface> source = mRenderTarget->mDrawTarget->Snapshot();
   466   RefPtr<DrawTarget> dest(mCopyTarget ? mCopyTarget : mDrawTarget);
   468   // The source DrawTarget is clipped to the invalidation region, so we have
   469   // to copy the individual rectangles in the region or else we'll draw blank
   470   // pixels.
   471   nsIntRegionRectIterator iter(mInvalidRegion);
   472   for (const nsIntRect *r = iter.Next(); r; r = iter.Next()) {
   473     dest->CopySurface(source,
   474                       IntRect(r->x - mInvalidRect.x, r->y - mInvalidRect.y, r->width, r->height),
   475                       IntPoint(r->x, r->y));
   476   }
   477   if (!mCopyTarget) {
   478     mWidget->EndRemoteDrawing();
   479   }
   481   mDrawTarget = nullptr;
   482   mRenderTarget = nullptr;
   483 }
   485 void
   486 BasicCompositor::AbortFrame()
   487 {
   488   mRenderTarget->mDrawTarget->PopClip();
   489   mRenderTarget->mDrawTarget->PopClip();
   490   mDrawTarget = nullptr;
   491   mRenderTarget = nullptr;
   492 }
   494 }
   495 }

mercurial