tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RenderCompositorLayersSWGL.cpp (17375B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 *
      5 * License, v. 2.0. If a copy of the MPL was not distributed with this
      6 * file,
      7 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      8 
      9 #include "RenderCompositorLayersSWGL.h"
     10 
     11 #include "GLContext.h"
     12 #include "GLContextEGL.h"
     13 #include "mozilla/layers/BuildConstants.h"
     14 #include "mozilla/layers/Effects.h"
     15 #include "mozilla/layers/TextureHostOGL.h"
     16 #include "mozilla/widget/CompositorWidget.h"
     17 #include "RenderCompositorRecordedFrame.h"
     18 
     19 #if defined(XP_WIN)
     20 #  include "mozilla/webrender/RenderCompositorD3D11SWGL.h"
     21 #else
     22 #  include "mozilla/webrender/RenderCompositorOGLSWGL.h"
     23 #endif
     24 
     25 namespace mozilla {
     26 using namespace layers;
     27 using namespace gfx;
     28 
     29 namespace wr {
     30 
     31 UniquePtr<RenderCompositor> RenderCompositorLayersSWGL::Create(
     32    const RefPtr<widget::CompositorWidget>& aWidget, nsACString& aError) {
     33 #ifdef XP_WIN
     34  return RenderCompositorD3D11SWGL::Create(aWidget, aError);
     35 #else
     36  return RenderCompositorOGLSWGL::Create(aWidget, aError);
     37 #endif
     38 }
     39 
     40 RenderCompositorLayersSWGL::RenderCompositorLayersSWGL(
     41    Compositor* aCompositor, const RefPtr<widget::CompositorWidget>& aWidget,
     42    void* aContext)
     43    : RenderCompositor(aWidget),
     44      mCompositor(aCompositor),
     45      mContext(aContext),
     46      mCurrentTileId(wr::NativeTileId()) {
     47  MOZ_ASSERT(mCompositor);
     48  MOZ_ASSERT(mContext);
     49 }
     50 
     51 RenderCompositorLayersSWGL::~RenderCompositorLayersSWGL() {
     52  wr_swgl_destroy_context(mContext);
     53 }
     54 
     55 bool RenderCompositorLayersSWGL::MakeCurrent() {
     56  wr_swgl_make_current(mContext);
     57  return true;
     58 }
     59 
     60 bool RenderCompositorLayersSWGL::BeginFrame() {
     61  MOZ_ASSERT(!mInFrame);
     62  MakeCurrent();
     63  mInFrame = true;
     64  return true;
     65 }
     66 
     67 void RenderCompositorLayersSWGL::CancelFrame() {
     68  MOZ_ASSERT(mInFrame);
     69  mInFrame = false;
     70  if (mCompositingStarted) {
     71    mCompositor->CancelFrame();
     72    mCompositingStarted = false;
     73  }
     74 }
     75 
     76 void RenderCompositorLayersSWGL::StartCompositing(
     77    wr::ColorF aClearColor, const wr::DeviceIntRect* aDirtyRects,
     78    size_t aNumDirtyRects, const wr::DeviceIntRect* aOpaqueRects,
     79    size_t aNumOpaqueRects) {
     80  MOZ_RELEASE_ASSERT(!mCompositingStarted);
     81 
     82  if (!mInFrame || aNumDirtyRects == 0) {
     83    return;
     84  }
     85 
     86  gfx::IntRect bounds(gfx::IntPoint(0, 0), GetBufferSize().ToUnknownSize());
     87  nsIntRegion dirty;
     88 
     89  MOZ_RELEASE_ASSERT(aNumDirtyRects > 0);
     90  for (size_t i = 0; i < aNumDirtyRects; i++) {
     91    const auto& rect = aDirtyRects[i];
     92    dirty.OrWith(
     93        gfx::IntRect(rect.min.x, rect.min.y, rect.width(), rect.height()));
     94  }
     95  dirty.AndWith(bounds);
     96 
     97  nsIntRegion opaque(bounds);
     98  opaque.SubOut(mWidget->GetTransparentRegion().ToUnknownRegion());
     99  for (size_t i = 0; i < aNumOpaqueRects; i++) {
    100    const auto& rect = aOpaqueRects[i];
    101    opaque.OrWith(
    102        gfx::IntRect(rect.min.x, rect.min.y, rect.width(), rect.height()));
    103  }
    104 
    105  mCompositor->SetClearColor(gfx::DeviceColor(aClearColor.r, aClearColor.g,
    106                                              aClearColor.b, aClearColor.a));
    107 
    108  if (!mCompositor->BeginFrameForWindow(dirty, Nothing(), bounds, opaque)) {
    109    return;
    110  }
    111  mCompositingStarted = true;
    112 }
    113 
    114 void RenderCompositorLayersSWGL::CompositorEndFrame() {
    115  nsTArray<FrameSurface> frameSurfaces = std::move(mFrameSurfaces);
    116 
    117  if (!mCompositingStarted) {
    118    return;
    119  }
    120 
    121  for (auto& frameSurface : frameSurfaces) {
    122    auto surfaceCursor = mSurfaces.find(frameSurface.mId);
    123    MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
    124    Surface* surface = surfaceCursor->second.get();
    125 
    126    for (auto it = surface->mTiles.begin(); it != surface->mTiles.end(); ++it) {
    127      if (!it->second->IsValid()) {
    128        continue;
    129      }
    130 
    131      gfx::Point tileOffset(it->first.mX * surface->mTileSize.width,
    132                            it->first.mY * surface->mTileSize.height);
    133      gfx::Rect drawRect = it->second->mValidRect + tileOffset;
    134 
    135      RefPtr<EffectRoundedClip> clipEffect;
    136 
    137      if (!frameSurface.mRoundedClipRadii.IsEmpty()) {
    138        clipEffect = new EffectRoundedClip(frameSurface.mRoundedClipRect,
    139                                           frameSurface.mRoundedClipRadii);
    140      }
    141 
    142      RefPtr<TexturedEffect> texturedEffect =
    143          new EffectRGB(it->second->GetTextureSource(),
    144                        /* aPremultiplied */ true, frameSurface.mFilter);
    145      // TODO(gw): Enable premul copy on tiles that aren't affected
    146      //           by the rounded clip.
    147      if (surface->mIsOpaque && !clipEffect) {
    148        texturedEffect->mPremultipliedCopy = true;
    149      }
    150 
    151      texturedEffect->mTextureCoords =
    152          gfx::Rect(it->second->mValidRect.x / surface->mTileSize.width,
    153                    it->second->mValidRect.y / surface->mTileSize.height,
    154                    it->second->mValidRect.width / surface->mTileSize.width,
    155                    it->second->mValidRect.height / surface->mTileSize.height);
    156 
    157      EffectChain effect;
    158      effect.mPrimaryEffect = texturedEffect;
    159      effect.mRoundedClipEffect = clipEffect;
    160      mCompositor->DrawQuad(drawRect, frameSurface.mClipRect, effect, 1.0,
    161                            frameSurface.mTransform, drawRect);
    162    }
    163 
    164    if (surface->mExternalImage) {
    165      HandleExternalImage(surface->mExternalImage, frameSurface);
    166    }
    167  }
    168 }
    169 
    170 RenderedFrameId RenderCompositorLayersSWGL::EndFrame(
    171    const nsTArray<DeviceIntRect>& aDirtyRects) {
    172  MOZ_ASSERT(mInFrame);
    173  mInFrame = false;
    174  if (mCompositingStarted) {
    175    mCompositor->EndFrame();
    176    mCompositingStarted = false;
    177  }
    178  return GetNextRenderFrameId();
    179 }
    180 
    181 LayoutDeviceIntSize RenderCompositorLayersSWGL::GetBufferSize() {
    182  return mWidget->GetClientSize();
    183 }
    184 
    185 void RenderCompositorLayersSWGL::Bind(wr::NativeTileId aId,
    186                                      wr::DeviceIntPoint* aOffset,
    187                                      uint32_t* aFboId,
    188                                      wr::DeviceIntRect aDirtyRect,
    189                                      wr::DeviceIntRect aValidRect) {
    190  MOZ_RELEASE_ASSERT(false);
    191 }
    192 
    193 void RenderCompositorLayersSWGL::Unbind() { MOZ_RELEASE_ASSERT(false); }
    194 
    195 bool RenderCompositorLayersSWGL::MapTile(wr::NativeTileId aId,
    196                                         wr::DeviceIntRect aDirtyRect,
    197                                         wr::DeviceIntRect aValidRect,
    198                                         void** aData, int32_t* aStride) {
    199  auto surfaceCursor = mSurfaces.find(aId.surface_id);
    200  MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
    201  Surface* surface = surfaceCursor->second.get();
    202 
    203  auto layerCursor = surface->mTiles.find(TileKey(aId.x, aId.y));
    204  MOZ_RELEASE_ASSERT(layerCursor != surface->mTiles.end());
    205 
    206  mCurrentTile = layerCursor->second.get();
    207  mCurrentTileId = aId;
    208  mCurrentTileDirty = gfx::IntRect(aDirtyRect.min.x, aDirtyRect.min.y,
    209                                   aDirtyRect.width(), aDirtyRect.height());
    210 
    211  if (!mCurrentTile->Map(aDirtyRect, aValidRect, aData, aStride)) {
    212    gfxCriticalNote << "MapTile failed aValidRect: "
    213                    << gfx::Rect(aValidRect.min.x, aValidRect.min.y,
    214                                 aValidRect.width(), aValidRect.height());
    215    return false;
    216  }
    217 
    218  // Store the new valid rect, so that we can composite only those pixels
    219  mCurrentTile->mValidRect = gfx::Rect(aValidRect.min.x, aValidRect.min.y,
    220                                       aValidRect.width(), aValidRect.height());
    221  return true;
    222 }
    223 
    224 void RenderCompositorLayersSWGL::UnmapTile() {
    225  mCurrentTile->Unmap(mCurrentTileDirty);
    226  mCurrentTile = nullptr;
    227 }
    228 
    229 void RenderCompositorLayersSWGL::CreateSurface(
    230    wr::NativeSurfaceId aId, wr::DeviceIntPoint aVirtualOffset,
    231    wr::DeviceIntSize aTileSize, bool aIsOpaque) {
    232  MOZ_RELEASE_ASSERT(mSurfaces.find(aId) == mSurfaces.end());
    233  auto surface = DoCreateSurface(aTileSize, aIsOpaque);
    234  mSurfaces.insert({aId, std::move(surface)});
    235 }
    236 
    237 UniquePtr<RenderCompositorLayersSWGL::Surface>
    238 RenderCompositorLayersSWGL::DoCreateSurface(wr::DeviceIntSize aTileSize,
    239                                            bool aIsOpaque) {
    240  return MakeUnique<Surface>(aTileSize, aIsOpaque);
    241 }
    242 
    243 void RenderCompositorLayersSWGL::CreateExternalSurface(wr::NativeSurfaceId aId,
    244                                                       bool aIsOpaque) {
    245  MOZ_RELEASE_ASSERT(mSurfaces.find(aId) == mSurfaces.end());
    246  auto surface = MakeUnique<Surface>(wr::DeviceIntSize{}, aIsOpaque);
    247  surface->mIsExternal = true;
    248  mSurfaces.insert({aId, std::move(surface)});
    249 }
    250 
    251 void RenderCompositorLayersSWGL::DestroySurface(NativeSurfaceId aId) {
    252  auto surfaceCursor = mSurfaces.find(aId);
    253  MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
    254  mSurfaces.erase(surfaceCursor);
    255 }
    256 
    257 void RenderCompositorLayersSWGL::CreateTile(wr::NativeSurfaceId aId, int32_t aX,
    258                                            int32_t aY) {
    259  auto surfaceCursor = mSurfaces.find(aId);
    260  MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
    261  Surface* surface = surfaceCursor->second.get();
    262  MOZ_RELEASE_ASSERT(!surface->mIsExternal);
    263 
    264  auto tile = DoCreateTile(surface);
    265  surface->mTiles.insert({TileKey(aX, aY), std::move(tile)});
    266 }
    267 
    268 void RenderCompositorLayersSWGL::DestroyTile(wr::NativeSurfaceId aId,
    269                                             int32_t aX, int32_t aY) {
    270  auto surfaceCursor = mSurfaces.find(aId);
    271  MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
    272  Surface* surface = surfaceCursor->second.get();
    273  MOZ_RELEASE_ASSERT(!surface->mIsExternal);
    274 
    275  auto layerCursor = surface->mTiles.find(TileKey(aX, aY));
    276  MOZ_RELEASE_ASSERT(layerCursor != surface->mTiles.end());
    277  surface->mTiles.erase(layerCursor);
    278 }
    279 
    280 void RenderCompositorLayersSWGL::AttachExternalImage(
    281    wr::NativeSurfaceId aId, wr::ExternalImageId aExternalImage) {
    282  RenderTextureHost* image =
    283      RenderThread::Get()->GetRenderTexture(aExternalImage);
    284  MOZ_ASSERT(image);
    285  if (!image) {
    286    gfxCriticalNoteOnce
    287        << "Failed to get RenderTextureHost for D3D11SWGL extId:"
    288        << AsUint64(aExternalImage);
    289    return;
    290  }
    291 #if defined(XP_WIN)
    292  MOZ_RELEASE_ASSERT(image->AsRenderDXGITextureHost() ||
    293                     image->AsRenderDXGIYCbCrTextureHost());
    294 #elif defined(ANDROID)
    295  MOZ_RELEASE_ASSERT(image->AsRenderAndroidHardwareBufferTextureHost() ||
    296                     image->AsRenderAndroidSurfaceTextureHost() ||
    297                     image->AsRenderEGLImageTextureHost());
    298 #endif
    299 
    300  auto surfaceCursor = mSurfaces.find(aId);
    301  MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
    302 
    303  Surface* surface = surfaceCursor->second.get();
    304  surface->mExternalImage = image;
    305  MOZ_RELEASE_ASSERT(surface->mTiles.empty());
    306  MOZ_RELEASE_ASSERT(surface->mIsExternal);
    307 }
    308 
    309 // static
    310 gfx::SamplingFilter RenderCompositorLayersSWGL::ToSamplingFilter(
    311    wr::ImageRendering aImageRendering) {
    312  if (aImageRendering == wr::ImageRendering::Auto) {
    313    return gfx::SamplingFilter::LINEAR;
    314  }
    315  return gfx::SamplingFilter::POINT;
    316 }
    317 
    318 void RenderCompositorLayersSWGL::AddSurface(
    319    wr::NativeSurfaceId aId, const wr::CompositorSurfaceTransform& aTransform,
    320    wr::DeviceIntRect aClipRect, wr::ImageRendering aImageRendering,
    321    wr::DeviceIntRect aRoundedClipRect, wr::ClipRadius aClipRadius) {
    322  float sx = aTransform.scale.x;
    323  float sy = aTransform.scale.y;
    324  float tx = aTransform.offset.x;
    325  float ty = aTransform.offset.y;
    326  gfx::Matrix4x4 transform(sx, 0.0, 0.0, 0.0, 0.0, sy, 0.0, 0.0, 0.0, 0.0, 1.0,
    327                           0.0, tx, ty, 0.0, 1.0);
    328  gfx::IntRect clipRect(aClipRect.min.x, aClipRect.min.y, aClipRect.width(),
    329                        aClipRect.height());
    330 
    331  gfx::Rect roundedClipRect(aRoundedClipRect.min.x, aRoundedClipRect.min.y,
    332                            aRoundedClipRect.width(),
    333                            aRoundedClipRect.height());
    334  gfx::RectCornerRadii radii(aClipRadius.top_left, aClipRadius.top_right,
    335                             aClipRadius.bottom_right, aClipRadius.bottom_left);
    336 
    337  mFrameSurfaces.AppendElement(FrameSurface{aId, transform, clipRect,
    338                                            ToSamplingFilter(aImageRendering),
    339                                            roundedClipRect, radii});
    340 }
    341 
    342 void RenderCompositorLayersSWGL::MaybeRequestAllowFrameRecording(
    343    bool aWillRecord) {
    344  mCompositor->RequestAllowFrameRecording(aWillRecord);
    345 }
    346 
    347 class WindowLMC : public profiler_screenshots::Window {
    348 public:
    349  explicit WindowLMC(Compositor* aCompositor) : mCompositor(aCompositor) {}
    350 
    351  already_AddRefed<profiler_screenshots::RenderSource> GetWindowContents(
    352      const gfx::IntSize& aWindowSize) override;
    353  already_AddRefed<profiler_screenshots::DownscaleTarget> CreateDownscaleTarget(
    354      const gfx::IntSize& aSize) override;
    355  already_AddRefed<profiler_screenshots::AsyncReadbackBuffer>
    356  CreateAsyncReadbackBuffer(const gfx::IntSize& aSize) override;
    357 
    358 protected:
    359  Compositor* mCompositor;
    360 };
    361 
    362 class RenderSourceLMC : public profiler_screenshots::RenderSource {
    363 public:
    364  explicit RenderSourceLMC(CompositingRenderTarget* aRT)
    365      : RenderSource(aRT->GetSize()), mRT(aRT) {}
    366 
    367  const auto& RenderTarget() { return mRT; }
    368 
    369 protected:
    370  virtual ~RenderSourceLMC() {}
    371 
    372  RefPtr<CompositingRenderTarget> mRT;
    373 };
    374 
    375 class DownscaleTargetLMC : public profiler_screenshots::DownscaleTarget {
    376 public:
    377  explicit DownscaleTargetLMC(CompositingRenderTarget* aRT,
    378                              Compositor* aCompositor)
    379      : profiler_screenshots::DownscaleTarget(aRT->GetSize()),
    380        mRenderSource(new RenderSourceLMC(aRT)),
    381        mCompositor(aCompositor) {}
    382 
    383  already_AddRefed<profiler_screenshots::RenderSource> AsRenderSource()
    384      override {
    385    return do_AddRef(mRenderSource);
    386  }
    387 
    388  bool DownscaleFrom(profiler_screenshots::RenderSource* aSource,
    389                     const IntRect& aSourceRect,
    390                     const IntRect& aDestRect) override {
    391    MOZ_RELEASE_ASSERT(aSourceRect.TopLeft() == IntPoint());
    392    MOZ_RELEASE_ASSERT(aDestRect.TopLeft() == IntPoint());
    393    RefPtr<CompositingRenderTarget> previousTarget =
    394        mCompositor->GetCurrentRenderTarget();
    395 
    396    mCompositor->SetRenderTarget(mRenderSource->RenderTarget());
    397    bool result = mCompositor->BlitRenderTarget(
    398        static_cast<RenderSourceLMC*>(aSource)->RenderTarget(),
    399        aSourceRect.Size(), aDestRect.Size());
    400 
    401    // Restore the old render target.
    402    mCompositor->SetRenderTarget(previousTarget);
    403 
    404    return result;
    405  }
    406 
    407 protected:
    408  virtual ~DownscaleTargetLMC() {}
    409 
    410  RefPtr<RenderSourceLMC> mRenderSource;
    411  Compositor* mCompositor;
    412 };
    413 
    414 class AsyncReadbackBufferLMC
    415    : public profiler_screenshots::AsyncReadbackBuffer {
    416 public:
    417  AsyncReadbackBufferLMC(mozilla::layers::AsyncReadbackBuffer* aARB,
    418                         Compositor* aCompositor)
    419      : profiler_screenshots::AsyncReadbackBuffer(aARB->GetSize()),
    420        mARB(aARB),
    421        mCompositor(aCompositor) {}
    422  void CopyFrom(profiler_screenshots::RenderSource* aSource) override {
    423    mCompositor->ReadbackRenderTarget(
    424        static_cast<RenderSourceLMC*>(aSource)->RenderTarget(), mARB);
    425  }
    426  bool MapAndCopyInto(DataSourceSurface* aSurface,
    427                      const IntSize& aReadSize) override {
    428    return mARB->MapAndCopyInto(aSurface, aReadSize);
    429  }
    430 
    431 protected:
    432  virtual ~AsyncReadbackBufferLMC() {}
    433 
    434  RefPtr<mozilla::layers::AsyncReadbackBuffer> mARB;
    435  Compositor* mCompositor;
    436 };
    437 
    438 already_AddRefed<profiler_screenshots::RenderSource>
    439 WindowLMC::GetWindowContents(const gfx::IntSize& aWindowSize) {
    440  RefPtr<CompositingRenderTarget> rt = mCompositor->GetWindowRenderTarget();
    441  if (!rt) {
    442    return nullptr;
    443  }
    444  return MakeAndAddRef<RenderSourceLMC>(rt);
    445 }
    446 
    447 already_AddRefed<profiler_screenshots::DownscaleTarget>
    448 WindowLMC::CreateDownscaleTarget(const gfx::IntSize& aSize) {
    449  RefPtr<CompositingRenderTarget> rt =
    450      mCompositor->CreateRenderTarget(IntRect({}, aSize), INIT_MODE_NONE);
    451  return MakeAndAddRef<DownscaleTargetLMC>(rt, mCompositor);
    452 }
    453 
    454 already_AddRefed<profiler_screenshots::AsyncReadbackBuffer>
    455 WindowLMC::CreateAsyncReadbackBuffer(const gfx::IntSize& aSize) {
    456  RefPtr<AsyncReadbackBuffer> carb =
    457      mCompositor->CreateAsyncReadbackBuffer(aSize);
    458  if (!carb) {
    459    return nullptr;
    460  }
    461  return MakeAndAddRef<AsyncReadbackBufferLMC>(carb, mCompositor);
    462 }
    463 
    464 bool RenderCompositorLayersSWGL::MaybeRecordFrame(
    465    layers::CompositionRecorder& aRecorder) {
    466  WindowLMC window(mCompositor);
    467  gfx::IntSize size = GetBufferSize().ToUnknownSize();
    468  RefPtr<layers::profiler_screenshots::RenderSource> snapshot =
    469      window.GetWindowContents(size);
    470  if (!snapshot) {
    471    return true;
    472  }
    473 
    474  RefPtr<layers::profiler_screenshots::AsyncReadbackBuffer> buffer =
    475      window.CreateAsyncReadbackBuffer(size);
    476  buffer->CopyFrom(snapshot);
    477 
    478  RefPtr<layers::RecordedFrame> frame =
    479      new RenderCompositorRecordedFrame(TimeStamp::Now(), std::move(buffer));
    480  aRecorder.RecordFrame(frame);
    481  return false;
    482 }
    483 
    484 bool RenderCompositorLayersSWGL::MaybeGrabScreenshot(
    485    const gfx::IntSize& aWindowSize) {
    486  if (!mCompositingStarted) {
    487    return true;
    488  }
    489  WindowLMC window(mCompositor);
    490  mProfilerScreenshotGrabber.MaybeGrabScreenshot(window, aWindowSize);
    491  return true;
    492 }
    493 
    494 bool RenderCompositorLayersSWGL::MaybeProcessScreenshotQueue() {
    495  mProfilerScreenshotGrabber.MaybeProcessQueue();
    496  return true;
    497 }
    498 
    499 }  // namespace wr
    500 }  // namespace mozilla