gfx/layers/CopyableCanvasLayer.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/layers/CopyableCanvasLayer.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,200 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "BasicLayersImpl.h"            // for FillWithMask, etc
    1.10 +#include "CopyableCanvasLayer.h"
    1.11 +#include "GLContext.h"                  // for GLContext
    1.12 +#include "GLScreenBuffer.h"             // for GLScreenBuffer
    1.13 +#include "SharedSurface.h"              // for SharedSurface
    1.14 +#include "SharedSurfaceGL.h"            // for SharedSurface_GL, etc
    1.15 +#include "SurfaceTypes.h"               // for APITypeT, APITypeT::OpenGL, etc
    1.16 +#include "gfxMatrix.h"                  // for gfxMatrix
    1.17 +#include "gfxPattern.h"                 // for gfxPattern, etc
    1.18 +#include "gfxPlatform.h"                // for gfxPlatform, gfxImageFormat
    1.19 +#include "gfxRect.h"                    // for gfxRect
    1.20 +#include "gfxUtils.h"                   // for gfxUtils
    1.21 +#include "gfx2DGlue.h"                  // for thebes --> moz2d transition
    1.22 +#include "mozilla/gfx/BaseSize.h"       // for BaseSize
    1.23 +#include "nsDebug.h"                    // for NS_ASSERTION, NS_WARNING, etc
    1.24 +#include "nsISupportsImpl.h"            // for gfxContext::AddRef, etc
    1.25 +#include "nsRect.h"                     // for nsIntRect
    1.26 +#include "nsSize.h"                     // for nsIntSize
    1.27 +#include "LayerUtils.h"
    1.28 +
    1.29 +using namespace mozilla::gfx;
    1.30 +using namespace mozilla::gl;
    1.31 +
    1.32 +namespace mozilla {
    1.33 +namespace layers {
    1.34 +
    1.35 +CopyableCanvasLayer::CopyableCanvasLayer(LayerManager* aLayerManager, void *aImplData) :
    1.36 +  CanvasLayer(aLayerManager, aImplData)
    1.37 +  , mStream(nullptr)
    1.38 +{
    1.39 +  MOZ_COUNT_CTOR(CopyableCanvasLayer);
    1.40 +}
    1.41 +
    1.42 +CopyableCanvasLayer::~CopyableCanvasLayer()
    1.43 +{
    1.44 +  MOZ_COUNT_DTOR(CopyableCanvasLayer);
    1.45 +}
    1.46 +
    1.47 +void
    1.48 +CopyableCanvasLayer::Initialize(const Data& aData)
    1.49 +{
    1.50 +  NS_ASSERTION(mSurface == nullptr, "BasicCanvasLayer::Initialize called twice!");
    1.51 +
    1.52 +  if (aData.mGLContext) {
    1.53 +    mGLContext = aData.mGLContext;
    1.54 +    mStream = aData.mStream;
    1.55 +    mIsGLAlphaPremult = aData.mIsGLAlphaPremult;
    1.56 +    mNeedsYFlip = true;
    1.57 +    MOZ_ASSERT(mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
    1.58 +
    1.59 +    // [Basic Layers, non-OMTC] WebGL layer init.
    1.60 +    // `GLScreenBuffer::Morph`ing is only needed in BasicShadowableCanvasLayer.
    1.61 +  } else if (aData.mDrawTarget) {
    1.62 +    mDrawTarget = aData.mDrawTarget;
    1.63 +    mSurface = mDrawTarget->Snapshot();
    1.64 +    mNeedsYFlip = false;
    1.65 +  } else {
    1.66 +    NS_ERROR("CanvasLayer created without mSurface, mDrawTarget or mGLContext?");
    1.67 +  }
    1.68 +
    1.69 +  mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
    1.70 +}
    1.71 +
    1.72 +bool
    1.73 +CopyableCanvasLayer::IsDataValid(const Data& aData)
    1.74 +{
    1.75 +  return mGLContext == aData.mGLContext && mStream == aData.mStream;
    1.76 +}
    1.77 +
    1.78 +void
    1.79 +CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
    1.80 +{
    1.81 +  if (!IsDirty())
    1.82 +    return;
    1.83 +  Painted();
    1.84 +
    1.85 +  if (mDrawTarget) {
    1.86 +    mDrawTarget->Flush();
    1.87 +    mSurface = mDrawTarget->Snapshot();
    1.88 +  }
    1.89 +
    1.90 +  if (!mGLContext && aDestTarget) {
    1.91 +    NS_ASSERTION(mSurface, "Must have surface to draw!");
    1.92 +    if (mSurface) {
    1.93 +      aDestTarget->CopySurface(mSurface,
    1.94 +                               IntRect(0, 0, mBounds.width, mBounds.height),
    1.95 +                               IntPoint(0, 0));
    1.96 +    }
    1.97 +    return;
    1.98 +  }
    1.99 +
   1.100 +  if (mGLContext) {
   1.101 +    RefPtr<DataSourceSurface> readSurf;
   1.102 +    RefPtr<SourceSurface> resultSurf;
   1.103 +
   1.104 +    SharedSurface_GL* sharedSurf = nullptr;
   1.105 +    if (mStream) {
   1.106 +      sharedSurf = SharedSurface_GL::Cast(mStream->SwapConsumer());
   1.107 +    } else {
   1.108 +      sharedSurf = mGLContext->RequestFrame();
   1.109 +    }
   1.110 +
   1.111 +    if (!sharedSurf) {
   1.112 +      NS_WARNING("Null frame received.");
   1.113 +      return;
   1.114 +    }
   1.115 +
   1.116 +    IntSize readSize(sharedSurf->Size());
   1.117 +    SurfaceFormat format = (GetContentFlags() & CONTENT_OPAQUE)
   1.118 +                            ? SurfaceFormat::B8G8R8X8
   1.119 +                            : SurfaceFormat::B8G8R8A8;
   1.120 +
   1.121 +    if (aDestTarget) {
   1.122 +      resultSurf = aDestTarget->Snapshot();
   1.123 +      if (!resultSurf) {
   1.124 +        resultSurf = GetTempSurface(readSize, format);
   1.125 +      }
   1.126 +    } else {
   1.127 +      resultSurf = GetTempSurface(readSize, format);
   1.128 +    }
   1.129 +    MOZ_ASSERT(resultSurf);
   1.130 +    MOZ_ASSERT(sharedSurf->APIType() == APITypeT::OpenGL);
   1.131 +    SharedSurface_GL* surfGL = SharedSurface_GL::Cast(sharedSurf);
   1.132 +
   1.133 +    if (surfGL->Type() == SharedSurfaceType::Basic) {
   1.134 +      // sharedSurf_Basic->mData must outlive readSurf. Alas, readSurf may not
   1.135 +      // leave the scope it was declared in.
   1.136 +      SharedSurface_Basic* sharedSurf_Basic = SharedSurface_Basic::Cast(surfGL);
   1.137 +      readSurf = sharedSurf_Basic->GetData();
   1.138 +    } else {
   1.139 +      if (resultSurf->GetSize() != readSize ||
   1.140 +          !(readSurf = resultSurf->GetDataSurface()) ||
   1.141 +          readSurf->GetFormat() != format)
   1.142 +      {
   1.143 +        readSurf = GetTempSurface(readSize, format);
   1.144 +      }
   1.145 +
   1.146 +      // Readback handles Flush/MarkDirty.
   1.147 +      mGLContext->Screen()->Readback(surfGL, readSurf);
   1.148 +    }
   1.149 +    MOZ_ASSERT(readSurf);
   1.150 +
   1.151 +    bool needsPremult = surfGL->HasAlpha() && !mIsGLAlphaPremult;
   1.152 +    if (needsPremult) {
   1.153 +      PremultiplySurface(readSurf);
   1.154 +    }
   1.155 +
   1.156 +    if (readSurf != resultSurf) {
   1.157 +      RefPtr<DataSourceSurface> resultDataSurface =
   1.158 +        resultSurf->GetDataSurface();
   1.159 +      RefPtr<DrawTarget> dt =
   1.160 +        Factory::CreateDrawTargetForData(BackendType::CAIRO,
   1.161 +                                         resultDataSurface->GetData(),
   1.162 +                                         resultDataSurface->GetSize(),
   1.163 +                                         resultDataSurface->Stride(),
   1.164 +                                         resultDataSurface->GetFormat());
   1.165 +      IntSize readSize = readSurf->GetSize();
   1.166 +      dt->CopySurface(readSurf,
   1.167 +                      IntRect(0, 0, readSize.width, readSize.height),
   1.168 +                      IntPoint(0, 0));
   1.169 +    }
   1.170 +
   1.171 +    // If !aDestSurface then we will end up painting using mSurface, so
   1.172 +    // stick our surface into mSurface, so that the Paint() path is the same.
   1.173 +    if (!aDestTarget) {
   1.174 +      mSurface = resultSurf;
   1.175 +    }
   1.176 +  }
   1.177 +}
   1.178 +
   1.179 +DataSourceSurface*
   1.180 +CopyableCanvasLayer::GetTempSurface(const IntSize& aSize,
   1.181 +                                    const SurfaceFormat aFormat)
   1.182 +{
   1.183 +  if (!mCachedTempSurface ||
   1.184 +      aSize.width != mCachedSize.width ||
   1.185 +      aSize.height != mCachedSize.height ||
   1.186 +      aFormat != mCachedFormat)
   1.187 +  {
   1.188 +    mCachedTempSurface = Factory::CreateDataSourceSurface(aSize, aFormat);
   1.189 +    mCachedSize = aSize;
   1.190 +    mCachedFormat = aFormat;
   1.191 +  }
   1.192 +
   1.193 +  return mCachedTempSurface;
   1.194 +}
   1.195 +
   1.196 +void
   1.197 +CopyableCanvasLayer::DiscardTempSurface()
   1.198 +{
   1.199 +  mCachedTempSurface = nullptr;
   1.200 +}
   1.201 +
   1.202 +}
   1.203 +}

mercurial