Пример #1
0
void
ClientCanvasLayer::RenderLayer()
{
    PROFILER_LABEL("ClientCanvasLayer", "RenderLayer",
                   js::ProfileEntry::Category::GRAPHICS);

    RenderMaskLayers(this);

    if (!mCanvasClient) {
        TextureFlags flags = TextureFlags::IMMEDIATE_UPLOAD;
        if (mOriginPos == gl::OriginPos::BottomLeft) {
            flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
        }

        if (!mGLContext) {
            // We don't support locking for buffer surfaces currently
            flags |= TextureFlags::IMMEDIATE_UPLOAD;
        }

        if (!mIsAlphaPremultiplied) {
            flags |= TextureFlags::NON_PREMULTIPLIED;
        }

        mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(),
                        ClientManager()->AsShadowForwarder(),
                        flags);
        if (!mCanvasClient) {
            return;
        }
        if (HasShadow()) {
            if (mAsyncRenderer) {
                static_cast<CanvasClientBridge*>(mCanvasClient.get())->SetLayer(this);
            } else {
                mCanvasClient->Connect();
                ClientManager()->AsShadowForwarder()->Attach(mCanvasClient, this);
            }
        }
    }

    if (mCanvasClient && mAsyncRenderer) {
        mCanvasClient->UpdateAsync(mAsyncRenderer);
    }

    if (!IsDirty()) {
        return;
    }
    Painted();

    FirePreTransactionCallback();
    if (mBufferProvider && mBufferProvider->GetTextureClient()) {
        mCanvasClient->UpdateFromTexture(mBufferProvider->GetTextureClient());
    } else {
        mCanvasClient->Update(gfx::IntSize(mBounds.width, mBounds.height), this);
    }

    FireDidTransactionCallback();

    ClientManager()->Hold(this);
    mCanvasClient->Updated();
}
Пример #2
0
void
ClientThebesLayer::RenderLayer()
{
  if (GetMaskLayer()) {
    ToClientLayer(GetMaskLayer())->RenderLayer();
  }
  
  if (!mContentClient) {
    mContentClient = ContentClient::CreateContentClient(ClientManager()->AsShadowForwarder());
    if (!mContentClient) {
      return;
    }
    mContentClient->Connect();
    ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
    MOZ_ASSERT(mContentClient->GetForwarder());
  }

  mContentClient->BeginPaint();
  PaintThebes();
  mContentClient->EndPaint();
  // It is very important that this is called after EndPaint, because destroying
  // textures is a three stage process:
  // 1. We are done with the buffer and move it to ContentClient::mOldTextures,
  // that happens in DestroyBuffers which is may be called indirectly from
  // PaintThebes.
  // 2. The content client calls RemoveTextureClient on the texture clients in
  // mOldTextures and forgets them. They then become invalid. The compositable
  // client keeps a record of IDs. This happens in EndPaint.
  // 3. An IPC message is sent to destroy the corresponding texture host. That
  // happens from OnTransaction.
  // It is important that these steps happen in order.
  mContentClient->OnTransaction();
}
Пример #3
0
void
ClientThebesLayer::PaintThebes()
{
  PROFILER_LABEL("ClientThebesLayer", "PaintThebes");
  NS_ASSERTION(ClientManager()->InDrawing(),
               "Can only draw in drawing phase");
  
  //TODO: This is going to copy back pixels that we might end up
  // drawing over anyway. It would be nice if we could avoid
  // this duplication.
  mContentClient->SyncFrontBufferToBackBuffer();

  bool canUseOpaqueSurface = CanUseOpaqueSurface();
  ContentType contentType =
    canUseOpaqueSurface ? GFX_CONTENT_COLOR :
                          GFX_CONTENT_COLOR_ALPHA;

  {
    uint32_t flags = 0;
#ifndef MOZ_WIDGET_ANDROID
    if (ClientManager()->CompositorMightResample()) {
      flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE;
    }
    if (!(flags & ThebesLayerBuffer::PAINT_WILL_RESAMPLE)) {
      if (MayResample()) {
        flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE;
      }
    }
#endif
    PaintState state =
      mContentClient->BeginPaintBuffer(this, contentType, flags);
    mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);

    if (state.mContext) {
      // The area that became invalid and is visible needs to be repainted
      // (this could be the whole visible area if our buffer switched
      // from RGB to RGBA, because we might need to repaint with
      // subpixel AA)
      state.mRegionToInvalidate.And(state.mRegionToInvalidate,
                                    GetEffectiveVisibleRegion());
      nsIntRegion extendedDrawRegion = state.mRegionToDraw;
      SetAntialiasingFlags(this, state.mContext);

      PaintBuffer(state.mContext,
                  state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate,
                  state.mDidSelfCopy, state.mClip);
      MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
      Mutated();
    } else {
      // It's possible that state.mRegionToInvalidate is nonempty here,
      // if we are shrinking the valid region to nothing. So use mRegionToDraw
      // instead.
      NS_WARN_IF_FALSE(state.mRegionToDraw.IsEmpty(),
                       "No context when we have something to draw, resource exhaustion?");
    }
  }
}
Пример #4
0
void
ClientCanvasLayer::RenderLayer()
{
  PROFILER_LABEL("ClientCanvasLayer", "RenderLayer",
    js::ProfileEntry::Category::GRAPHICS);

  if (GetMaskLayer()) {
    ToClientLayer(GetMaskLayer())->RenderLayer();
  }

  if (!IsDirty()) {
    return;
  }

  if (!mCanvasClient) {
    TextureFlags flags = TextureFlags::IMMEDIATE_UPLOAD;
    if (mNeedsYFlip) {
      flags |= TextureFlags::NEEDS_Y_FLIP;
    }

    if (!mGLContext) {
      // We don't support locking for buffer surfaces currently
      flags |= TextureFlags::IMMEDIATE_UPLOAD;
    } else {
      // GLContext's SurfaceStream handles ownership itself,
      // and doesn't require layers to do any deallocation.
      flags |= TextureFlags::DEALLOCATE_CLIENT;
    }

    if (!mIsAlphaPremultiplied) {
      flags |= TextureFlags::NON_PREMULTIPLIED;
    }

    mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(),
                                                     ClientManager()->AsShadowForwarder(),
                                                     flags);
    if (!mCanvasClient) {
      return;
    }
    if (HasShadow()) {
      mCanvasClient->Connect();
      ClientManager()->AsShadowForwarder()->Attach(mCanvasClient, this);
    }
  }

  FirePreTransactionCallback();
  mCanvasClient->Update(gfx::IntSize(mBounds.width, mBounds.height), this);

  FireDidTransactionCallback();

  ClientManager()->Hold(this);
  mCanvasClient->Updated();
  mCanvasClient->OnTransaction();
}
Пример #5
0
void
ClientThebesLayer::PaintThebes()
{
  PROFILER_LABEL("ClientThebesLayer", "PaintThebes");
  NS_ASSERTION(ClientManager()->InDrawing(),
               "Can only draw in drawing phase");
  
  {
    mContentClient->PrepareFrame();

    uint32_t flags = 0;
#ifndef MOZ_WIDGET_ANDROID
    if (ClientManager()->CompositorMightResample()) {
      flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE;
    }
    if (!(flags & RotatedContentBuffer::PAINT_WILL_RESAMPLE)) {
      if (MayResample()) {
        flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE;
      }
    }
#endif
    PaintState state =
      mContentClient->BeginPaintBuffer(this, flags);
    mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);

    if (DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(this, state)) {
      // The area that became invalid and is visible needs to be repainted
      // (this could be the whole visible area if our buffer switched
      // from RGB to RGBA, because we might need to repaint with
      // subpixel AA)
      state.mRegionToInvalidate.And(state.mRegionToInvalidate,
                                    GetEffectiveVisibleRegion());
      SetAntialiasingFlags(this, target);

      nsRefPtr<gfxContext> ctx = gfxContext::ContextForDrawTarget(target);
      PaintBuffer(ctx,
                  state.mRegionToDraw, state.mRegionToDraw, state.mRegionToInvalidate,
                  state.mDidSelfCopy, state.mClip);
      MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
      Mutated();
      ctx = nullptr;
      mContentClient->ReturnDrawTargetToBuffer(target);
    } else {
      // It's possible that state.mRegionToInvalidate is nonempty here,
      // if we are shrinking the valid region to nothing. So use mRegionToDraw
      // instead.
      NS_WARN_IF_FALSE(state.mRegionToDraw.IsEmpty(),
                       "No context when we have something to draw, resource exhaustion?");
    }
  }
}
Пример #6
0
void
ClientPaintedLayer::PaintThebes(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates)
{
  AUTO_PROFILER_LABEL("ClientPaintedLayer::PaintThebes", GRAPHICS);

  NS_ASSERTION(ClientManager()->InDrawing(),
               "Can only draw in drawing phase");

  mContentClient->BeginPaint();

  uint32_t flags = GetPaintFlags();

  PaintState state = mContentClient->BeginPaintBuffer(this, flags);
  if (!UpdatePaintRegion(state)) {
    return;
  }

  bool didUpdate = false;
  RotatedContentBuffer::DrawIterator iter;
  while (DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state, &iter)) {
    if (!target || !target->IsValid()) {
      if (target) {
        mContentClient->ReturnDrawTargetToBuffer(target);
      }
      continue;
    }

    SetAntialiasingFlags(this, target);

    RefPtr<gfxContext> ctx = gfxContext::CreatePreservingTransformOrNull(target);
    MOZ_ASSERT(ctx); // already checked the target above

    ClientManager()->GetPaintedLayerCallback()(this,
                                              ctx,
                                              iter.mDrawRegion,
                                              iter.mDrawRegion,
                                              state.mClip,
                                              state.mRegionToInvalidate,
                                              ClientManager()->GetPaintedLayerCallbackData());

    ctx = nullptr;
    mContentClient->ReturnDrawTargetToBuffer(target);
    didUpdate = true;
  }

  mContentClient->EndPaint(aReadbackUpdates);

  if (didUpdate) {
    UpdateContentClient(state);
  }
}
Пример #7
0
void
ClientCanvasLayer::Initialize(const Data& aData)
{
  CopyableCanvasLayer::Initialize(aData);
 
  mCanvasClient = nullptr;

  if (mGLContext) {
    GLScreenBuffer* screen = mGLContext->Screen();
    SurfaceStreamType streamType =
        SurfaceStream::ChooseGLStreamType(SurfaceStream::OffMainThread,
                                          screen->PreserveBuffer());
    SurfaceFactory_GL* factory = nullptr;
    if (!mForceReadback) {
      if (ClientManager()->AsShadowForwarder()->GetCompositorBackendType() == mozilla::layers::LayersBackend::LAYERS_OPENGL) {
        if (mGLContext->GetContextType() == GLContextType::EGL) {
          bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);

          if (!isCrossProcess) {
            // [Basic/OGL Layers, OMTC] WebGL layer init.
            factory = SurfaceFactory_EGLImage::Create(mGLContext, screen->Caps());
          } else {
            // [Basic/OGL Layers, OOPC] WebGL layer init. (Out Of Process Compositing)
#ifdef MOZ_WIDGET_GONK
            factory = new SurfaceFactory_Gralloc(mGLContext, screen->Caps(), ClientManager()->AsShadowForwarder());
#else
            // we could do readback here maybe
            NS_NOTREACHED("isCrossProcess but not on native B2G!");
#endif
          }
        } else {
          // [Basic Layers, OMTC] WebGL layer init.
          // Well, this *should* work...
#ifdef XP_MACOSX
          factory = new SurfaceFactory_IOSurface(mGLContext, screen->Caps());
#else
          factory = new SurfaceFactory_GLTexture(mGLContext, nullptr, screen->Caps());
#endif
        }
      }
    }

    if (factory) {
      screen->Morph(factory, streamType);
    }
  }
}
void
ClientCanvasLayer::RenderLayer()
{
    PROFILER_LABEL("ClientCanvasLayer", "Paint");
    if (!IsDirty()) {
        return;
    }

    if (GetMaskLayer()) {
        ToClientLayer(GetMaskLayer())->RenderLayer();
    }

    if (!mCanvasClient) {
        TextureFlags flags = TEXTURE_IMMEDIATE_UPLOAD;
        if (mNeedsYFlip) {
            flags |= TEXTURE_NEEDS_Y_FLIP;
        }

        bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
        //Append TEXTURE_DEALLOCATE_CLIENT flag for streaming buffer under OOPC case
        if (isCrossProcess && mGLContext) {
            GLScreenBuffer* screen = mGLContext->Screen();
            if (screen && screen->Stream()) {
                flags |= TEXTURE_DEALLOCATE_CLIENT;
            }
        }
        mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(),
                        ClientManager(), flags);
        if (!mCanvasClient) {
            return;
        }
        if (HasShadow()) {
            mCanvasClient->Connect();
            ClientManager()->Attach(mCanvasClient, this);
        }
    }

    FirePreTransactionCallback();
    mCanvasClient->Update(gfx::IntSize(mBounds.width, mBounds.height), this);

    FireDidTransactionCallback();

    ClientManager()->Hold(this);
    mCanvasClient->Updated();
    mCanvasClient->OnTransaction();
}
Пример #9
0
bool
ClientTiledPaintedLayer::UseProgressiveDraw() {
  if (!gfxPlatform::GetPlatform()->UseProgressivePaint()) {
    // pref is disabled, so never do progressive
    return false;
  }

  if (!mContentClient->GetTiledBuffer()->SupportsProgressiveUpdate()) {
    return false;
  }

  if (ClientManager()->HasShadowTarget()) {
    // This condition is true when we are in a reftest scenario. We don't want
    // to draw progressively here because it can cause intermittent reftest
    // failures because the harness won't wait for all the tiles to be drawn.
    return false;
  }

  if (mPaintData.mCriticalDisplayPort.IsEmpty()) {
    // This catches three scenarios:
    // 1) This layer doesn't have a scrolling ancestor
    // 2) This layer is subject to OMTA transforms
    // 3) Low-precision painting is disabled
    // In all of these cases, we don't want to draw this layer progressively.
    return false;
  }

  if (GetIsFixedPosition() || GetParent()->GetIsFixedPosition()) {
    // This layer is fixed-position and so even if it does have a scrolling
    // ancestor it will likely be entirely on-screen all the time, so we
    // should draw it all at once
    return false;
  }

  if (ClientManager()->AsyncPanZoomEnabled()) {
    LayerMetricsWrapper scrollAncestor;
    GetAncestorLayers(&scrollAncestor, nullptr, nullptr);
    MOZ_ASSERT(scrollAncestor); // because mPaintData.mCriticalDisplayPort is non-empty
    const FrameMetrics& parentMetrics = scrollAncestor.Metrics();
    if (!IsScrollingOnCompositor(parentMetrics)) {
      return false;
    }
  }

  return true;
}
void
SimpleClientTiledThebesLayer::RenderLayer()
{
  LayerManager::DrawThebesLayerCallback callback =
    ClientManager()->GetThebesLayerCallback();
  void *data = ClientManager()->GetThebesLayerCallbackData();
  if (!callback) {
    ClientManager()->SetTransactionIncomplete();
    return;
  }

  // First time? Create a content client.
  if (!mContentClient) {
    mContentClient = new SimpleTiledContentClient(this, ClientManager());

    mContentClient->Connect();
    ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
    MOZ_ASSERT(mContentClient->GetForwarder());
  }

  // If the format changed, nothing is valid
  if (mContentClient->mTiledBuffer.HasFormatChanged()) {
    mValidRegion = nsIntRegion();
  }

  nsIntRegion invalidRegion = mVisibleRegion;
  invalidRegion.Sub(invalidRegion, mValidRegion);
  if (invalidRegion.IsEmpty()) {
    return;
  }

  // Only paint the mask layer on the first transaction.
  if (GetMaskLayer() && !ClientManager()->IsRepeatTransaction()) {
    ToClientLayer(GetMaskLayer())->RenderLayer();
  }

  // SimpleTiledContentClient doesn't support progressive updates or the low
  // precision buffer yet.
  MOZ_ASSERT(!gfxPrefs::UseProgressiveTilePainting() &&
             !gfxPrefs::UseLowPrecisionBuffer());

  mValidRegion = mVisibleRegion;

  NS_ASSERTION(!ClientManager()->IsRepeatTransaction(), "Didn't paint our mask layer");

  mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
                                           callback, data);

  ClientManager()->Hold(this);

  mContentClient->UseTiledLayerBuffer();
}
Пример #11
0
void
ClientThebesLayer::PaintBuffer(gfxContext* aContext,
                               const nsIntRegion& aRegionToDraw,
                               const nsIntRegion& aExtendedRegionToDraw,
                               const nsIntRegion& aRegionToInvalidate,
                               bool aDidSelfCopy, DrawRegionClip aClip)
{
  ContentClientRemote* contentClientRemote = static_cast<ContentClientRemote*>(mContentClient.get());
  MOZ_ASSERT(contentClientRemote->GetIPDLActor());

  // NB: this just throws away the entire valid region if there are
  // too many rects.
  mValidRegion.SimplifyInward(8);

  if (!ClientManager()->GetThebesLayerCallback()) {
    ClientManager()->SetTransactionIncomplete();
    return;
  }
  ClientManager()->GetThebesLayerCallback()(this,
                                            aContext,
                                            aExtendedRegionToDraw,
                                            aClip,
                                            aRegionToInvalidate,
                                            ClientManager()->GetThebesLayerCallbackData());

  // Everything that's visible has been validated. Do this instead of just
  // OR-ing with aRegionToDraw, since that can lead to a very complex region
  // here (OR doesn't automatically simplify to the simplest possible
  // representation of a region.)
  nsIntRegion tmp;
  tmp.Or(mVisibleRegion, aExtendedRegionToDraw);
  mValidRegion.Or(mValidRegion, tmp);

  // Hold(this) ensures this layer is kept alive through the current transaction
  // The ContentClient assumes this layer is kept alive (e.g., in CreateBuffer,
  // DestroyThebesBuffer), so deleting this Hold for whatever reason will break things.
  ClientManager()->Hold(this);
  contentClientRemote->Updated(aRegionToDraw,
                               mVisibleRegion,
                               aDidSelfCopy);
}
Пример #12
0
void
ClientThebesLayer::RenderLayer()
{
  if (GetMaskLayer()) {
    ToClientLayer(GetMaskLayer())->RenderLayer();
  }
  
  if (!mContentClient) {
    mContentClient = ContentClient::CreateContentClient(ClientManager());
    if (!mContentClient) {
      return;
    }
    mContentClient->Connect();
    ClientManager()->Attach(mContentClient, this);
    MOZ_ASSERT(mContentClient->GetForwarder());
  }

  mContentClient->BeginPaint();
  PaintThebes();
  mContentClient->EndPaint();
}
Пример #13
0
uint32_t
ClientPaintedLayer::GetPaintFlags()
{
  uint32_t flags = RotatedContentBuffer::PAINT_CAN_DRAW_ROTATED;
  #ifndef MOZ_IGNORE_PAINT_WILL_RESAMPLE
   if (ClientManager()->CompositorMightResample()) {
     flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE;
   }
   if (!(flags & RotatedContentBuffer::PAINT_WILL_RESAMPLE)) {
     if (MayResample()) {
       flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE;
     }
   }
  #endif
  return flags;
}
bool
ClientTiledPaintedLayer::RenderHighPrecision(nsIntRegion& aInvalidRegion,
                                            const nsIntRegion& aVisibleRegion,
                                            LayerManager::DrawPaintedLayerCallback aCallback,
                                            void* aCallbackData)
{
  // If we have no high-precision stuff to draw, or we have started drawing low-precision
  // already, then we shouldn't do anything there.
  if (aInvalidRegion.IsEmpty() || mPaintData.mLowPrecisionPaintCount != 0) {
    return false;
  }

  // Only draw progressively when the resolution is unchanged, and we're not
  // in a reftest scenario (that's what the HasShadowManager() check is for).
  if (gfxPlatform::GetPlatform()->UseProgressivePaint() &&
      !ClientManager()->HasShadowTarget() &&
      mContentClient->mTiledBuffer.GetFrameResolution() == mPaintData.mResolution) {
    // Store the old valid region, then clear it before painting.
    // We clip the old valid region to the visible region, as it only gets
    // used to decide stale content (currently valid and previously visible)
    nsIntRegion oldValidRegion = mContentClient->mTiledBuffer.GetValidRegion();
    oldValidRegion.And(oldValidRegion, aVisibleRegion);
    if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
      oldValidRegion.And(oldValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
    }

    TILING_LOG("TILING %p: Progressive update with old valid region %s\n", this, Stringify(oldValidRegion).c_str());

    return mContentClient->mTiledBuffer.ProgressiveUpdate(mValidRegion, aInvalidRegion,
                      oldValidRegion, &mPaintData, aCallback, aCallbackData);
  }

  // Otherwise do a non-progressive paint

  mValidRegion = aVisibleRegion;
  if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
    mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
  }

  TILING_LOG("TILING %p: Non-progressive paint invalid region %s\n", this, Stringify(aInvalidRegion).c_str());
  TILING_LOG("TILING %p: Non-progressive paint new valid region %s\n", this, Stringify(mValidRegion).c_str());

  mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution);
  mContentClient->mTiledBuffer.PaintThebes(mValidRegion, aInvalidRegion, aCallback, aCallbackData);
  return true;
}
Пример #15
0
void
ClientCanvasLayer::Initialize(const Data& aData)
{
    CopyableCanvasLayer::Initialize(aData);

    mCanvasClient = nullptr;

    if (!mGLContext)
        return;

    GLScreenBuffer* screen = mGLContext->Screen();

    SurfaceCaps caps;
    if (mGLFrontbuffer) {
        // The screen caps are irrelevant if we're using a separate frontbuffer.
        caps = mGLFrontbuffer->mHasAlpha ? SurfaceCaps::ForRGBA()
               : SurfaceCaps::ForRGB();
    } else {
        MOZ_ASSERT(screen);
        caps = screen->mCaps;
    }
    MOZ_ASSERT(caps.alpha == aData.mHasAlpha);

    auto forwarder = ClientManager()->AsShadowForwarder();

    mFlags = TextureFlags::ORIGIN_BOTTOM_LEFT;
    if (!aData.mIsGLAlphaPremult) {
        mFlags |= TextureFlags::NON_PREMULTIPLIED;
    }

    UniquePtr<SurfaceFactory> factory = GLScreenBuffer::CreateFactory(mGLContext, caps, forwarder, mFlags);

    if (mGLFrontbuffer) {
        // We're using a source other than the one in the default screen.
        // (SkiaGL)
        mFactory = Move(factory);
        if (!mFactory) {
            // Absolutely must have a factory here, so create a basic one
            mFactory = MakeUnique<SurfaceFactory_Basic>(mGLContext, caps, mFlags);
        }
    } else {
        if (factory)
            screen->Morph(Move(factory));
    }
}
Пример #16
0
void
ClientCanvasLayer::Initialize(const Data& aData)
{
  CopyableCanvasLayer::Initialize(aData);

  mCanvasClient = nullptr;

  if (mGLContext) {
    GLScreenBuffer* screen = mGLContext->Screen();

    SurfaceCaps caps = screen->Caps();
    if (mStream) {
      // The screen caps are irrelevant if we're using a separate stream
      caps = GetContentFlags() & CONTENT_OPAQUE ? SurfaceCaps::ForRGB() : SurfaceCaps::ForRGBA();
    }

    SurfaceStreamType streamType =
        SurfaceStream::ChooseGLStreamType(SurfaceStream::OffMainThread,
                                          screen->PreserveBuffer());
    SurfaceFactory_GL* factory = nullptr;
    if (!gfxPrefs::WebGLForceLayersReadback()) {
      if (ClientManager()->AsShadowForwarder()->GetCompositorBackendType() == mozilla::layers::LayersBackend::LAYERS_OPENGL) {
        if (mGLContext->GetContextType() == GLContextType::EGL) {
          bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);

          if (!isCrossProcess) {
            // [Basic/OGL Layers, OMTC] WebGL layer init.
            factory = SurfaceFactory_EGLImage::Create(mGLContext, caps);
          } else {
            // [Basic/OGL Layers, OOPC] WebGL layer init. (Out Of Process Compositing)
#ifdef MOZ_WIDGET_GONK
            factory = new SurfaceFactory_Gralloc(mGLContext, caps, ClientManager()->AsShadowForwarder());
#else
            // we could do readback here maybe
            NS_NOTREACHED("isCrossProcess but not on native B2G!");
#endif
          }
        } else {
          // [Basic Layers, OMTC] WebGL layer init.
          // Well, this *should* work...
#ifdef XP_MACOSX
          factory = new SurfaceFactory_IOSurface(mGLContext, caps);
#else
          factory = new SurfaceFactory_GLTexture(mGLContext, nullptr, caps);
#endif
        }
      }
    }

    if (mStream) {
      // We're using a stream other than the one in the default screen
      mFactory = factory;
      if (!mFactory) {
        // Absolutely must have a factory here, so create a basic one
        mFactory = new SurfaceFactory_Basic(mGLContext, caps);
      }

      gfx::IntSize size = gfx::IntSize(aData.mSize.width, aData.mSize.height);
      mTextureSurface = SharedSurface_GLTexture::Create(mGLContext, mGLContext,
                                                        mGLContext->GetGLFormats(),
                                                        size, caps.alpha, aData.mTexID);
      SharedSurface* producer = mStream->SwapProducer(mFactory, size);
      if (!producer) {
        // Fallback to basic factory
        delete mFactory;
        mFactory = new SurfaceFactory_Basic(mGLContext, caps);
        producer = mStream->SwapProducer(mFactory, size);
        MOZ_ASSERT(producer, "Failed to create initial canvas surface with basic factory");
      }
    } else if (factory) {
      screen->Morph(factory, streamType);
    }
  }
}
Пример #17
0
void
ClientThebesLayer::PaintThebes()
{
    PROFILER_LABEL("ClientThebesLayer", "PaintThebes");
    NS_ASSERTION(ClientManager()->InDrawing(),
                 "Can only draw in drawing phase");

    uint32_t flags = RotatedContentBuffer::PAINT_CAN_DRAW_ROTATED;
#ifndef MOZ_WIDGET_ANDROID
    if (ClientManager()->CompositorMightResample()) {
        flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE;
    }
    if (!(flags & RotatedContentBuffer::PAINT_WILL_RESAMPLE)) {
        if (MayResample()) {
            flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE;
        }
    }
#endif
    PaintState state =
        mContentClient->BeginPaintBuffer(this, flags);
    mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);

    if (!state.mRegionToDraw.IsEmpty() && !ClientManager()->GetThebesLayerCallback()) {
        ClientManager()->SetTransactionIncomplete();
        return;
    }

    // The area that became invalid and is visible needs to be repainted
    // (this could be the whole visible area if our buffer switched
    // from RGB to RGBA, because we might need to repaint with
    // subpixel AA)
    state.mRegionToInvalidate.And(state.mRegionToInvalidate,
                                  GetEffectiveVisibleRegion());

    bool didUpdate = false;
    RotatedContentBuffer::DrawIterator iter;
    while (DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state, &iter)) {
        SetAntialiasingFlags(this, target);

        nsRefPtr<gfxContext> ctx = gfxContext::ContextForDrawTarget(target);

        ClientManager()->GetThebesLayerCallback()(this,
                ctx,
                iter.mDrawRegion,
                state.mClip,
                state.mRegionToInvalidate,
                ClientManager()->GetThebesLayerCallbackData());

        ctx = nullptr;
        mContentClient->ReturnDrawTargetToBuffer(target);
        didUpdate = true;
    }

    if (didUpdate) {
        Mutated();

        mValidRegion.Or(mValidRegion, state.mRegionToDraw);

        ContentClientRemote* contentClientRemote = static_cast<ContentClientRemote*>(mContentClient.get());
        MOZ_ASSERT(contentClientRemote->GetIPDLActor());

        // Hold(this) ensures this layer is kept alive through the current transaction
        // The ContentClient assumes this layer is kept alive (e.g., in CreateBuffer),
        // so deleting this Hold for whatever reason will break things.
        ClientManager()->Hold(this);
        contentClientRemote->Updated(state.mRegionToDraw,
                                     mVisibleRegion,
                                     state.mDidSelfCopy);
    }
}
Пример #18
0
/***
 * If we can, let's paint this ClientPaintedLayer's contents off the main thread.
 * The essential idea is that we ask the ContentClient for a DrawTarget and record
 * the moz2d commands. On the Paint Thread, we replay those commands to the
 * destination draw target. There are a couple of lifetime issues here though:
 *
 * 1) TextureClient owns the underlying buffer and DrawTarget. Because of this
 *    we have to keep the TextureClient and DrawTarget alive but trick the
 *    TextureClient into thinking it's already returned the DrawTarget
 *    since we iterate through different Rects to get DrawTargets*. If
 *    the TextureClient goes away, the DrawTarget and thus buffer can too.
 * 2) When ContentClient::EndPaint happens, it flushes the DrawTarget. We have
 *    to Reflush on the Paint Thread
 * 3) DrawTarget API is NOT thread safe. We get around this by recording
 *    on the main thread and painting on the paint thread. Logically,
 *    ClientLayerManager will force a flushed paint and block the main thread
 *    if we have another transaction. Thus we have a gap between when the main
 *    thread records, the paint thread paints, and we block the main thread
 *    from trying to paint again. The underlying API however is NOT thread safe.
 *  4) We have both "sync" and "async" OMTP. Sync OMTP means we paint on the main thread
 *     but block the main thread while the paint thread paints. Async OMTP doesn't block
 *     the main thread. Sync OMTP is only meant to be used as a debugging tool.
 */
bool
ClientPaintedLayer::PaintOffMainThread()
{
  mContentClient->BeginAsyncPaint();

  uint32_t flags = GetPaintFlags();

  PaintState state = mContentClient->BeginPaintBuffer(this, flags);
  if (!UpdatePaintRegion(state)) {
    return false;
  }

  bool didUpdate = false;
  RotatedContentBuffer::DrawIterator iter;

  // Debug Protip: Change to BorrowDrawTargetForPainting if using sync OMTP.
  while (RefPtr<CapturedPaintState> captureState =
          mContentClient->BorrowDrawTargetForRecording(state, &iter))
  {
    DrawTarget* target = captureState->mTarget;
    if (!target || !target->IsValid()) {
      if (target) {
        mContentClient->ReturnDrawTargetToBuffer(target);
      }
      continue;
    }

    RefPtr<DrawTargetCapture> captureDT =
      Factory::CreateCaptureDrawTarget(target->GetBackendType(),
                                       target->GetSize(),
                                       target->GetFormat());

    captureDT->SetTransform(captureState->mTargetTransform);
    SetAntialiasingFlags(this, captureDT);

    RefPtr<gfxContext> ctx = gfxContext::CreatePreservingTransformOrNull(captureDT);
    MOZ_ASSERT(ctx); // already checked the target above

    ClientManager()->GetPaintedLayerCallback()(this,
                                              ctx,
                                              iter.mDrawRegion,
                                              iter.mDrawRegion,
                                              state.mClip,
                                              state.mRegionToInvalidate,
                                              ClientManager()->GetPaintedLayerCallbackData());

    ctx = nullptr;

    captureState->mCapture = captureDT.forget();
    PaintThread::Get()->PaintContents(captureState,
                                      RotatedContentBuffer::PrepareDrawTargetForPainting);

    mContentClient->ReturnDrawTargetToBuffer(target);

    didUpdate = true;
  }
  mContentClient->EndPaint(nullptr);

  if (didUpdate) {
    UpdateContentClient(state);
  }
  return true;
}
Пример #19
0
void
ClientTiledThebesLayer::BeginPaint()
{
  if (ClientManager()->IsRepeatTransaction()) {
    return;
  }

  mPaintData.mLowPrecisionPaintCount = 0;
  mPaintData.mPaintFinished = false;
  mPaintData.mCompositionBounds.SetEmpty();
  mPaintData.mCriticalDisplayPort.SetEmpty();

  if (!GetBaseTransform().Is2D()) {
    // Give up if there is a complex CSS transform on the layer. We might
    // eventually support these but for now it's too complicated to handle
    // given that it's a pretty rare scenario.
    return;
  }

  // Get the metrics of the nearest scrollable layer and the nearest layer
  // with a displayport.
  ContainerLayer* scrollAncestor = nullptr;
  ContainerLayer* displayPortAncestor = nullptr;
  for (ContainerLayer* ancestor = GetParent(); ancestor; ancestor = ancestor->GetParent()) {
    const FrameMetrics& metrics = ancestor->GetFrameMetrics();
    if (!scrollAncestor && metrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID) {
      scrollAncestor = ancestor;
    }
    if (!metrics.mDisplayPort.IsEmpty()) {
      displayPortAncestor = ancestor;
      // Any layer that has a displayport must be scrollable, so we can break
      // here.
      break;
    }
  }

  if (!displayPortAncestor || !scrollAncestor) {
    // No displayport or scroll ancestor, so we can't do progressive rendering.
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_B2G)
    // Both Android and b2g are guaranteed to have a displayport set, so this
    // should never happen.
    NS_WARNING("Tiled Thebes layer with no scrollable container ancestor");
#endif
    return;
  }

  TILING_PRLOG(("TILING 0x%p: Found scrollAncestor 0x%p and displayPortAncestor 0x%p\n", this,
    scrollAncestor, displayPortAncestor));

  const FrameMetrics& scrollMetrics = scrollAncestor->GetFrameMetrics();
  const FrameMetrics& displayportMetrics = displayPortAncestor->GetFrameMetrics();

  // Calculate the transform required to convert ParentLayer space of our
  // display port ancestor to the Layer space of this layer.
  gfx3DMatrix transformToDisplayPort =
    GetTransformToAncestorsParentLayer(this, displayPortAncestor);

  mPaintData.mTransformDisplayPortToLayer = transformToDisplayPort.Inverse();

  // Note that below we use GetZoomToParent() in a number of places. Because this
  // code runs on the client side, the mTransformScale field of the FrameMetrics
  // will not have been set. This can result in incorrect values being returned
  // by GetZoomToParent() when we have CSS transforms set on some of these layers.
  // This code should be audited and updated as part of fixing bug 993525.

  // Compute the critical display port that applies to this layer in the
  // LayoutDevice space of this layer.
  ParentLayerRect criticalDisplayPort =
    (displayportMetrics.mCriticalDisplayPort * displayportMetrics.GetZoomToParent())
    + displayportMetrics.mCompositionBounds.TopLeft();
  mPaintData.mCriticalDisplayPort = RoundedOut(
    ApplyParentLayerToLayerTransform(mPaintData.mTransformDisplayPortToLayer, criticalDisplayPort));
  TILING_PRLOG_OBJ(("TILING 0x%p: Critical displayport %s\n", this, tmpstr.get()), mPaintData.mCriticalDisplayPort);

  // Compute the viewport that applies to this layer in the LayoutDevice
  // space of this layer.
  ParentLayerRect viewport =
    (displayportMetrics.mViewport * displayportMetrics.GetZoomToParent())
    + displayportMetrics.mCompositionBounds.TopLeft();
  mPaintData.mViewport = ApplyParentLayerToLayerTransform(
    mPaintData.mTransformDisplayPortToLayer, viewport);
  TILING_PRLOG_OBJ(("TILING 0x%p: Viewport %s\n", this, tmpstr.get()), mPaintData.mViewport);

  // Store the resolution from the displayport ancestor layer. Because this is Gecko-side,
  // before any async transforms have occurred, we can use the zoom for this.
  mPaintData.mResolution = displayportMetrics.GetZoomToParent();
  TILING_PRLOG(("TILING 0x%p: Resolution %f\n", this, mPaintData.mResolution.scale));

  // Store the applicable composition bounds in this layer's Layer units.
  gfx3DMatrix transformToCompBounds =
    GetTransformToAncestorsParentLayer(this, scrollAncestor);
  mPaintData.mCompositionBounds = ApplyParentLayerToLayerTransform(
    transformToCompBounds.Inverse(), ParentLayerRect(scrollMetrics.mCompositionBounds));
  TILING_PRLOG_OBJ(("TILING 0x%p: Composition bounds %s\n", this, tmpstr.get()), mPaintData.mCompositionBounds);

  // Calculate the scroll offset since the last transaction
  mPaintData.mScrollOffset = displayportMetrics.GetScrollOffset() * displayportMetrics.GetZoomToParent();
  TILING_PRLOG_OBJ(("TILING 0x%p: Scroll offset %s\n", this, tmpstr.get()), mPaintData.mScrollOffset);
}
Пример #20
0
void
ClientTiledThebesLayer::RenderLayer()
{
  LayerManager::DrawThebesLayerCallback callback =
    ClientManager()->GetThebesLayerCallback();
  void *data = ClientManager()->GetThebesLayerCallbackData();
  if (!callback) {
    ClientManager()->SetTransactionIncomplete();
    return;
  }

  if (!mContentClient) {
    mContentClient = new TiledContentClient(this, ClientManager());

    mContentClient->Connect();
    ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
    MOZ_ASSERT(mContentClient->GetForwarder());
  }

  if (mContentClient->mTiledBuffer.HasFormatChanged()) {
    mValidRegion = nsIntRegion();
  }

  TILING_PRLOG_OBJ(("TILING 0x%p: Initial visible region %s\n", this, tmpstr.get()), mVisibleRegion);
  TILING_PRLOG_OBJ(("TILING 0x%p: Initial valid region %s\n", this, tmpstr.get()), mValidRegion);

  nsIntRegion invalidRegion = mVisibleRegion;
  invalidRegion.Sub(invalidRegion, mValidRegion);
  if (invalidRegion.IsEmpty()) {
    EndPaint(true);
    return;
  }

  // Only paint the mask layer on the first transaction.
  if (GetMaskLayer() && !ClientManager()->IsRepeatTransaction()) {
    ToClientLayer(GetMaskLayer())->RenderLayer();
  }

  bool isFixed = GetIsFixedPosition() || GetParent()->GetIsFixedPosition();

  // Fast path for no progressive updates, no low-precision updates and no
  // critical display-port set, or no display-port set, or this is a fixed
  // position layer/contained in a fixed position layer
  const FrameMetrics& parentMetrics = GetParent()->GetFrameMetrics();
  if ((!gfxPrefs::UseProgressiveTilePainting() &&
       !gfxPrefs::UseLowPrecisionBuffer() &&
       parentMetrics.mCriticalDisplayPort.IsEmpty()) ||
       parentMetrics.mDisplayPort.IsEmpty() ||
       isFixed) {
    mValidRegion = mVisibleRegion;

    NS_ASSERTION(!ClientManager()->IsRepeatTransaction(), "Didn't paint our mask layer");

    mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
                                             callback, data);

    ClientManager()->Hold(this);
    mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER);

    return;
  }

  // Calculate everything we need to perform the paint.
  BeginPaint();
  if (mPaintData.mPaintFinished) {
    return;
  }

  TILING_PRLOG_OBJ(("TILING 0x%p: Valid region %s\n", this, tmpstr.get()), mValidRegion);
  TILING_PRLOG_OBJ(("TILING 0x%p: Visible region %s\n", this, tmpstr.get()), mVisibleRegion);

  // Make sure that tiles that fall outside of the visible region are
  // discarded on the first update.
  if (!ClientManager()->IsRepeatTransaction()) {
    mValidRegion.And(mValidRegion, mVisibleRegion);
    if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
      // Make sure that tiles that fall outside of the critical displayport are
      // discarded on the first update.
      mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
    }
  }

  nsIntRegion lowPrecisionInvalidRegion;
  if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
    if (gfxPrefs::UseLowPrecisionBuffer()) {
      // Calculate the invalid region for the low precision buffer
      lowPrecisionInvalidRegion.Sub(mVisibleRegion, mLowPrecisionValidRegion);

      // Remove the valid region from the low precision valid region (we don't
      // validate this part of the low precision buffer).
      lowPrecisionInvalidRegion.Sub(lowPrecisionInvalidRegion, mValidRegion);
    }

    // Clip the invalid region to the critical display-port
    invalidRegion.And(invalidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
    if (invalidRegion.IsEmpty() && lowPrecisionInvalidRegion.IsEmpty()) {
      EndPaint(true);
      return;
    }
  }

  TILING_PRLOG_OBJ(("TILING 0x%p: Invalid region %s\n", this, tmpstr.get()), invalidRegion);

  if (!invalidRegion.IsEmpty() && mPaintData.mLowPrecisionPaintCount == 0) {
    bool updatedBuffer = false;
    // Only draw progressively when the resolution is unchanged.
    if (gfxPrefs::UseProgressiveTilePainting() &&
        !ClientManager()->HasShadowTarget() &&
        mContentClient->mTiledBuffer.GetFrameResolution() == mPaintData.mResolution) {
      // Store the old valid region, then clear it before painting.
      // We clip the old valid region to the visible region, as it only gets
      // used to decide stale content (currently valid and previously visible)
      nsIntRegion oldValidRegion = mContentClient->mTiledBuffer.GetValidRegion();
      oldValidRegion.And(oldValidRegion, mVisibleRegion);
      if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
        oldValidRegion.And(oldValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
      }

      TILING_PRLOG_OBJ(("TILING 0x%p: Progressive update with old valid region %s\n", this, tmpstr.get()), oldValidRegion);

      updatedBuffer =
        mContentClient->mTiledBuffer.ProgressiveUpdate(mValidRegion, invalidRegion,
                                                       oldValidRegion, &mPaintData,
                                                       callback, data);
    } else {
      updatedBuffer = true;
      mValidRegion = mVisibleRegion;
      if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
        mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
      }

      TILING_PRLOG_OBJ(("TILING 0x%p: Painting: valid region %s\n", this, tmpstr.get()), mValidRegion);
      TILING_PRLOG_OBJ(("TILING 0x%p: and invalid region %s\n", this, tmpstr.get()), invalidRegion);

      mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution);
      mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
                                               callback, data);
    }

    if (updatedBuffer) {
      ClientManager()->Hold(this);
      mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER);

      // If there are low precision updates, mark the paint as unfinished and
      // request a repeat transaction.
      if (!lowPrecisionInvalidRegion.IsEmpty() && mPaintData.mPaintFinished) {
        ClientManager()->SetRepeatTransaction();
        mPaintData.mLowPrecisionPaintCount = 1;
        mPaintData.mPaintFinished = false;
      }

      // Return so that low precision updates aren't performed in the same
      // transaction as high-precision updates.
      EndPaint(false);
      return;
    }
  }

  TILING_PRLOG_OBJ(("TILING 0x%p: Low-precision valid region is %s\n", this, tmpstr.get()), mLowPrecisionValidRegion);
  TILING_PRLOG_OBJ(("TILING 0x%p: Low-precision invalid region is %s\n", this, tmpstr.get()), lowPrecisionInvalidRegion);

  // Render the low precision buffer, if there's area to invalidate and the
  // visible region is larger than the critical display port.
  bool updatedLowPrecision = false;
  if (!lowPrecisionInvalidRegion.IsEmpty() &&
      !nsIntRegion(LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort)).Contains(mVisibleRegion)) {
    nsIntRegion oldValidRegion =
      mContentClient->mLowPrecisionTiledBuffer.GetValidRegion();
    oldValidRegion.And(oldValidRegion, mVisibleRegion);

    // If the frame resolution or format have changed, invalidate the buffer
    if (mContentClient->mLowPrecisionTiledBuffer.GetFrameResolution() != mPaintData.mResolution ||
        mContentClient->mLowPrecisionTiledBuffer.HasFormatChanged()) {
      if (!mLowPrecisionValidRegion.IsEmpty()) {
        updatedLowPrecision = true;
      }
      oldValidRegion.SetEmpty();
      mLowPrecisionValidRegion.SetEmpty();
      mContentClient->mLowPrecisionTiledBuffer.SetFrameResolution(mPaintData.mResolution);
      lowPrecisionInvalidRegion = mVisibleRegion;
    }

    // Invalidate previously valid content that is no longer visible
    if (mPaintData.mLowPrecisionPaintCount == 1) {
      mLowPrecisionValidRegion.And(mLowPrecisionValidRegion, mVisibleRegion);
    }
    mPaintData.mLowPrecisionPaintCount++;

    // Remove the valid high-precision region from the invalid low-precision
    // region. We don't want to spend time drawing things twice.
    lowPrecisionInvalidRegion.Sub(lowPrecisionInvalidRegion, mValidRegion);

    if (!lowPrecisionInvalidRegion.IsEmpty()) {
      updatedLowPrecision = mContentClient->mLowPrecisionTiledBuffer
                              .ProgressiveUpdate(mLowPrecisionValidRegion,
                                                 lowPrecisionInvalidRegion,
                                                 oldValidRegion, &mPaintData,
                                                 callback, data);
    }
  } else if (!mLowPrecisionValidRegion.IsEmpty()) {
    // Clear the low precision tiled buffer
    updatedLowPrecision = true;
    mLowPrecisionValidRegion.SetEmpty();
    mContentClient->mLowPrecisionTiledBuffer.ResetPaintedAndValidState();
  }

  // We send a Painted callback if we clear the valid region of the low
  // precision buffer, so that the shadow buffer's valid region can be updated
  // and the associated resources can be freed.
  if (updatedLowPrecision) {
    ClientManager()->Hold(this);
    mContentClient->UseTiledLayerBuffer(TiledContentClient::LOW_PRECISION_TILED_BUFFER);
  }

  EndPaint(false);
}
void
ClientTiledPaintedLayer::RenderLayer()
{
  LayerManager::DrawPaintedLayerCallback callback =
    ClientManager()->GetPaintedLayerCallback();
  void *data = ClientManager()->GetPaintedLayerCallbackData();
  if (!callback) {
    ClientManager()->SetTransactionIncomplete();
    return;
  }

  if (!mContentClient) {
    mContentClient = new TiledContentClient(this, ClientManager());

    mContentClient->Connect();
    ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
    MOZ_ASSERT(mContentClient->GetForwarder());
  }

  if (mContentClient->mTiledBuffer.HasFormatChanged()) {
    mValidRegion = nsIntRegion();
    mContentClient->mTiledBuffer.ResetPaintedAndValidState();
  }

  TILING_LOG("TILING %p: Initial visible region %s\n", this, Stringify(mVisibleRegion).c_str());
  TILING_LOG("TILING %p: Initial valid region %s\n", this, Stringify(mValidRegion).c_str());
  TILING_LOG("TILING %p: Initial low-precision valid region %s\n", this, Stringify(mLowPrecisionValidRegion).c_str());

  nsIntRegion neededRegion = mVisibleRegion;
#ifndef MOZ_IGNORE_PAINT_WILL_RESAMPLE
  // This is handled by PadDrawTargetOutFromRegion in TiledContentClient for mobile
  if (MayResample()) {
    // If we're resampling then bilinear filtering can read up to 1 pixel
    // outside of our texture coords. Make the visible region a single rect,
    // and pad it out by 1 pixel (restricted to tile boundaries) so that
    // we always have valid content or transparent pixels to sample from.
    nsIntRect bounds = neededRegion.GetBounds();
    nsIntRect wholeTiles = bounds;
    wholeTiles.Inflate(nsIntSize(
      gfxPlatform::GetPlatform()->GetTileWidth(),
      gfxPlatform::GetPlatform()->GetTileHeight()));
    nsIntRect padded = bounds;
    padded.Inflate(1);
    padded.IntersectRect(padded, wholeTiles);
    neededRegion = padded;
  }
#endif

  nsIntRegion invalidRegion;
  invalidRegion.Sub(neededRegion, mValidRegion);
  if (invalidRegion.IsEmpty()) {
    EndPaint();
    return;
  }

  if (!ClientManager()->IsRepeatTransaction()) {
    // Only paint the mask layer on the first transaction.
    if (GetMaskLayer()) {
      ToClientLayer(GetMaskLayer())->RenderLayer();
    }

    // In some cases we can take a fast path and just be done with it.
    if (UseFastPath()) {
      TILING_LOG("TILING %p: Taking fast-path\n", this);
      mValidRegion = neededRegion;
      mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion, callback, data);
      ClientManager()->Hold(this);
      mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER);
      return;
    }

    // For more complex cases we need to calculate a bunch of metrics before we
    // can do the paint.
    BeginPaint();
    if (mPaintData.mPaintFinished) {
      return;
    }

    // Make sure that tiles that fall outside of the visible region or outside of the
    // critical displayport are discarded on the first update. Also make sure that we
    // only draw stuff inside the critical displayport on the first update.
    mValidRegion.And(mValidRegion, neededRegion);
    if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
      mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
      invalidRegion.And(invalidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
    }

    TILING_LOG("TILING %p: First-transaction valid region %s\n", this, Stringify(mValidRegion).c_str());
    TILING_LOG("TILING %p: First-transaction invalid region %s\n", this, Stringify(invalidRegion).c_str());
  } else {
    if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
      invalidRegion.And(invalidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
    }
    TILING_LOG("TILING %p: Repeat-transaction invalid region %s\n", this, Stringify(invalidRegion).c_str());
  }

  nsIntRegion lowPrecisionInvalidRegion;
  if (gfxPrefs::UseLowPrecisionBuffer()) {
    // Calculate the invalid region for the low precision buffer. Make sure
    // to remove the valid high-precision area so we don't double-paint it.
    lowPrecisionInvalidRegion.Sub(neededRegion, mLowPrecisionValidRegion);
    lowPrecisionInvalidRegion.Sub(lowPrecisionInvalidRegion, mValidRegion);
  }
  TILING_LOG("TILING %p: Low-precision invalid region %s\n", this, Stringify(lowPrecisionInvalidRegion).c_str());

  bool updatedHighPrecision = RenderHighPrecision(invalidRegion,
                                                  neededRegion,
                                                  callback, data);
  if (updatedHighPrecision) {
    ClientManager()->Hold(this);
    mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER);

    if (!mPaintData.mPaintFinished) {
      // There is still more high-res stuff to paint, so we're not
      // done yet. A subsequent transaction will take care of this.
      ClientManager()->SetRepeatTransaction();
      return;
    }
  }

  // If there is nothing to draw in low-precision, then we're done.
  if (lowPrecisionInvalidRegion.IsEmpty()) {
    EndPaint();
    return;
  }

  if (updatedHighPrecision) {
    // If there are low precision updates, but we just did some high-precision
    // updates, then mark the paint as unfinished and request a repeat transaction.
    // This is so that we don't perform low-precision updates in the same transaction
    // as high-precision updates.
    TILING_LOG("TILING %p: Scheduling repeat transaction for low-precision painting\n", this);
    ClientManager()->SetRepeatTransaction();
    mPaintData.mLowPrecisionPaintCount = 1;
    mPaintData.mPaintFinished = false;
    return;
  }

  bool updatedLowPrecision = RenderLowPrecision(lowPrecisionInvalidRegion,
                                                neededRegion,
                                                callback, data);
  if (updatedLowPrecision) {
    ClientManager()->Hold(this);
    mContentClient->UseTiledLayerBuffer(TiledContentClient::LOW_PRECISION_TILED_BUFFER);

    if (!mPaintData.mPaintFinished) {
      // There is still more low-res stuff to paint, so we're not
      // done yet. A subsequent transaction will take care of this.
      ClientManager()->SetRepeatTransaction();
      return;
    }
  }

  // If we get here, we've done all the high- and low-precision
  // paints we wanted to do, so we can finish the paint and chill.
  EndPaint();
}
Пример #22
0
void
ClientCanvasLayer::Initialize(const Data& aData)
{
  CopyableCanvasLayer::Initialize(aData);

  mCanvasClient = nullptr;

  if (!mGLContext)
    return;

  GLScreenBuffer* screen = mGLContext->Screen();

  SurfaceCaps caps;
  if (mGLFrontbuffer) {
    // The screen caps are irrelevant if we're using a separate frontbuffer.
    caps = mGLFrontbuffer->mHasAlpha ? SurfaceCaps::ForRGBA()
                                     : SurfaceCaps::ForRGB();
  } else {
    MOZ_ASSERT(screen);
    caps = screen->mCaps;
  }
  MOZ_ASSERT(caps.alpha == aData.mHasAlpha);

  auto forwarder = ClientManager()->AsShadowForwarder();

  mFlags = TextureFlags::ORIGIN_BOTTOM_LEFT;
  if (!aData.mIsGLAlphaPremult) {
    mFlags |= TextureFlags::NON_PREMULTIPLIED;
  }

  UniquePtr<SurfaceFactory> factory;

  if (!gfxPrefs::WebGLForceLayersReadback()) {
    switch (forwarder->GetCompositorBackendType()) {
      case mozilla::layers::LayersBackend::LAYERS_OPENGL: {
#if defined(XP_MACOSX)
        factory = SurfaceFactory_IOSurface::Create(mGLContext, caps, forwarder, mFlags);
#elif defined(MOZ_WIDGET_GONK)
        factory = MakeUnique<SurfaceFactory_Gralloc>(mGLContext, caps, forwarder, mFlags);
#else
        if (mGLContext->GetContextType() == GLContextType::EGL) {
          bool isCrossProcess = (XRE_GetProcessType() != GeckoProcessType_Default);
          if (!isCrossProcess) {
            factory = SurfaceFactory_EGLImage::Create(mGLContext, caps, forwarder,
                                                      mFlags);
          }
        }
#endif
        break;
      }
      case mozilla::layers::LayersBackend::LAYERS_D3D11: {
#ifdef XP_WIN
        if (mGLContext->IsANGLE() &&
            DoesD3D11TextureSharingWork(gfxWindowsPlatform::GetPlatform()->GetD3D11Device()))
        {
          factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext, caps, forwarder,
                                                            mFlags);
        }
#endif
        break;
      }
      default:
        break;
    }
  }

  if (mGLFrontbuffer) {
    // We're using a source other than the one in the default screen.
    // (SkiaGL)
    mFactory = Move(factory);
    if (!mFactory) {
      // Absolutely must have a factory here, so create a basic one
      mFactory = MakeUnique<SurfaceFactory_Basic>(mGLContext, caps, mFlags);
    }
  } else {
    if (factory)
      screen->Morph(Move(factory));
  }
}
void
ClientTiledThebesLayer::BeginPaint()
{
  if (ClientManager()->IsRepeatTransaction()) {
    return;
  }

  mPaintData.mLowPrecisionPaintCount = 0;
  mPaintData.mPaintFinished = false;

  // Calculate the transform required to convert screen space into layer space
  mPaintData.mTransformScreenToLayer = GetEffectiveTransform();
  // XXX Not sure if this code for intermediate surfaces is correct.
  //     It rarely gets hit though, and shouldn't have terrible consequences
  //     even if it is wrong.
  for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
    if (parent->UseIntermediateSurface()) {
      mPaintData.mTransformScreenToLayer.PreMultiply(parent->GetEffectiveTransform());
    }
  }
  mPaintData.mTransformScreenToLayer.Invert();

  // Compute the critical display port in layer space.
  mPaintData.mLayerCriticalDisplayPort.SetEmpty();
  const gfx::Rect& criticalDisplayPort = GetParent()->GetFrameMetrics().mCriticalDisplayPort;
  if (!criticalDisplayPort.IsEmpty()) {
    gfxRect transformedCriticalDisplayPort =
      mPaintData.mTransformScreenToLayer.TransformBounds(
        gfxRect(criticalDisplayPort.x, criticalDisplayPort.y,
                criticalDisplayPort.width, criticalDisplayPort.height));
    transformedCriticalDisplayPort.RoundOut();
    mPaintData.mLayerCriticalDisplayPort = nsIntRect(transformedCriticalDisplayPort.x,
                                             transformedCriticalDisplayPort.y,
                                             transformedCriticalDisplayPort.width,
                                             transformedCriticalDisplayPort.height);
  }

  // Calculate the frame resolution.
  mPaintData.mResolution.SizeTo(1, 1);
  for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
    const FrameMetrics& metrics = parent->GetFrameMetrics();
    mPaintData.mResolution.width *= metrics.mResolution.width;
    mPaintData.mResolution.height *= metrics.mResolution.height;
  }

  // Calculate the scroll offset since the last transaction, and the
  // composition bounds.
  mPaintData.mCompositionBounds.SetEmpty();
  mPaintData.mScrollOffset.MoveTo(0, 0);
  Layer* primaryScrollable = ClientManager()->GetPrimaryScrollableLayer();
  if (primaryScrollable) {
    const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
    mPaintData.mScrollOffset = metrics.mScrollOffset;
    gfxRect transformedViewport = mPaintData.mTransformScreenToLayer.TransformBounds(
      gfxRect(metrics.mCompositionBounds.x, metrics.mCompositionBounds.y,
              metrics.mCompositionBounds.width, metrics.mCompositionBounds.height));
    transformedViewport.RoundOut();
    mPaintData.mCompositionBounds =
      nsIntRect(transformedViewport.x, transformedViewport.y,
                transformedViewport.width, transformedViewport.height);
  }
}
Пример #24
0
void
ClientCanvasLayer::Initialize(const Data& aData)
{
  CopyableCanvasLayer::Initialize(aData);

  mCanvasClient = nullptr;

  if (!mGLContext)
    return;

  GLScreenBuffer* screen = mGLContext->Screen();

  SurfaceCaps caps;
  if (mGLFrontbuffer) {
    // The screen caps are irrelevant if we're using a separate frontbuffer.
    caps = mGLFrontbuffer->mHasAlpha ? SurfaceCaps::ForRGBA()
                                     : SurfaceCaps::ForRGB();
  } else {
    MOZ_ASSERT(screen);
    caps = screen->mCaps;
  }
  MOZ_ASSERT(caps.alpha == aData.mHasAlpha);

  UniquePtr<SurfaceFactory> factory;

  if (!gfxPrefs::WebGLForceLayersReadback()) {
    switch (ClientManager()->AsShadowForwarder()->GetCompositorBackendType()) {
      case mozilla::layers::LayersBackend::LAYERS_OPENGL: {
        if (mGLContext->GetContextType() == GLContextType::EGL) {
#ifdef MOZ_WIDGET_GONK
          TextureFlags flags = TextureFlags::DEALLOCATE_CLIENT |
                               TextureFlags::ORIGIN_BOTTOM_LEFT;
          if (!aData.mIsGLAlphaPremult) {
            flags |= TextureFlags::NON_PREMULTIPLIED;
          }
          factory = MakeUnique<SurfaceFactory_Gralloc>(mGLContext,
                                                       caps,
                                                       flags,
                                                       ClientManager()->AsShadowForwarder());
#else
          bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
          if (!isCrossProcess) {
            // [Basic/OGL Layers, OMTC] WebGL layer init.
            factory = SurfaceFactory_EGLImage::Create(mGLContext, caps);
          } else {
            // we could do readback here maybe
            NS_NOTREACHED("isCrossProcess but not on native B2G!");
          }
#endif
        } else {
          // [Basic Layers, OMTC] WebGL layer init.
          // Well, this *should* work...
#ifdef XP_MACOSX
          factory = SurfaceFactory_IOSurface::Create(mGLContext, caps);
#else
          GLContext* nullConsGL = nullptr; // Bug 1050044.
          factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, nullConsGL, caps);
#endif
        }
        break;
      }
      case mozilla::layers::LayersBackend::LAYERS_D3D11: {
#ifdef XP_WIN
        if (mGLContext->IsANGLE() && DoesD3D11TextureSharingWork(gfxWindowsPlatform::GetPlatform()->GetD3D11Device())) {
          factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext, caps);
        }
#endif
        break;
      }
      default:
        break;
    }
  }

  if (mGLFrontbuffer) {
    // We're using a source other than the one in the default screen.
    // (SkiaGL)
    mFactory = Move(factory);
    if (!mFactory) {
      // Absolutely must have a factory here, so create a basic one
      mFactory = MakeUnique<SurfaceFactory_Basic>(mGLContext, caps);
    }
  } else {
    if (factory)
      screen->Morph(Move(factory));
  }
}
void
ClientTiledThebesLayer::BeginPaint()
{
  if (ClientManager()->IsRepeatTransaction()) {
    return;
  }

  mPaintData.mLowPrecisionPaintCount = 0;
  mPaintData.mPaintFinished = false;

  // Get the metrics of the nearest scroll container.
  ContainerLayer* scrollParent = nullptr;
  for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
    const FrameMetrics& metrics = parent->GetFrameMetrics();
    if (metrics.mScrollId != FrameMetrics::NULL_SCROLL_ID) {
      scrollParent = parent;
      break;
    }
  }

  if (!scrollParent) {
    // XXX I don't think this can happen, but if it does, warn and set the
    //     composition bounds to empty so that progressive updates are disabled.
    NS_WARNING("Tiled Thebes layer with no scrollable container parent");
    mPaintData.mCompositionBounds.SetEmpty();
    return;
  }

  const FrameMetrics& metrics = scrollParent->GetFrameMetrics();

  // Calculate the transform required to convert screen space into transformed
  // layout device space.
  gfx::Matrix4x4 effectiveTransform = GetEffectiveTransform();
  for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
    if (parent->UseIntermediateSurface()) {
      effectiveTransform = effectiveTransform * parent->GetEffectiveTransform();
    }
  }
  gfx3DMatrix layoutToScreen;
  gfx::To3DMatrix(effectiveTransform, layoutToScreen);
  layoutToScreen.ScalePost(metrics.mCumulativeResolution.scale,
                           metrics.mCumulativeResolution.scale,
                           1.f);

  mPaintData.mTransformScreenToLayout = layoutToScreen.Inverse();

  // Compute the critical display port in layer space.
  mPaintData.mLayoutCriticalDisplayPort.SetEmpty();
  if (!metrics.mCriticalDisplayPort.IsEmpty()) {
    // Convert the display port to screen space first so that we can transform
    // it into layout device space.
    const ScreenRect& criticalDisplayPort = metrics.mCriticalDisplayPort * metrics.mZoom;
    LayoutDeviceRect transformedCriticalDisplayPort =
      ApplyScreenToLayoutTransform(mPaintData.mTransformScreenToLayout, criticalDisplayPort);
    mPaintData.mLayoutCriticalDisplayPort =
      LayoutDeviceIntRect::ToUntyped(RoundedOut(transformedCriticalDisplayPort));
  }

  // Calculate the frame resolution. Because this is Gecko-side, before any
  // async transforms have occurred, we can use mZoom for this.
  mPaintData.mResolution = metrics.mZoom;

  // Calculate the scroll offset since the last transaction, and the
  // composition bounds.
  mPaintData.mCompositionBounds.SetEmpty();
  mPaintData.mScrollOffset.MoveTo(0, 0);
  Layer* primaryScrollable = ClientManager()->GetPrimaryScrollableLayer();
  if (primaryScrollable) {
    const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
    mPaintData.mScrollOffset = metrics.mScrollOffset * metrics.mZoom;
    mPaintData.mCompositionBounds =
      ApplyScreenToLayoutTransform(mPaintData.mTransformScreenToLayout,
                                   ScreenRect(metrics.mCompositionBounds));
  }
}
void
SimpleClientTiledThebesLayer::RenderLayer()
{
  LayerManager::DrawThebesLayerCallback callback =
    ClientManager()->GetThebesLayerCallback();
  void *data = ClientManager()->GetThebesLayerCallbackData();
  if (!callback) {
    ClientManager()->SetTransactionIncomplete();
    return;
  }

  // First time? Create a content client.
  if (!mContentClient) {
    mContentClient = new SimpleTiledContentClient(this, ClientManager());

    mContentClient->Connect();
    ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
    MOZ_ASSERT(mContentClient->GetForwarder());
  }

  // If the format changed, nothing is valid
  if (mContentClient->mTiledBuffer.HasFormatChanged()) {
    mValidRegion = nsIntRegion();
  }

  nsIntRegion invalidRegion = mVisibleRegion;
  invalidRegion.Sub(invalidRegion, mValidRegion);
  if (invalidRegion.IsEmpty()) {
    EndPaint(true);
    return;
  }

  const FrameMetrics& parentMetrics = GetParent()->GetFrameMetrics();

  nsIntRegion wantToPaintRegion = mVisibleRegion;

  // Only paint the mask layer on the first transaction.
  if (GetMaskLayer() && !ClientManager()->IsRepeatTransaction()) {
    ToClientLayer(GetMaskLayer())->RenderLayer();
  }

  // Fast path for no progressive updates, no low-precision updates and no
  // critical display-port set, or no display-port set.
  if (parentMetrics.mCriticalDisplayPort.IsEmpty() ||
      parentMetrics.mDisplayPort.IsEmpty())
  {
    mValidRegion = wantToPaintRegion;

    NS_ASSERTION(!ClientManager()->IsRepeatTransaction(), "Didn't paint our mask layer");

    mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
                                             callback, data);

    ClientManager()->Hold(this);

    mContentClient->UseTiledLayerBuffer();

    return;
  }

  // Calculate everything we need to perform the paint.
  BeginPaint();

  if (mPaintData.mPaintFinished) {
    return;
  }

  // Make sure that tiles that fall outside of the visible region are
  // discarded on the first update.
  if (!ClientManager()->IsRepeatTransaction()) {
    mValidRegion.And(mValidRegion, wantToPaintRegion);
    if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
      // Make sure that tiles that fall outside of the critical displayport are
      // discarded on the first update.
      mValidRegion.And(mValidRegion, mPaintData.mLayoutCriticalDisplayPort);
    }
  }

  nsIntRegion lowPrecisionInvalidRegion;
  if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
    // Clip the invalid region to the critical display-port
    invalidRegion.And(invalidRegion, mPaintData.mLayoutCriticalDisplayPort);
    if (invalidRegion.IsEmpty() && lowPrecisionInvalidRegion.IsEmpty()) {
      EndPaint(true);
      return;
    }
  }

  if (!invalidRegion.IsEmpty()) {
    mValidRegion = wantToPaintRegion;
    if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
      mValidRegion.And(mValidRegion, mPaintData.mLayoutCriticalDisplayPort);
    }
    mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution);
    mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
                                             callback, data);

    ClientManager()->Hold(this);
    mContentClient->UseTiledLayerBuffer();

    EndPaint(false);
    return;
  }

  EndPaint(false);
}
Пример #27
0
void
ClientCanvasLayer::Initialize(const Data& aData)
{
  CopyableCanvasLayer::Initialize(aData);

  mCanvasClient = nullptr;

  if (mGLContext) {
    GLScreenBuffer* screen = mGLContext->Screen();

    SurfaceCaps caps;
    if (mStream) {
      // The screen caps are irrelevant if we're using a separate stream
      caps = aData.mHasAlpha ? SurfaceCaps::ForRGBA() : SurfaceCaps::ForRGB();
    } else {
      caps = screen->mCaps;
    }
    MOZ_ASSERT(caps.alpha == aData.mHasAlpha);

    SurfaceStreamType streamType =
        SurfaceStream::ChooseGLStreamType(SurfaceStream::OffMainThread,
                                          screen->PreserveBuffer());
    UniquePtr<SurfaceFactory> factory;

    if (!gfxPrefs::WebGLForceLayersReadback()) {
      switch (ClientManager()->AsShadowForwarder()->GetCompositorBackendType()) {
        case mozilla::layers::LayersBackend::LAYERS_OPENGL: {
          if (mGLContext->GetContextType() == GLContextType::EGL) {
#ifdef MOZ_WIDGET_GONK
            factory = MakeUnique<SurfaceFactory_Gralloc>(mGLContext,
                                                         caps,
                                                         ClientManager()->AsShadowForwarder());
#else
            bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
            if (!isCrossProcess) {
              // [Basic/OGL Layers, OMTC] WebGL layer init.
              factory = SurfaceFactory_EGLImage::Create(mGLContext, caps);
            } else {
              // we could do readback here maybe
              NS_NOTREACHED("isCrossProcess but not on native B2G!");
            }
#endif
          } else {
            // [Basic Layers, OMTC] WebGL layer init.
            // Well, this *should* work...
#ifdef XP_MACOSX
            factory = SurfaceFactory_IOSurface::Create(mGLContext, caps);
#else
            GLContext* nullConsGL = nullptr; // Bug 1050044.
            factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, nullConsGL, caps);
#endif
          }
          break;
        }
        case mozilla::layers::LayersBackend::LAYERS_D3D10:
        case mozilla::layers::LayersBackend::LAYERS_D3D11: {
#ifdef XP_WIN
          if (mGLContext->IsANGLE()) {
            factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext, caps);
          }
#endif
          break;
        }
        default:
          break;
      }
    }

    if (mStream) {
      // We're using a stream other than the one in the default screen
      mFactory = Move(factory);
      if (!mFactory) {
        // Absolutely must have a factory here, so create a basic one
        mFactory = MakeUnique<SurfaceFactory_Basic>(mGLContext, caps);
      }

      gfx::IntSize size = gfx::IntSize(aData.mSize.width, aData.mSize.height);
      mTextureSurface = SharedSurface_GLTexture::Create(mGLContext, mGLContext,
                                                        mGLContext->GetGLFormats(),
                                                        size, caps.alpha, aData.mTexID);
      SharedSurface* producer = mStream->SwapProducer(mFactory.get(), size);
      if (!producer) {
        // Fallback to basic factory
        mFactory = MakeUnique<SurfaceFactory_Basic>(mGLContext, caps);
        producer = mStream->SwapProducer(mFactory.get(), size);
        MOZ_ASSERT(producer, "Failed to create initial canvas surface with basic factory");
      }
    } else if (factory) {
      screen->Morph(Move(factory), streamType);
    }
  }
}
Пример #28
0
 virtual void SetVisibleRegion(const nsIntRegion& aRegion)
 {
   NS_ASSERTION(ClientManager()->InConstruction(),
                "Can only set properties in construction phase");
   ImageLayer::SetVisibleRegion(aRegion);
 }
Пример #29
0
ServerApp::ServerApp(const sf::Uint16 port, const sf::Uint16 max_players) {
    m_port = port;
    m_ClMan = ClientManager();
    m_ClMan.SetMaxPlayers(max_players);
}