Revert "Bug 1962217 Part 1: Refactor NativeLayerCA into a helper class for surface management. r=mstange"
This reverts commit f7b29d93c7.
This commit is contained in:
committed by
imoraru@mozilla.com
parent
1d90e0e847
commit
fe607528c2
@@ -17,8 +17,6 @@
|
||||
|
||||
#include "mozilla/gfx/MacIOSurface.h"
|
||||
#include "mozilla/layers/NativeLayer.h"
|
||||
#include "mozilla/layers/NativeLayerMacSurfaceHandler.h"
|
||||
#include "mozilla/webrender/RenderMacIOSurfaceTextureHost.h"
|
||||
#include "CFTypeRefPtr.h"
|
||||
#include "nsRegion.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
@@ -44,6 +42,7 @@ namespace layers {
|
||||
#ifdef XP_MACOSX
|
||||
class NativeLayerRootSnapshotterCA;
|
||||
#endif
|
||||
class SurfacePoolHandleCA;
|
||||
|
||||
enum class VideoLowPowerType {
|
||||
// These must be kept synchronized with the telemetry histogram enums.
|
||||
@@ -324,6 +323,16 @@ class NativeLayerCA : public NativeLayer {
|
||||
const gfx::IntRect& aDisplayRect,
|
||||
const gfx::IntRegion& aUpdateRegion, F&& aCopyFn);
|
||||
|
||||
struct SurfaceWithInvalidRegion {
|
||||
CFTypeRefPtr<IOSurfaceRef> mSurface;
|
||||
gfx::IntRegion mInvalidRegion;
|
||||
};
|
||||
|
||||
struct SurfaceWithInvalidRegionAndCheckCount {
|
||||
SurfaceWithInvalidRegion mEntry;
|
||||
uint32_t mCheckCount; // The number of calls to IOSurfaceIsInUse
|
||||
};
|
||||
|
||||
Maybe<SurfaceWithInvalidRegion> GetUnusedSurfaceAndCleanUp(
|
||||
const MutexAutoLock& aProofOfLock);
|
||||
|
||||
|
||||
@@ -2068,8 +2068,8 @@ bool NativeLayerCA::WillUpdateAffectLayers(
|
||||
}
|
||||
|
||||
// Called when mMutex is already being held by the current thread.
|
||||
Maybe<SurfaceWithInvalidRegion> NativeLayerCA::GetUnusedSurfaceAndCleanUp(
|
||||
const MutexAutoLock& aProofOfLock) {
|
||||
Maybe<NativeLayerCA::SurfaceWithInvalidRegion>
|
||||
NativeLayerCA::GetUnusedSurfaceAndCleanUp(const MutexAutoLock& aProofOfLock) {
|
||||
std::vector<SurfaceWithInvalidRegionAndCheckCount> usedSurfaces;
|
||||
Maybe<SurfaceWithInvalidRegion> unusedSurface;
|
||||
|
||||
|
||||
@@ -1,230 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_layers_NativeLayerMacIOSurfaceHandler_h
|
||||
#define mozilla_layers_NativeLayerMacIOSurfaceHandler_h
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/gfx/Types.h"
|
||||
|
||||
#include "GLTypes.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsRegion.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace gl {
|
||||
class GLContext;
|
||||
} // namespace gl
|
||||
|
||||
namespace wr {
|
||||
class RenderTextureHost;
|
||||
class RenderMacIOSurfaceTextureHost;
|
||||
} // namespace wr
|
||||
|
||||
namespace layers {
|
||||
class SurfacePoolHandleCA;
|
||||
|
||||
struct SurfaceWithInvalidRegion {
|
||||
CFTypeRefPtr<IOSurfaceRef> mSurface;
|
||||
gfx::IntRegion mInvalidRegion;
|
||||
};
|
||||
|
||||
struct SurfaceWithInvalidRegionAndCheckCount {
|
||||
SurfaceWithInvalidRegion mEntry;
|
||||
uint32_t mCheckCount; // The number of calls to IOSurfaceIsInUse
|
||||
};
|
||||
|
||||
// A companion to macOS-specific subclasses of NativeLayer, this class
|
||||
// handles the implementation of the surface management calls. The
|
||||
// expectation is that NativeLayerMacIOSurfaceHandler is composed into
|
||||
// these classes, rather than be used as a superclass/.
|
||||
class NativeLayerMacSurfaceHandler {
|
||||
public:
|
||||
NativeLayerMacSurfaceHandler(const gfx::IntSize& aSize,
|
||||
SurfacePoolHandleCA* aSurfacePoolHandle);
|
||||
~NativeLayerMacSurfaceHandler();
|
||||
|
||||
gfx::IntSize Size() { return mSize; }
|
||||
|
||||
// Returns the "display rect", in content coordinates, of the current front
|
||||
// surface. This rect acts as an extra clip and prevents invalid content from
|
||||
// getting to the screen. The display rect starts out empty before the first
|
||||
// call to NextSurface*. Note the different coordinate space from the regular
|
||||
// clip rect: the clip rect is "outside" the layer position, the display rect
|
||||
// is "inside" the layer position (moves with the layer).
|
||||
gfx::IntRect DisplayRect() { return mDisplayRect; }
|
||||
|
||||
void SetSurfaceIsFlipped(bool aIsFlipped) { mSurfaceIsFlipped = aIsFlipped; }
|
||||
bool SurfaceIsFlipped() { return mSurfaceIsFlipped; }
|
||||
|
||||
// Gets the next surface for drawing from our swap chain and stores it in
|
||||
// mInProgressSurface. Returns whether this was successful.
|
||||
// mInProgressSurface is guaranteed to be not in use by the window server.
|
||||
// After a call to NextSurface, NextSurface must not be called again until
|
||||
// after NotifySurfaceReady has been called. Can be called on any thread. When
|
||||
// used from multiple threads, callers need to make sure that they still only
|
||||
// call NextSurface and NotifySurfaceReady alternatingly and not in any other
|
||||
// order.
|
||||
bool NextSurface();
|
||||
|
||||
// Invalidates the specified region in all surfaces that are tracked by this
|
||||
// layer.
|
||||
void InvalidateRegionThroughoutSwapchain(const gfx::IntRegion& aRegion);
|
||||
|
||||
// Invalidate aUpdateRegion and make sure that mInProgressSurface retains any
|
||||
// valid content from the previous surface outside of aUpdateRegion, so that
|
||||
// only aUpdateRegion needs to be drawn. If content needs to be copied,
|
||||
// aCopyFn is called to do the copying.
|
||||
// aCopyFn: Fn(CFTypeRefPtr<IOSurfaceRef> aValidSourceIOSurface,
|
||||
// const gfx::IntRegion& aCopyRegion) -> void
|
||||
template <typename F>
|
||||
void HandlePartialUpdate(const gfx::IntRect& aDisplayRect,
|
||||
const gfx::IntRegion& aUpdateRegion, F&& aCopyFn);
|
||||
|
||||
Maybe<SurfaceWithInvalidRegion> GetUnusedSurfaceAndCleanUp();
|
||||
|
||||
// Returns a DrawTarget. The size of the DrawTarget will be the same as the
|
||||
// size of this layer. The caller should draw to that DrawTarget, then drop
|
||||
// its reference to the DrawTarget, and then call NotifySurfaceReady(). It can
|
||||
// limit its drawing to aUpdateRegion (which is in the DrawTarget's device
|
||||
// space). After a call to NextSurface*, NextSurface* must not be called again
|
||||
// until after NotifySurfaceReady has been called. Can be called on any
|
||||
// thread. When used from multiple threads, callers need to make sure that
|
||||
// they still only call NextSurface* and NotifySurfaceReady alternatingly and
|
||||
// not in any other order. aUpdateRegion and aDisplayRect are in "content
|
||||
// coordinates" and must not extend beyond the layer size. If aDisplayRect
|
||||
// contains parts that were not valid before, then those parts must be updated
|
||||
// (must be part of aUpdateRegion), so that the entirety of aDisplayRect is
|
||||
// valid after the update. The display rect determines the parts of the
|
||||
// surface that will be shown; this allows using surfaces with only
|
||||
// partially-valid content, as long as none of the invalid content is included
|
||||
// in the display rect.
|
||||
RefPtr<gfx::DrawTarget> NextSurfaceAsDrawTarget(
|
||||
const gfx::IntRect& aDisplayRect, const gfx::IntRegion& aUpdateRegion,
|
||||
gfx::BackendType aBackendType);
|
||||
|
||||
// Returns a GLuint for a framebuffer that can be used for drawing to the
|
||||
// surface. The size of the framebuffer will be the same as the size of this
|
||||
// layer. If aNeedsDepth is true, the framebuffer is created with a depth
|
||||
// buffer.
|
||||
// The framebuffer's depth buffer (if present) may be shared with other
|
||||
// framebuffers of the same size, even from entirely different NativeLayer
|
||||
// objects. The caller should not assume anything about the depth buffer's
|
||||
// existing contents (i.e. it should clear it at the beginning of the draw).
|
||||
// Callers should draw to one layer at a time, such that there is no
|
||||
// interleaved drawing to different framebuffers that could be tripped up by
|
||||
// the sharing.
|
||||
// The caller should draw to the framebuffer, unbind it, and then call
|
||||
// NotifySurfaceReady(). It can limit its drawing to aUpdateRegion (which is
|
||||
// in the framebuffer's device space, possibly "upside down" if
|
||||
// SurfaceIsFlipped()).
|
||||
// The framebuffer will be created in the GLContext that this layer's
|
||||
// SurfacePoolHandle was created for.
|
||||
// After a call to NextSurface*, NextSurface* must not be called again until
|
||||
// after NotifySurfaceReady has been called. Can be called on any thread. When
|
||||
// used from multiple threads, callers need to make sure that they still only
|
||||
// call NextSurface and NotifySurfaceReady alternatingly and not in any other
|
||||
// order.
|
||||
// aUpdateRegion and aDisplayRect are in "content coordinates" and must not
|
||||
// extend beyond the layer size. If aDisplayRect contains parts that were not
|
||||
// valid before, then those parts must be updated (must be part of
|
||||
// aUpdateRegion), so that the entirety of aDisplayRect is valid after the
|
||||
// update. The display rect determines the parts of the surface that will be
|
||||
// shown; this allows using surfaces with only partially-valid content, as
|
||||
// long as none of the invalid content is included in the display rect.
|
||||
Maybe<GLuint> NextSurfaceAsFramebuffer(const gfx::IntRect& aDisplayRect,
|
||||
const gfx::IntRegion& aUpdateRegion,
|
||||
bool aNeedsDepth);
|
||||
|
||||
// Indicates that the surface which has been returned from the most recent
|
||||
// call to NextSurface* is now finished being drawn to and can be displayed on
|
||||
// the screen. Resets the invalid region on the surface to the empty region.
|
||||
// Returns true if the display rect has changed.
|
||||
bool NotifySurfaceReady();
|
||||
|
||||
// If you know that this layer will likely not draw any more frames, then it's
|
||||
// good to call DiscardBackbuffers in order to save memory and allow other
|
||||
// layer's to pick up the released surfaces from the pool.
|
||||
void DiscardBackbuffers();
|
||||
|
||||
Maybe<SurfaceWithInvalidRegion> FrontSurface() { return mFrontSurface; }
|
||||
Maybe<SurfaceWithInvalidRegion> InProgressSurface() {
|
||||
return mInProgressSurface;
|
||||
}
|
||||
std::vector<SurfaceWithInvalidRegionAndCheckCount> Surfaces() {
|
||||
return mSurfaces;
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class NativeLayerCA;
|
||||
|
||||
gfx::IntSize mSize;
|
||||
gfx::IntRect mDisplayRect;
|
||||
bool mSurfaceIsFlipped = false;
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
// Track the consistency of our caller's API usage. Layers that are drawn
|
||||
// should only ever be called with NotifySurfaceReady. Layers that are
|
||||
// external should only ever be called with AttachExternalImage.
|
||||
bool mHasEverAttachExternalImage = false;
|
||||
bool mHasEverNotifySurfaceReady = false;
|
||||
#endif
|
||||
|
||||
// Each IOSurface is initially created inside NextSurface.
|
||||
// The surface stays alive until the recycling mechanism in NextSurface
|
||||
// determines it is no longer needed (because the swap chain has grown too
|
||||
// long) or until DiscardBackbuffers() is called or the layer is destroyed.
|
||||
// During the surface's lifetime, it will continuously move through the fields
|
||||
// mInProgressSurface, mFrontSurface, and back to front through the mSurfaces
|
||||
// queue:
|
||||
//
|
||||
// mSurfaces.front()
|
||||
// ------[NextSurface()]-----> mInProgressSurface
|
||||
// --[NotifySurfaceReady()]--> mFrontSurface
|
||||
// --[NotifySurfaceReady()]--> mSurfaces.back() --> .... -->
|
||||
// mSurfaces.front()
|
||||
//
|
||||
// We mark an IOSurface as "in use" as long as it is either in
|
||||
// mInProgressSurface. When it is in mFrontSurface or in the mSurfaces queue,
|
||||
// it is not marked as "in use" by us - but it can be "in use" by the window
|
||||
// server. Consequently, IOSurfaceIsInUse on a surface from mSurfaces reflects
|
||||
// whether the window server is still reading from the surface, and we can use
|
||||
// this indicator to decide when to recycle the surface.
|
||||
//
|
||||
// Users of NativeLayerCA normally proceed in this order:
|
||||
// 1. Begin a frame by calling NextSurface to get the surface.
|
||||
// 2. Draw to the surface.
|
||||
// 3. Mark the surface as done by calling NotifySurfaceReady.
|
||||
// 4. Call NativeLayerRoot::CommitToScreen(), which calls ApplyChanges()
|
||||
// during a CATransaction.
|
||||
|
||||
// The surface we returned from the most recent call to NextSurface, before
|
||||
// the matching call to NotifySurfaceReady.
|
||||
// Will only be Some() between calls to NextSurface and NotifySurfaceReady.
|
||||
Maybe<SurfaceWithInvalidRegion> mInProgressSurface;
|
||||
Maybe<gfx::IntRegion> mInProgressUpdateRegion;
|
||||
Maybe<gfx::IntRect> mInProgressDisplayRect;
|
||||
|
||||
// The surface that the most recent call to NotifySurfaceReady was for.
|
||||
// Will be Some() after the first call to NotifySurfaceReady, for the rest of
|
||||
// the layer's life time.
|
||||
Maybe<SurfaceWithInvalidRegion> mFrontSurface;
|
||||
|
||||
// The queue of surfaces which make up the rest of our "swap chain".
|
||||
// mSurfaces.front() is the next surface we'll attempt to use.
|
||||
// mSurfaces.back() is the one that was used most recently.
|
||||
std::vector<SurfaceWithInvalidRegionAndCheckCount> mSurfaces;
|
||||
|
||||
// Non-null between calls to NextSurfaceAsDrawTarget and NotifySurfaceReady.
|
||||
RefPtr<MacIOSurface> mInProgressLockedIOSurface;
|
||||
|
||||
RefPtr<SurfacePoolHandleCA> mSurfacePoolHandle;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_layers_NativeLayerMacIOSurfaceHandler_h
|
||||
@@ -1,260 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/layers/NativeLayerMacSurfaceHandler.h"
|
||||
#include "mozilla/layers/SurfacePoolCA.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
NativeLayerMacSurfaceHandler::NativeLayerMacSurfaceHandler(
|
||||
const gfx::IntSize& aSize, SurfacePoolHandleCA* aSurfacePoolHandle)
|
||||
: mSize(aSize), mSurfacePoolHandle(aSurfacePoolHandle) {
|
||||
MOZ_RELEASE_ASSERT(mSurfacePoolHandle,
|
||||
"Need a non-null surface pool handle.");
|
||||
}
|
||||
|
||||
NativeLayerMacSurfaceHandler::~NativeLayerMacSurfaceHandler() {
|
||||
if (mInProgressLockedIOSurface) {
|
||||
mInProgressLockedIOSurface->Unlock(false);
|
||||
mInProgressLockedIOSurface = nullptr;
|
||||
}
|
||||
if (mInProgressSurface) {
|
||||
IOSurfaceDecrementUseCount(mInProgressSurface->mSurface.get());
|
||||
mSurfacePoolHandle->ReturnSurfaceToPool(mInProgressSurface->mSurface);
|
||||
}
|
||||
if (mFrontSurface) {
|
||||
mSurfacePoolHandle->ReturnSurfaceToPool(mFrontSurface->mSurface);
|
||||
}
|
||||
for (const auto& surf : mSurfaces) {
|
||||
mSurfacePoolHandle->ReturnSurfaceToPool(surf.mEntry.mSurface);
|
||||
}
|
||||
}
|
||||
|
||||
bool NativeLayerMacSurfaceHandler::NextSurface() {
|
||||
if (mSize.IsEmpty()) {
|
||||
gfxCriticalError()
|
||||
<< "NextSurface returning false because of invalid mSize ("
|
||||
<< mSize.width << ", " << mSize.height << ").";
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(!mInProgressSurface,
|
||||
"ERROR: Do not call NextSurface twice in sequence. Call "
|
||||
"NotifySurfaceReady before the "
|
||||
"next call to NextSurface.");
|
||||
|
||||
Maybe<SurfaceWithInvalidRegion> surf = GetUnusedSurfaceAndCleanUp();
|
||||
if (!surf) {
|
||||
CFTypeRefPtr<IOSurfaceRef> newSurf =
|
||||
mSurfacePoolHandle->ObtainSurfaceFromPool(mSize);
|
||||
MOZ_RELEASE_ASSERT(
|
||||
newSurf, "NextSurface IOSurfaceCreate failed to create the surface.");
|
||||
surf = Some(SurfaceWithInvalidRegion{newSurf, IntRect({}, mSize)});
|
||||
}
|
||||
|
||||
mInProgressSurface = std::move(surf);
|
||||
IOSurfaceIncrementUseCount(mInProgressSurface->mSurface.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
void NativeLayerMacSurfaceHandler::InvalidateRegionThroughoutSwapchain(
|
||||
const IntRegion& aRegion) {
|
||||
IntRegion r = aRegion;
|
||||
if (mInProgressSurface) {
|
||||
mInProgressSurface->mInvalidRegion.OrWith(r);
|
||||
}
|
||||
if (mFrontSurface) {
|
||||
mFrontSurface->mInvalidRegion.OrWith(r);
|
||||
}
|
||||
for (auto& surf : mSurfaces) {
|
||||
surf.mEntry.mInvalidRegion.OrWith(r);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void NativeLayerMacSurfaceHandler::HandlePartialUpdate(
|
||||
const IntRect& aDisplayRect, const IntRegion& aUpdateRegion, F&& aCopyFn) {
|
||||
MOZ_RELEASE_ASSERT(IntRect({}, mSize).Contains(aUpdateRegion.GetBounds()),
|
||||
"The update region should be within the surface bounds.");
|
||||
MOZ_RELEASE_ASSERT(IntRect({}, mSize).Contains(aDisplayRect),
|
||||
"The display rect should be within the surface bounds.");
|
||||
|
||||
MOZ_RELEASE_ASSERT(!mInProgressUpdateRegion);
|
||||
MOZ_RELEASE_ASSERT(!mInProgressDisplayRect);
|
||||
|
||||
mInProgressUpdateRegion = Some(aUpdateRegion);
|
||||
mInProgressDisplayRect = Some(aDisplayRect);
|
||||
|
||||
if (mFrontSurface) {
|
||||
// Copy not-overwritten valid content from mFrontSurface so that valid
|
||||
// content never gets lost.
|
||||
gfx::IntRegion copyRegion;
|
||||
copyRegion.Sub(mInProgressSurface->mInvalidRegion, aUpdateRegion);
|
||||
copyRegion.SubOut(mFrontSurface->mInvalidRegion);
|
||||
|
||||
if (!copyRegion.IsEmpty()) {
|
||||
// Now copy the valid content, using a caller-provided copy function.
|
||||
aCopyFn(mFrontSurface->mSurface, copyRegion);
|
||||
mInProgressSurface->mInvalidRegion.SubOut(copyRegion);
|
||||
}
|
||||
}
|
||||
|
||||
InvalidateRegionThroughoutSwapchain(aUpdateRegion);
|
||||
}
|
||||
|
||||
Maybe<SurfaceWithInvalidRegion>
|
||||
NativeLayerMacSurfaceHandler::GetUnusedSurfaceAndCleanUp() {
|
||||
std::vector<SurfaceWithInvalidRegionAndCheckCount> usedSurfaces;
|
||||
Maybe<SurfaceWithInvalidRegion> unusedSurface;
|
||||
|
||||
// Separate mSurfaces into used and unused surfaces.
|
||||
for (auto& surf : mSurfaces) {
|
||||
if (IOSurfaceIsInUse(surf.mEntry.mSurface.get())) {
|
||||
surf.mCheckCount++;
|
||||
if (surf.mCheckCount < 10) {
|
||||
usedSurfaces.push_back(std::move(surf));
|
||||
} else {
|
||||
// The window server has been holding on to this surface for an
|
||||
// unreasonably long time. This is known to happen sometimes, for
|
||||
// example in occluded windows or after a GPU switch. In that case,
|
||||
// release our references to the surface so that it doesn't look like
|
||||
// we're trying to keep it alive.
|
||||
mSurfacePoolHandle->ReturnSurfaceToPool(
|
||||
std::move(surf.mEntry.mSurface));
|
||||
}
|
||||
} else {
|
||||
if (unusedSurface) {
|
||||
// Multiple surfaces are unused. Keep the most recent one and release
|
||||
// any earlier ones. The most recent one requires the least amount of
|
||||
// copying during partial repaints.
|
||||
mSurfacePoolHandle->ReturnSurfaceToPool(
|
||||
std::move(unusedSurface->mSurface));
|
||||
}
|
||||
unusedSurface = Some(std::move(surf.mEntry));
|
||||
}
|
||||
}
|
||||
|
||||
// Put the used surfaces back into mSurfaces.
|
||||
mSurfaces = std::move(usedSurfaces);
|
||||
|
||||
return unusedSurface;
|
||||
}
|
||||
|
||||
RefPtr<gfx::DrawTarget> NativeLayerMacSurfaceHandler::NextSurfaceAsDrawTarget(
|
||||
const IntRect& aDisplayRect, const IntRegion& aUpdateRegion,
|
||||
gfx::BackendType aBackendType) {
|
||||
if (!NextSurface()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto surf = MakeRefPtr<MacIOSurface>(mInProgressSurface->mSurface);
|
||||
if (NS_WARN_IF(!surf->Lock(false))) {
|
||||
gfxCriticalError() << "NextSurfaceAsDrawTarget lock surface failed.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mInProgressLockedIOSurface = std::move(surf);
|
||||
RefPtr<gfx::DrawTarget> dt =
|
||||
mInProgressLockedIOSurface->GetAsDrawTargetLocked(aBackendType);
|
||||
|
||||
HandlePartialUpdate(
|
||||
aDisplayRect, aUpdateRegion,
|
||||
[&](CFTypeRefPtr<IOSurfaceRef> validSource,
|
||||
const gfx::IntRegion& copyRegion) {
|
||||
RefPtr<MacIOSurface> source = new MacIOSurface(validSource);
|
||||
if (source->Lock(true)) {
|
||||
RefPtr<gfx::DrawTarget> sourceDT =
|
||||
source->GetAsDrawTargetLocked(aBackendType);
|
||||
RefPtr<gfx::SourceSurface> sourceSurface = sourceDT->Snapshot();
|
||||
|
||||
for (auto iter = copyRegion.RectIter(); !iter.Done(); iter.Next()) {
|
||||
const gfx::IntRect& r = iter.Get();
|
||||
dt->CopySurface(sourceSurface, r, r.TopLeft());
|
||||
}
|
||||
source->Unlock(true);
|
||||
} else {
|
||||
gfxCriticalError() << "HandlePartialUpdate lock surface failed.";
|
||||
}
|
||||
});
|
||||
|
||||
return dt;
|
||||
}
|
||||
|
||||
Maybe<GLuint> NativeLayerMacSurfaceHandler::NextSurfaceAsFramebuffer(
|
||||
const IntRect& aDisplayRect, const IntRegion& aUpdateRegion,
|
||||
bool aNeedsDepth) {
|
||||
bool gotNextSurface = NextSurface();
|
||||
MOZ_RELEASE_ASSERT(gotNextSurface,
|
||||
"NextSurfaceAsFramebuffer needs a surface.");
|
||||
|
||||
Maybe<GLuint> fbo = mSurfacePoolHandle->GetFramebufferForSurface(
|
||||
mInProgressSurface->mSurface, aNeedsDepth);
|
||||
MOZ_RELEASE_ASSERT(fbo, "GetFramebufferForSurface failed.");
|
||||
|
||||
HandlePartialUpdate(
|
||||
aDisplayRect, aUpdateRegion,
|
||||
[&](CFTypeRefPtr<IOSurfaceRef> validSource,
|
||||
const gfx::IntRegion& copyRegion) {
|
||||
// Copy copyRegion from validSource to fbo.
|
||||
MOZ_RELEASE_ASSERT(mSurfacePoolHandle->gl());
|
||||
mSurfacePoolHandle->gl()->MakeCurrent();
|
||||
Maybe<GLuint> sourceFBO =
|
||||
mSurfacePoolHandle->GetFramebufferForSurface(validSource, false);
|
||||
MOZ_RELEASE_ASSERT(
|
||||
sourceFBO,
|
||||
"GetFramebufferForSurface failed during HandlePartialUpdate.");
|
||||
for (auto iter = copyRegion.RectIter(); !iter.Done(); iter.Next()) {
|
||||
gfx::IntRect r = iter.Get();
|
||||
if (mSurfaceIsFlipped) {
|
||||
r.y = mSize.height - r.YMost();
|
||||
}
|
||||
mSurfacePoolHandle->gl()->BlitHelper()->BlitFramebufferToFramebuffer(
|
||||
*sourceFBO, *fbo, r, r, LOCAL_GL_NEAREST);
|
||||
}
|
||||
});
|
||||
|
||||
return fbo;
|
||||
}
|
||||
|
||||
bool NativeLayerMacSurfaceHandler::NotifySurfaceReady() {
|
||||
MOZ_RELEASE_ASSERT(
|
||||
mInProgressSurface,
|
||||
"NotifySurfaceReady called without preceding call to NextSurface");
|
||||
|
||||
if (mInProgressLockedIOSurface) {
|
||||
mInProgressLockedIOSurface->Unlock(false);
|
||||
mInProgressLockedIOSurface = nullptr;
|
||||
}
|
||||
|
||||
if (mFrontSurface) {
|
||||
mSurfaces.push_back({*mFrontSurface, 0});
|
||||
mFrontSurface = Nothing();
|
||||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(mInProgressUpdateRegion);
|
||||
IOSurfaceDecrementUseCount(mInProgressSurface->mSurface.get());
|
||||
mFrontSurface = std::move(mInProgressSurface);
|
||||
mFrontSurface->mInvalidRegion.SubOut(mInProgressUpdateRegion.extract());
|
||||
|
||||
bool mutatedDisplayRect = false;
|
||||
MOZ_RELEASE_ASSERT(mInProgressDisplayRect);
|
||||
if (!mDisplayRect.IsEqualInterior(*mInProgressDisplayRect)) {
|
||||
mutatedDisplayRect = true;
|
||||
mDisplayRect = *mInProgressDisplayRect;
|
||||
}
|
||||
mInProgressDisplayRect = Nothing();
|
||||
return mutatedDisplayRect;
|
||||
}
|
||||
|
||||
void NativeLayerMacSurfaceHandler::DiscardBackbuffers() {
|
||||
for (const auto& surf : mSurfaces) {
|
||||
mSurfacePoolHandle->ReturnSurfaceToPool(surf.mEntry.mSurface);
|
||||
}
|
||||
mSurfaces.clear();
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
@@ -268,7 +268,6 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("cocoa", "uikit"):
|
||||
EXPORTS.mozilla.layers += [
|
||||
"GpuFenceMTLSharedEvent.h",
|
||||
"NativeLayerCA.h",
|
||||
"NativeLayerMacSurfaceHandler.h",
|
||||
"SurfacePoolCA.h",
|
||||
]
|
||||
EXPORTS += [
|
||||
@@ -277,7 +276,6 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("cocoa", "uikit"):
|
||||
]
|
||||
UNIFIED_SOURCES += [
|
||||
"NativeLayerCA.mm",
|
||||
"NativeLayerMacSurfaceHandler.mm",
|
||||
"SurfacePoolCA.mm",
|
||||
]
|
||||
SOURCES += [
|
||||
|
||||
Reference in New Issue
Block a user