Bug 1677459 - Split platform independent part to RenderCompositorCompositorSWGL r=mattwoodrow

The change is a preparation of Bug 1673342

Differential Revision: https://phabricator.services.mozilla.com/D99046
This commit is contained in:
sotaro 2021-02-23 08:57:27 +00:00
Родитель 6bd700d7de
Коммит 9d6fd76b93
6 изменённых файлов: 733 добавлений и 492 удалений

Просмотреть файл

@ -13,13 +13,13 @@
#include "mozilla/gfx/Logging.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/layers/SyncObject.h"
#include "mozilla/webrender/RenderCompositorLayersSWGL.h"
#include "mozilla/webrender/RenderCompositorOGL.h"
#include "mozilla/webrender/RenderCompositorSWGL.h"
#include "mozilla/widget/CompositorWidget.h"
#ifdef XP_WIN
# include "mozilla/webrender/RenderCompositorANGLE.h"
# include "mozilla/webrender/RenderCompositorD3D11SWGL.h"
#endif
#if defined(MOZ_WAYLAND) || defined(MOZ_WIDGET_ANDROID)
@ -155,16 +155,12 @@ UniquePtr<RenderCompositor> RenderCompositor::Create(
if (!gfxPlatform::IsHeadless()) {
return RenderCompositorNativeSWGL::Create(std::move(aWidget), aError);
}
#elif defined(XP_WIN)
if (StaticPrefs::gfx_webrender_software_d3d11_AtStartup() &&
gfx::gfxConfig::IsEnabled(gfx::Feature::D3D11_COMPOSITING)) {
UniquePtr<RenderCompositor> comp =
RenderCompositorD3D11SWGL::Create(std::move(aWidget), aError);
if (comp) {
return comp;
}
}
#endif
UniquePtr<RenderCompositor> comp =
RenderCompositorLayersSWGL::Create(std::move(aWidget), aError);
if (comp) {
return comp;
}
return RenderCompositorSWGL::Create(std::move(aWidget), aError);
}

Просмотреть файл

@ -38,6 +38,11 @@ RenderCompositorD3D11SWGL::GetUploadMode() {
UniquePtr<RenderCompositor> RenderCompositorD3D11SWGL::Create(
RefPtr<widget::CompositorWidget>&& aWidget, nsACString& aError) {
if (!StaticPrefs::gfx_webrender_software_d3d11_AtStartup() ||
!gfx::gfxConfig::IsEnabled(gfx::Feature::D3D11_COMPOSITING)) {
return nullptr;
}
void* ctx = wr_swgl_create_context();
if (!ctx) {
gfxCriticalNote << "Failed SWGL context creation for WebRender";
@ -61,164 +66,88 @@ UniquePtr<RenderCompositor> RenderCompositorD3D11SWGL::Create(
RenderCompositorD3D11SWGL::RenderCompositorD3D11SWGL(
CompositorD3D11* aCompositor, RefPtr<widget::CompositorWidget>&& aWidget,
void* aContext)
: RenderCompositor(std::move(aWidget)),
mCompositor(aCompositor),
mContext(aContext) {
MOZ_ASSERT(mContext);
mSyncObject = mCompositor->GetSyncObject();
: RenderCompositorLayersSWGL(aCompositor, std::move(aWidget), aContext) {
mSyncObject = GetCompositorD3D11()->GetSyncObject();
}
RenderCompositorD3D11SWGL::~RenderCompositorD3D11SWGL() {
wr_swgl_destroy_context(mContext);
}
bool RenderCompositorD3D11SWGL::MakeCurrent() {
wr_swgl_make_current(mContext);
return true;
}
RenderCompositorD3D11SWGL::~RenderCompositorD3D11SWGL() {}
bool RenderCompositorD3D11SWGL::BeginFrame() {
MOZ_ASSERT(!mInFrame);
MakeCurrent();
IntRect rect = IntRect(IntPoint(0, 0), GetBufferSize().ToUnknownSize());
if (!mCompositor->BeginFrameForWindow(nsIntRegion(rect), Nothing(), rect,
nsIntRegion())) {
if (!RenderCompositorLayersSWGL::BeginFrame()) {
return false;
}
mInFrame = true;
mUploadMode = GetUploadMode();
return true;
}
void RenderCompositorD3D11SWGL::CancelFrame() {
MOZ_ASSERT(mInFrame);
mCompositor->CancelFrame();
mInFrame = false;
}
void RenderCompositorD3D11SWGL::CompositorEndFrame() {
nsTArray<FrameSurface> frameSurfaces = std::move(mFrameSurfaces);
if (!mInFrame) {
return;
}
for (auto& frameSurface : frameSurfaces) {
auto surfaceCursor = mSurfaces.find(frameSurface.mId);
MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
Surface& surface = surfaceCursor->second;
for (auto it = surface.mTiles.begin(); it != surface.mTiles.end(); ++it) {
if (!it->second.mTexture) {
continue;
}
gfx::Point tileOffset(it->first.mX * surface.mTileSize.width,
it->first.mY * surface.mTileSize.height);
gfx::Rect drawRect = it->second.mValidRect + tileOffset;
RefPtr<TexturedEffect> texturedEffect = CreateTexturedEffect(
surface.mIsOpaque ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8,
it->second.mTexture, frameSurface.mFilter, true);
texturedEffect->mTextureCoords =
gfx::Rect(it->second.mValidRect.x / surface.mTileSize.width,
it->second.mValidRect.y / surface.mTileSize.height,
it->second.mValidRect.width / surface.mTileSize.width,
it->second.mValidRect.height / surface.mTileSize.height);
EffectChain effect;
effect.mPrimaryEffect = texturedEffect;
mCompositor->DrawQuad(drawRect, frameSurface.mClipRect, effect, 1.0,
frameSurface.mTransform, drawRect);
void RenderCompositorD3D11SWGL::HandleExternalImage(
RenderTextureHost* aExternalImage, FrameSurface& aFrameSurface) {
// We need to hold the texture source separately from the effect,
// since the effect doesn't hold a strong reference.
RefPtr<DataTextureSourceD3D11> layer;
RefPtr<TexturedEffect> texturedEffect;
gfx::IntSize size;
if (auto* host = aExternalImage->AsRenderDXGITextureHost()) {
if (!host->EnsureD3D11Texture2D(GetDevice())) {
return;
}
if (surface.mExternalImage) {
// We need to hold the texture source separately from the effect,
// since the effect doesn't hold a strong reference.
RefPtr<DataTextureSourceD3D11> layer;
RefPtr<TexturedEffect> texturedEffect;
gfx::IntSize size;
if (auto* host = surface.mExternalImage->AsRenderDXGITextureHost()) {
if (!host->EnsureD3D11Texture2D(mCompositor->GetDevice())) {
continue;
}
layer = new DataTextureSourceD3D11(mCompositor->GetDevice(),
host->GetFormat(),
host->GetD3D11Texture2D());
if (host->GetFormat() == SurfaceFormat::NV12 ||
host->GetFormat() == SurfaceFormat::P010 ||
host->GetFormat() == SurfaceFormat::P016) {
texturedEffect = new EffectNV12(
layer, host->GetYUVColorSpace(), host->GetColorRange(),
host->GetColorDepth(), frameSurface.mFilter);
} else {
MOZ_ASSERT(host->GetFormat() == SurfaceFormat::B8G8R8X8 ||
host->GetFormat() == SurfaceFormat::B8G8R8A8);
texturedEffect = CreateTexturedEffect(host->GetFormat(), layer,
frameSurface.mFilter, true);
}
size = host->GetSize(0);
host->LockInternal();
} else if (auto* host =
surface.mExternalImage->AsRenderDXGIYCbCrTextureHost()) {
if (!host->EnsureD3D11Texture2D(mCompositor->GetDevice())) {
continue;
}
layer = new DataTextureSourceD3D11(mCompositor->GetDevice(),
SurfaceFormat::A8,
host->GetD3D11Texture2D(0));
RefPtr<DataTextureSourceD3D11> u = new DataTextureSourceD3D11(
mCompositor->GetDevice(), SurfaceFormat::A8,
host->GetD3D11Texture2D(1));
layer->SetNextSibling(u);
RefPtr<DataTextureSourceD3D11> v = new DataTextureSourceD3D11(
mCompositor->GetDevice(), SurfaceFormat::A8,
host->GetD3D11Texture2D(2));
u->SetNextSibling(v);
texturedEffect = new EffectYCbCr(
layer, host->GetYUVColorSpace(), host->GetColorRange(),
host->GetColorDepth(), frameSurface.mFilter);
size = host->GetSize(0);
host->LockInternal();
}
gfx::Rect drawRect(0, 0, size.width, size.height);
EffectChain effect;
effect.mPrimaryEffect = texturedEffect;
mCompositor->DrawQuad(drawRect, frameSurface.mClipRect, effect, 1.0,
frameSurface.mTransform, drawRect);
if (auto* host = surface.mExternalImage->AsRenderDXGITextureHost()) {
host->Unlock();
} else if (auto* host =
surface.mExternalImage->AsRenderDXGIYCbCrTextureHost()) {
host->Unlock();
}
layer = new DataTextureSourceD3D11(GetDevice(), host->GetFormat(),
host->GetD3D11Texture2D());
if (host->GetFormat() == SurfaceFormat::NV12 ||
host->GetFormat() == SurfaceFormat::P010 ||
host->GetFormat() == SurfaceFormat::P016) {
texturedEffect =
new EffectNV12(layer, host->GetYUVColorSpace(), host->GetColorRange(),
host->GetColorDepth(), aFrameSurface.mFilter);
} else {
MOZ_ASSERT(host->GetFormat() == SurfaceFormat::B8G8R8X8 ||
host->GetFormat() == SurfaceFormat::B8G8R8A8);
texturedEffect = CreateTexturedEffect(host->GetFormat(), layer,
aFrameSurface.mFilter, true);
}
size = host->GetSize(0);
host->LockInternal();
} else if (auto* host = aExternalImage->AsRenderDXGIYCbCrTextureHost()) {
if (!host->EnsureD3D11Texture2D(GetDevice())) {
return;
}
}
}
RenderedFrameId RenderCompositorD3D11SWGL::EndFrame(
const nsTArray<DeviceIntRect>& aDirtyRects) {
MOZ_ASSERT(mInFrame);
mInFrame = false;
mCompositor->EndFrame();
return GetNextRenderFrameId();
layer = new DataTextureSourceD3D11(GetDevice(), SurfaceFormat::A8,
host->GetD3D11Texture2D(0));
RefPtr<DataTextureSourceD3D11> u = new DataTextureSourceD3D11(
GetDevice(), SurfaceFormat::A8, host->GetD3D11Texture2D(1));
layer->SetNextSibling(u);
RefPtr<DataTextureSourceD3D11> v = new DataTextureSourceD3D11(
GetDevice(), SurfaceFormat::A8, host->GetD3D11Texture2D(2));
u->SetNextSibling(v);
texturedEffect =
new EffectYCbCr(layer, host->GetYUVColorSpace(), host->GetColorRange(),
host->GetColorDepth(), aFrameSurface.mFilter);
size = host->GetSize(0);
host->LockInternal();
}
gfx::Rect drawRect(0, 0, size.width, size.height);
EffectChain effect;
effect.mPrimaryEffect = texturedEffect;
mCompositor->DrawQuad(drawRect, aFrameSurface.mClipRect, effect, 1.0,
aFrameSurface.mTransform, drawRect);
if (auto* host = aExternalImage->AsRenderDXGITextureHost()) {
host->Unlock();
} else if (auto* host = aExternalImage->AsRenderDXGIYCbCrTextureHost()) {
host->Unlock();
}
}
void RenderCompositorD3D11SWGL::Pause() {}
bool RenderCompositorD3D11SWGL::Resume() { return true; }
LayoutDeviceIntSize RenderCompositorD3D11SWGL::GetBufferSize() {
return mWidget->GetClientSize();
}
GLenum RenderCompositorD3D11SWGL::IsContextLost(bool aForce) {
// CompositorD3D11 uses ID3D11Device for composite. The device status needs to
// be checked.
@ -243,84 +172,79 @@ GLenum RenderCompositorD3D11SWGL::IsContextLost(bool aForce) {
}
}
CompositorCapabilities RenderCompositorD3D11SWGL::GetCompositorCapabilities() {
CompositorCapabilities caps;
caps.virtual_surface_size = 0;
return caps;
UniquePtr<RenderCompositorLayersSWGL::Surface>
RenderCompositorD3D11SWGL::DoCreateSurface(wr::DeviceIntSize aTileSize,
bool aIsOpaque) {
return MakeUnique<SurfaceD3D11SWGL>(aTileSize, aIsOpaque);
}
void RenderCompositorD3D11SWGL::Bind(wr::NativeTileId aId,
wr::DeviceIntPoint* aOffset,
uint32_t* aFboId,
wr::DeviceIntRect aDirtyRect,
wr::DeviceIntRect aValidRect) {
MOZ_RELEASE_ASSERT(false);
}
SurfaceD3D11SWGL::SurfaceD3D11SWGL(wr::DeviceIntSize aTileSize, bool aIsOpaque)
: Surface(aTileSize, aIsOpaque) {}
void RenderCompositorD3D11SWGL::Unbind() { MOZ_RELEASE_ASSERT(false); }
RenderCompositorD3D11SWGL::TileD3D11::TileD3D11(
layers::DataTextureSourceD3D11* aTexture, ID3D11Texture2D* aStagingTexture,
DataSourceSurface* aDataSourceSurface, Surface* aOwner,
RenderCompositorD3D11SWGL* aRenderCompositor)
: Tile(),
mTexture(aTexture),
mStagingTexture(aStagingTexture),
mSurface(aDataSourceSurface),
mOwner(aOwner->AsSurfaceD3D11SWGL()),
mRenderCompositor(aRenderCompositor) {}
bool RenderCompositorD3D11SWGL::MapTile(wr::NativeTileId aId,
wr::DeviceIntRect aDirtyRect,
wr::DeviceIntRect aValidRect,
void** aData, int32_t* aStride) {
auto surfaceCursor = mSurfaces.find(aId.surface_id);
MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
Surface& surface = surfaceCursor->second;
bool RenderCompositorD3D11SWGL::TileD3D11::Map(wr::DeviceIntRect aDirtyRect,
wr::DeviceIntRect aValidRect,
void** aData, int32_t* aStride) {
const UploadMode uploadMode = mRenderCompositor->GetUploadMode();
const gfx::IntSize tileSize = mOwner->TileSize();
auto layerCursor = surface.mTiles.find(TileKey(aId.x, aId.y));
MOZ_RELEASE_ASSERT(layerCursor != surface.mTiles.end());
mCurrentTile = layerCursor->second;
mCurrentTileId = aId;
mCurrentTileDirty = IntRect(aDirtyRect.origin.x, aDirtyRect.origin.y,
aDirtyRect.size.width, aDirtyRect.size.height);
if (!mCurrentTile.mTexture) {
if (!IsValid()) {
return false;
}
// Check if this tile's upload method matches what we're using for this frame,
// and if not then reallocate to fix it. Do this before we copy the struct
// into mCurrentTile.
if (mUploadMode == Upload_Immediate) {
if (mCurrentTile.mStagingTexture) {
MOZ_ASSERT(!mCurrentTile.mSurface);
mCurrentTile.mStagingTexture = nullptr;
mCurrentTile.mSurface = CreateStagingSurface(surface.TileSize());
if (uploadMode == Upload_Immediate) {
if (mStagingTexture) {
MOZ_ASSERT(!mSurface);
mStagingTexture = nullptr;
mSurface = mRenderCompositor->CreateStagingSurface(tileSize);
}
} else {
if (mCurrentTile.mSurface) {
MOZ_ASSERT(!mCurrentTile.mStagingTexture);
mCurrentTile.mSurface = nullptr;
mCurrentTile.mStagingTexture = CreateStagingTexture(surface.TileSize());
if (mSurface) {
MOZ_ASSERT(!mStagingTexture);
mSurface = nullptr;
mStagingTexture = mRenderCompositor->CreateStagingTexture(tileSize);
}
}
if (mUploadMode == Upload_Immediate) {
mRenderCompositor->mCurrentStagingTexture = mStagingTexture;
mRenderCompositor->mCurrentStagingTextureIsTemp = false;
if (uploadMode == Upload_Immediate) {
DataSourceSurface::MappedSurface map;
if (!mCurrentTile.mSurface->Map(DataSourceSurface::READ_WRITE, &map)) {
if (!mSurface->Map(DataSourceSurface::READ_WRITE, &map)) {
return false;
}
*aData =
map.mData + aValidRect.origin.y * map.mStride + aValidRect.origin.x * 4;
*aStride = map.mStride;
layerCursor->second.mValidRect =
gfx::Rect(aValidRect.origin.x, aValidRect.origin.y,
aValidRect.size.width, aValidRect.size.height);
mValidRect = gfx::Rect(aValidRect.origin.x, aValidRect.origin.y,
aValidRect.size.width, aValidRect.size.height);
return true;
}
RefPtr<ID3D11DeviceContext> context;
mCompositor->GetDevice()->GetImmediateContext(getter_AddRefs(context));
mRenderCompositor->GetDevice()->GetImmediateContext(getter_AddRefs(context));
D3D11_MAPPED_SUBRESOURCE mappedSubresource;
bool shouldBlock = mUploadMode == Upload_Staging;
bool shouldBlock = uploadMode == Upload_Staging;
HRESULT hr = context->Map(
mCurrentTile.mStagingTexture, 0, D3D11_MAP_READ_WRITE,
mRenderCompositor->mCurrentStagingTexture, 0, D3D11_MAP_READ_WRITE,
shouldBlock ? 0 : D3D11_MAP_FLAG_DO_NOT_WAIT, &mappedSubresource);
if (hr == DXGI_ERROR_WAS_STILL_DRAWING) {
// mCurrentTile is a copy of the real tile data, so we can just replace the
@ -330,27 +254,31 @@ bool RenderCompositorD3D11SWGL::MapTile(wr::NativeTileId aId,
// having a pool of shared staging textures for all the tiles.
// Mark the tile as having a temporary staging texture.
mCurrentTile.mIsTemp = true;
mRenderCompositor->mCurrentStagingTextureIsTemp = true;
// Try grabbing a texture from the staging pool and see if we can use that.
if (mUploadMode == Upload_StagingPooled && surface.mStagingPool.Length()) {
mCurrentTile.mStagingTexture = surface.mStagingPool.ElementAt(0);
surface.mStagingPool.RemoveElementAt(0);
hr = context->Map(mCurrentTile.mStagingTexture, 0, D3D11_MAP_READ_WRITE,
D3D11_MAP_FLAG_DO_NOT_WAIT, &mappedSubresource);
if (uploadMode == Upload_StagingPooled && mOwner->mStagingPool.Length()) {
mRenderCompositor->mCurrentStagingTexture =
mOwner->mStagingPool.ElementAt(0);
mOwner->mStagingPool.RemoveElementAt(0);
hr = context->Map(mRenderCompositor->mCurrentStagingTexture, 0,
D3D11_MAP_READ_WRITE, D3D11_MAP_FLAG_DO_NOT_WAIT,
&mappedSubresource);
// If that failed, put it back into the pool (but at the end).
if (hr == DXGI_ERROR_WAS_STILL_DRAWING) {
surface.mStagingPool.AppendElement(mCurrentTile.mStagingTexture);
mOwner->mStagingPool.AppendElement(
mRenderCompositor->mCurrentStagingTexture);
}
}
// No staging textures, or we tried one and it was busy. Allocate a brand
// new one instead.
if (hr == DXGI_ERROR_WAS_STILL_DRAWING) {
mCurrentTile.mStagingTexture = CreateStagingTexture(surface.TileSize());
hr = context->Map(mCurrentTile.mStagingTexture, 0, D3D11_MAP_READ_WRITE,
0, &mappedSubresource);
mRenderCompositor->mCurrentStagingTexture =
mRenderCompositor->CreateStagingTexture(tileSize);
hr = context->Map(mRenderCompositor->mCurrentStagingTexture, 0,
D3D11_MAP_READ_WRITE, 0, &mappedSubresource);
}
}
MOZ_ASSERT(SUCCEEDED(hr));
@ -364,83 +292,66 @@ bool RenderCompositorD3D11SWGL::MapTile(wr::NativeTileId aId,
*aStride = mappedSubresource.RowPitch;
// Store the new valid rect, so that we can composite only those pixels
layerCursor->second.mValidRect =
gfx::Rect(aValidRect.origin.x, aValidRect.origin.y, aValidRect.size.width,
aValidRect.size.height);
mValidRect = gfx::Rect(aValidRect.origin.x, aValidRect.origin.y,
aValidRect.size.width, aValidRect.size.height);
return true;
}
void RenderCompositorD3D11SWGL::UnmapTile() {
if (!mCurrentTile.mTexture) {
void RenderCompositorD3D11SWGL::TileD3D11::Unmap(
const gfx::IntRect& aDirtyRect) {
const UploadMode uploadMode = mRenderCompositor->GetUploadMode();
if (!IsValid()) {
return;
}
if (mCurrentTile.mSurface) {
MOZ_ASSERT(mUploadMode == Upload_Immediate);
mCurrentTile.mSurface->Unmap();
nsIntRegion dirty(mCurrentTileDirty);
if (mSurface) {
MOZ_ASSERT(uploadMode == Upload_Immediate);
mSurface->Unmap();
nsIntRegion dirty(aDirtyRect);
// This uses UpdateSubresource, which blocks, so is likely implemented as a
// memcpy into driver owned memory, followed by an async upload. The staging
// method should avoid this extra copy, and is likely to be faster usually.
// We could possible do this call on a background thread so that sw-wr can
// start drawing the next tile while the memcpy is in progress.
mCurrentTile.mTexture->Update(mCurrentTile.mSurface, &dirty);
mTexture->Update(mSurface, &dirty);
return;
}
RefPtr<ID3D11DeviceContext> context;
mCompositor->GetDevice()->GetImmediateContext(getter_AddRefs(context));
mRenderCompositor->GetDevice()->GetImmediateContext(getter_AddRefs(context));
context->Unmap(mCurrentTile.mStagingTexture, 0);
context->Unmap(mRenderCompositor->mCurrentStagingTexture, 0);
D3D11_BOX box;
box.front = 0;
box.back = 1;
box.left = mCurrentTileDirty.X();
box.top = mCurrentTileDirty.Y();
box.right = mCurrentTileDirty.XMost();
box.bottom = mCurrentTileDirty.YMost();
box.left = aDirtyRect.X();
box.top = aDirtyRect.Y();
box.right = aDirtyRect.XMost();
box.bottom = aDirtyRect.YMost();
context->CopySubresourceRegion(mCurrentTile.mTexture->GetD3D11Texture(), 0,
mCurrentTileDirty.x, mCurrentTileDirty.y, 0,
mCurrentTile.mStagingTexture, 0, &box);
context->CopySubresourceRegion(
mTexture->GetD3D11Texture(), 0, aDirtyRect.x, aDirtyRect.y, 0,
mRenderCompositor->mCurrentStagingTexture, 0, &box);
// If we allocated a temp staging texture for this tile, and we're running
// in pooled mode, then consider adding it to the pool for later.
if (mCurrentTile.mIsTemp && mUploadMode == Upload_StagingPooled) {
auto surfaceCursor = mSurfaces.find(mCurrentTileId.surface_id);
MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
Surface& surface = surfaceCursor->second;
if (mRenderCompositor->mCurrentStagingTextureIsTemp &&
uploadMode == Upload_StagingPooled) {
static const uint32_t kMaxPoolSize = 5;
if (surface.mStagingPool.Length() < kMaxPoolSize) {
surface.mStagingPool.AppendElement(mCurrentTile.mStagingTexture);
if (mOwner->mStagingPool.Length() < kMaxPoolSize) {
mOwner->mStagingPool.AppendElement(
mRenderCompositor->mCurrentStagingTexture);
}
}
mCurrentTile.mStagingTexture = nullptr;
mRenderCompositor->mCurrentStagingTexture = nullptr;
mRenderCompositor->mCurrentStagingTextureIsTemp = false;
}
void RenderCompositorD3D11SWGL::CreateSurface(wr::NativeSurfaceId aId,
wr::DeviceIntPoint aVirtualOffset,
wr::DeviceIntSize aTileSize,
bool aIsOpaque) {
MOZ_RELEASE_ASSERT(mSurfaces.find(aId) == mSurfaces.end());
mSurfaces.insert({aId, Surface{aTileSize, aIsOpaque}});
}
void RenderCompositorD3D11SWGL::CreateExternalSurface(wr::NativeSurfaceId aId,
bool aIsOpaque) {
MOZ_RELEASE_ASSERT(mSurfaces.find(aId) == mSurfaces.end());
Surface surface{wr::DeviceIntSize{}, aIsOpaque};
surface.mIsExternal = true;
mSurfaces.insert({aId, std::move(surface)});
}
void RenderCompositorD3D11SWGL::DestroySurface(NativeSurfaceId aId) {
auto surfaceCursor = mSurfaces.find(aId);
MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
mSurfaces.erase(surfaceCursor);
}
bool RenderCompositorD3D11SWGL::TileD3D11::IsValid() { return !!mTexture; }
already_AddRefed<ID3D11Texture2D>
RenderCompositorD3D11SWGL::CreateStagingTexture(const gfx::IntSize aSize) {
@ -452,8 +363,8 @@ RenderCompositorD3D11SWGL::CreateStagingTexture(const gfx::IntSize aSize) {
desc.BindFlags = 0;
RefPtr<ID3D11Texture2D> cpuTexture;
DebugOnly<HRESULT> hr = mCompositor->GetDevice()->CreateTexture2D(
&desc, nullptr, getter_AddRefs(cpuTexture));
DebugOnly<HRESULT> hr =
GetDevice()->CreateTexture2D(&desc, nullptr, getter_AddRefs(cpuTexture));
MOZ_ASSERT(SUCCEEDED(hr));
return cpuTexture.forget();
}
@ -463,103 +374,41 @@ RenderCompositorD3D11SWGL::CreateStagingSurface(const gfx::IntSize aSize) {
return Factory::CreateDataSourceSurface(aSize, SurfaceFormat::B8G8R8A8);
}
void RenderCompositorD3D11SWGL::CreateTile(wr::NativeSurfaceId aId, int32_t aX,
int32_t aY) {
auto surfaceCursor = mSurfaces.find(aId);
MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
Surface& surface = surfaceCursor->second;
MOZ_RELEASE_ASSERT(!surface.mIsExternal);
UniquePtr<RenderCompositorLayersSWGL::Tile>
RenderCompositorD3D11SWGL::DoCreateTile(Surface* aSurface) {
MOZ_RELEASE_ASSERT(aSurface);
const auto tileSize = aSurface->TileSize();
if (mUploadMode == Upload_Immediate) {
RefPtr<DataTextureSourceD3D11> source =
new DataTextureSourceD3D11(gfx::SurfaceFormat::B8G8R8A8, mCompositor,
layers::TextureFlags::NO_FLAGS);
RefPtr<DataSourceSurface> surf = CreateStagingSurface(surface.TileSize());
surface.mTiles.insert({TileKey(aX, aY), Tile{source, nullptr, surf}});
return;
RefPtr<DataSourceSurface> surf = CreateStagingSurface(tileSize);
return MakeUnique<TileD3D11>(source, nullptr, surf, aSurface, this);
}
MOZ_ASSERT(mUploadMode == Upload_Staging ||
mUploadMode == Upload_StagingNoBlock ||
mUploadMode == Upload_StagingPooled);
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
surface.mTileSize.width, surface.mTileSize.height,
1, 1);
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, tileSize.width,
tileSize.height, 1, 1);
RefPtr<ID3D11Texture2D> texture;
DebugOnly<HRESULT> hr = mCompositor->GetDevice()->CreateTexture2D(
&desc, nullptr, getter_AddRefs(texture));
DebugOnly<HRESULT> hr =
GetDevice()->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
MOZ_ASSERT(SUCCEEDED(hr));
if (!texture) {
gfxCriticalNote << "Failed to allocate Texture2D: " << surface.TileSize();
surface.mTiles.insert({TileKey(aX, aY), Tile{nullptr, nullptr, nullptr}});
return;
gfxCriticalNote << "Failed to allocate Texture2D: " << aSurface->TileSize();
MakeUnique<TileD3D11>(nullptr, nullptr, nullptr, aSurface, this);
}
RefPtr<DataTextureSourceD3D11> source = new DataTextureSourceD3D11(
mCompositor->GetDevice(), gfx::SurfaceFormat::B8G8R8A8, texture);
GetDevice(), gfx::SurfaceFormat::B8G8R8A8, texture);
RefPtr<ID3D11Texture2D> cpuTexture = CreateStagingTexture(surface.TileSize());
surface.mTiles.insert({TileKey(aX, aY), Tile{source, cpuTexture, nullptr}});
}
void RenderCompositorD3D11SWGL::DestroyTile(wr::NativeSurfaceId aId, int32_t aX,
int32_t aY) {
auto surfaceCursor = mSurfaces.find(aId);
MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
Surface& surface = surfaceCursor->second;
MOZ_RELEASE_ASSERT(!surface.mIsExternal);
auto layerCursor = surface.mTiles.find(TileKey(aX, aY));
MOZ_RELEASE_ASSERT(layerCursor != surface.mTiles.end());
surface.mTiles.erase(layerCursor);
}
void RenderCompositorD3D11SWGL::AttachExternalImage(
wr::NativeSurfaceId aId, wr::ExternalImageId aExternalImage) {
RenderTextureHost* image =
RenderThread::Get()->GetRenderTexture(aExternalImage);
MOZ_ASSERT(image);
if (!image) {
gfxCriticalNoteOnce
<< "Failed to get RenderTextureHost for D3D11SWGL extId:"
<< AsUint64(aExternalImage);
return;
}
MOZ_RELEASE_ASSERT(image->AsRenderDXGITextureHost() ||
image->AsRenderDXGIYCbCrTextureHost());
auto surfaceCursor = mSurfaces.find(aId);
MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
Surface& surface = surfaceCursor->second;
surface.mExternalImage = image;
MOZ_RELEASE_ASSERT(surface.mTiles.empty());
MOZ_RELEASE_ASSERT(surface.mIsExternal);
}
gfx::SamplingFilter ToSamplingFilter(wr::ImageRendering aImageRendering) {
if (aImageRendering == wr::ImageRendering::Auto) {
return gfx::SamplingFilter::LINEAR;
}
return gfx::SamplingFilter::POINT;
}
void RenderCompositorD3D11SWGL::AddSurface(
wr::NativeSurfaceId aId, const wr::CompositorSurfaceTransform& aTransform,
wr::DeviceIntRect aClipRect, wr::ImageRendering aImageRendering) {
Matrix4x4 transform(
aTransform.m11, aTransform.m12, aTransform.m13, aTransform.m14,
aTransform.m21, aTransform.m22, aTransform.m23, aTransform.m24,
aTransform.m31, aTransform.m32, aTransform.m33, aTransform.m34,
aTransform.m41, aTransform.m42, aTransform.m43, aTransform.m44);
gfx::IntRect clipRect(aClipRect.origin.x, aClipRect.origin.y,
aClipRect.size.width, aClipRect.size.height);
mFrameSurfaces.AppendElement(FrameSurface{aId, transform, clipRect,
ToSamplingFilter(aImageRendering)});
RefPtr<ID3D11Texture2D> cpuTexture = CreateStagingTexture(tileSize);
return MakeUnique<TileD3D11>(source, cpuTexture, nullptr, aSurface, this);
}
bool RenderCompositorD3D11SWGL::MaybeReadback(
@ -576,44 +425,7 @@ bool RenderCompositorD3D11SWGL::MaybeReadback(
return false;
}
mCompositor->Readback(dt);
return true;
}
void RenderCompositorD3D11SWGL::MaybeRequestAllowFrameRecording(
bool aWillRecord) {
mCompositor->RequestAllowFrameRecording(aWillRecord);
}
bool RenderCompositorD3D11SWGL::MaybeRecordFrame(
layers::CompositionRecorder& aRecorder) {
layers::WindowLMC window(mCompositor);
gfx::IntSize size = GetBufferSize().ToUnknownSize();
RefPtr<layers::profiler_screenshots::RenderSource> snapshot =
window.GetWindowContents(size);
if (!snapshot) {
return true;
}
RefPtr<layers::profiler_screenshots::AsyncReadbackBuffer> buffer =
window.CreateAsyncReadbackBuffer(size);
buffer->CopyFrom(snapshot);
RefPtr<layers::RecordedFrame> frame =
new RenderCompositorRecordedFrame(TimeStamp::Now(), std::move(buffer));
aRecorder.RecordFrame(frame);
return false;
}
bool RenderCompositorD3D11SWGL::MaybeGrabScreenshot(
const gfx::IntSize& aWindowSize) {
layers::WindowLMC window(mCompositor);
mProfilerScreenshotGrabber.MaybeGrabScreenshot(window, aWindowSize);
return true;
}
bool RenderCompositorD3D11SWGL::MaybeProcessScreenshotQueue() {
mProfilerScreenshotGrabber.MaybeProcessQueue();
GetCompositorD3D11()->Readback(dt);
return true;
}

Просмотреть файл

@ -10,13 +10,15 @@
#include "mozilla/layers/ScreenshotGrabber.h"
#include "mozilla/layers/TextureD3D11.h"
#include "mozilla/layers/CompositorD3D11.h"
#include "mozilla/webrender/RenderCompositor.h"
#include "mozilla/webrender/RenderCompositorLayersSWGL.h"
namespace mozilla {
namespace wr {
class RenderCompositorD3D11SWGL : public RenderCompositor {
class SurfaceD3D11SWGL;
class RenderCompositorD3D11SWGL : public RenderCompositorLayersSWGL {
public:
static UniquePtr<RenderCompositor> Create(
RefPtr<widget::CompositorWidget>&& aWidget, nsACString& aError);
@ -26,29 +28,11 @@ class RenderCompositorD3D11SWGL : public RenderCompositor {
void* aContext);
virtual ~RenderCompositorD3D11SWGL();
void* swgl() const override { return mContext; }
bool MakeCurrent() override;
bool BeginFrame() override;
void CancelFrame() override;
RenderedFrameId EndFrame(const nsTArray<DeviceIntRect>& aDirtyRects) final;
void Pause() override;
bool Resume() override;
bool SurfaceOriginIsTopLeft() override { return true; }
LayoutDeviceIntSize GetBufferSize() override;
GLenum IsContextLost(bool aForce) override;
// Should we support this?
bool SupportsExternalBufferTextures() const override { return false; }
layers::WebRenderBackend BackendType() const override {
return layers::WebRenderBackend::SOFTWARE;
}
layers::WebRenderCompositor CompositorType() const override {
return layers::WebRenderCompositor::D3D11;
}
@ -56,55 +40,18 @@ class RenderCompositorD3D11SWGL : public RenderCompositor {
return this;
}
// Interface for wr::Compositor
CompositorCapabilities GetCompositorCapabilities() override;
bool ShouldUseNativeCompositor() override { return true; }
void CompositorBeginFrame() override {}
void CompositorEndFrame() override;
void Bind(wr::NativeTileId aId, wr::DeviceIntPoint* aOffset, uint32_t* aFboId,
wr::DeviceIntRect aDirtyRect,
wr::DeviceIntRect aValidRect) override;
void Unbind() override;
bool MapTile(wr::NativeTileId aId, wr::DeviceIntRect aDirtyRect,
wr::DeviceIntRect aValidRect, void** aData,
int32_t* aStride) override;
void UnmapTile() override;
void CreateSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aVirtualOffset,
wr::DeviceIntSize aTileSize, bool aIsOpaque) override;
void CreateExternalSurface(wr::NativeSurfaceId aId, bool aIsOpaque) override;
void DestroySurface(NativeSurfaceId aId) override;
void CreateTile(wr::NativeSurfaceId, int32_t aX, int32_t aY) override;
void DestroyTile(wr::NativeSurfaceId, int32_t aX, int32_t aY) override;
void AttachExternalImage(wr::NativeSurfaceId aId,
wr::ExternalImageId aExternalImage) override;
void AddSurface(wr::NativeSurfaceId aId,
const wr::CompositorSurfaceTransform& aTransform,
wr::DeviceIntRect aClipRect,
wr::ImageRendering aImageRendering) override;
void EnableNativeCompositor(bool aEnable) override {}
void DeInit() override {}
bool BeginFrame() override;
bool MaybeReadback(const gfx::IntSize& aReadbackSize,
const wr::ImageFormat& aReadbackFormat,
const Range<uint8_t>& aReadbackBuffer,
bool* aNeedsYFlip) override;
void MaybeRequestAllowFrameRecording(bool aWillRecord) override;
bool MaybeRecordFrame(layers::CompositionRecorder& aRecorder) override;
bool MaybeGrabScreenshot(const gfx::IntSize& aWindowSize) override;
bool MaybeProcessScreenshotQueue() override;
// TODO: Screenshots etc
layers::CompositorD3D11* GetCompositorD3D11() {
return mCompositor->AsCompositorD3D11();
}
struct TileKey {
TileKey(int32_t aX, int32_t aY) : mX(aX), mY(aY) {}
int32_t mX;
int32_t mY;
};
ID3D11Device* GetDevice() { return mCompositor->GetDevice(); }
ID3D11Device* GetDevice() { return GetCompositorD3D11()->GetDevice(); }
private:
already_AddRefed<ID3D11Texture2D> CreateStagingTexture(
@ -112,52 +59,35 @@ class RenderCompositorD3D11SWGL : public RenderCompositor {
already_AddRefed<DataSourceSurface> CreateStagingSurface(
const gfx::IntSize aSize);
RefPtr<layers::CompositorD3D11> mCompositor;
void* mContext = nullptr;
void HandleExternalImage(RenderTextureHost* aExternalImage,
FrameSurface& aFrameSurface) override;
UniquePtr<RenderCompositorLayersSWGL::Surface> DoCreateSurface(
wr::DeviceIntSize aTileSize, bool aIsOpaque) override;
UniquePtr<RenderCompositorLayersSWGL::Tile> DoCreateTile(
Surface* aSurface) override;
struct Tile {
// Each tile retains a texture, and a DataSourceSurface of the
// same size. We draw into the source surface, and then copy the
// changed area into the texture.
class TileD3D11 : public RenderCompositorLayersSWGL::Tile {
public:
TileD3D11(layers::DataTextureSourceD3D11* aTexture,
ID3D11Texture2D* aStagingTexture,
DataSourceSurface* aDataSourceSurface, Surface* aOwner,
RenderCompositorD3D11SWGL* aRenderCompositor);
virtual ~TileD3D11() {}
bool Map(wr::DeviceIntRect aDirtyRect, wr::DeviceIntRect aValidRect,
void** aData, int32_t* aStride) override;
void Unmap(const gfx::IntRect& aDirtyRect) override;
layers::DataTextureSource* GetTextureSource() override { return mTexture; }
bool IsValid() override;
private:
RefPtr<layers::DataTextureSourceD3D11> mTexture;
RefPtr<ID3D11Texture2D> mStagingTexture;
RefPtr<DataSourceSurface> mSurface;
gfx::Rect mValidRect;
bool mIsTemp = false;
struct KeyHashFn {
std::size_t operator()(const TileKey& aId) const {
return HashGeneric(aId.mX, aId.mY);
}
};
SurfaceD3D11SWGL* mOwner;
RenderCompositorD3D11SWGL* mRenderCompositor;
};
struct Surface {
explicit Surface(wr::DeviceIntSize aTileSize, bool aIsOpaque)
: mTileSize(aTileSize), mIsOpaque(aIsOpaque) {}
gfx::IntSize TileSize() {
return gfx::IntSize(mTileSize.width, mTileSize.height);
}
// External images can change size depending on which image
// is attached, so mTileSize will be 0,0 when mIsExternal
// is true.
wr::DeviceIntSize mTileSize;
bool mIsOpaque;
bool mIsExternal = false;
std::unordered_map<TileKey, Tile, Tile::KeyHashFn> mTiles;
RefPtr<RenderTextureHost> mExternalImage;
nsTArray<RefPtr<ID3D11Texture2D>> mStagingPool;
struct IdHashFn {
std::size_t operator()(const wr::NativeSurfaceId& aId) const {
return HashGeneric(wr::AsUint64(aId));
}
};
};
std::unordered_map<wr::NativeSurfaceId, Surface, Surface::IdHashFn> mSurfaces;
enum UploadMode {
Upload_Immediate,
Upload_Staging,
@ -167,28 +97,19 @@ class RenderCompositorD3D11SWGL : public RenderCompositor {
UploadMode GetUploadMode();
UploadMode mUploadMode = Upload_Staging;
// Temporary state held between MapTile and UnmapTile
Tile mCurrentTile;
gfx::IntRect mCurrentTileDirty;
wr::NativeTileId mCurrentTileId;
// The set of surfaces added to be composited for the current frame
struct FrameSurface {
wr::NativeSurfaceId mId;
gfx::Matrix4x4 mTransform;
gfx::IntRect mClipRect;
gfx::SamplingFilter mFilter;
};
nsTArray<FrameSurface> mFrameSurfaces;
bool mInFrame = false;
layers::ScreenshotGrabber mProfilerScreenshotGrabber;
RefPtr<ID3D11Texture2D> mCurrentStagingTexture;
bool mCurrentStagingTextureIsTemp = false;
};
static inline bool operator==(const RenderCompositorD3D11SWGL::TileKey& a0,
const RenderCompositorD3D11SWGL::TileKey& a1) {
return a0.mX == a1.mX && a0.mY == a1.mY;
}
class SurfaceD3D11SWGL : public RenderCompositorLayersSWGL::Surface {
public:
SurfaceD3D11SWGL(wr::DeviceIntSize aTileSize, bool aIsOpaque);
virtual ~SurfaceD3D11SWGL() {}
SurfaceD3D11SWGL* AsSurfaceD3D11SWGL() override { return this; }
nsTArray<RefPtr<ID3D11Texture2D>> mStagingPool;
};
} // namespace wr
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,321 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "RenderCompositorLayersSWGL.h"
#include "GLContext.h"
#include "GLContextEGL.h"
#include "mozilla/layers/BuildConstants.h"
#include "mozilla/layers/Effects.h"
#include "mozilla/layers/TextureHostOGL.h"
#include "mozilla/widget/CompositorWidget.h"
#include "mozilla/layers/LayerManagerComposite.h"
#include "RenderCompositorRecordedFrame.h"
#if defined(XP_WIN)
# include "mozilla/webrender/RenderCompositorD3D11SWGL.h"
#endif
namespace mozilla {
using namespace layers;
namespace wr {
UniquePtr<RenderCompositor> RenderCompositorLayersSWGL::Create(
RefPtr<widget::CompositorWidget>&& aWidget, nsACString& aError) {
#ifdef XP_WIN
return RenderCompositorD3D11SWGL::Create(std::move(aWidget), aError);
#else
return nullptr;
#endif
}
RenderCompositorLayersSWGL::RenderCompositorLayersSWGL(
Compositor* aCompositor, RefPtr<widget::CompositorWidget>&& aWidget,
void* aContext)
: RenderCompositor(std::move(aWidget)),
mCompositor(aCompositor),
mContext(aContext) {
MOZ_ASSERT(mCompositor);
MOZ_ASSERT(mContext);
}
RenderCompositorLayersSWGL::~RenderCompositorLayersSWGL() {
wr_swgl_destroy_context(mContext);
}
bool RenderCompositorLayersSWGL::MakeCurrent() {
wr_swgl_make_current(mContext);
return true;
}
bool RenderCompositorLayersSWGL::BeginFrame() {
MOZ_ASSERT(!mInFrame);
MakeCurrent();
gfx::IntRect rect =
gfx::IntRect(gfx::IntPoint(0, 0), GetBufferSize().ToUnknownSize());
if (!mCompositor->BeginFrameForWindow(nsIntRegion(rect), Nothing(), rect,
nsIntRegion())) {
return false;
}
mInFrame = true;
return true;
}
void RenderCompositorLayersSWGL::CancelFrame() {
MOZ_ASSERT(mInFrame);
mCompositor->CancelFrame();
mInFrame = false;
}
void RenderCompositorLayersSWGL::CompositorEndFrame() {
nsTArray<FrameSurface> frameSurfaces = std::move(mFrameSurfaces);
if (!mInFrame) {
return;
}
for (auto& frameSurface : frameSurfaces) {
auto surfaceCursor = mSurfaces.find(frameSurface.mId);
MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
Surface* surface = surfaceCursor->second.get();
for (auto it = surface->mTiles.begin(); it != surface->mTiles.end(); ++it) {
if (!it->second->IsValid()) {
continue;
}
gfx::Point tileOffset(it->first.mX * surface->mTileSize.width,
it->first.mY * surface->mTileSize.height);
gfx::Rect drawRect = it->second->mValidRect + tileOffset;
RefPtr<TexturedEffect> texturedEffect = CreateTexturedEffect(
surface->mIsOpaque ? gfx::SurfaceFormat::B8G8R8X8
: gfx::SurfaceFormat::B8G8R8A8,
it->second->GetTextureSource(), frameSurface.mFilter, true);
texturedEffect->mTextureCoords =
gfx::Rect(it->second->mValidRect.x / surface->mTileSize.width,
it->second->mValidRect.y / surface->mTileSize.height,
it->second->mValidRect.width / surface->mTileSize.width,
it->second->mValidRect.height / surface->mTileSize.height);
EffectChain effect;
effect.mPrimaryEffect = texturedEffect;
mCompositor->DrawQuad(drawRect, frameSurface.mClipRect, effect, 1.0,
frameSurface.mTransform, drawRect);
}
if (surface->mExternalImage) {
HandleExternalImage(surface->mExternalImage, frameSurface);
}
}
}
RenderedFrameId RenderCompositorLayersSWGL::EndFrame(
const nsTArray<DeviceIntRect>& aDirtyRects) {
MOZ_ASSERT(mInFrame);
mInFrame = false;
mCompositor->EndFrame();
return GetNextRenderFrameId();
}
LayoutDeviceIntSize RenderCompositorLayersSWGL::GetBufferSize() {
return mWidget->GetClientSize();
}
CompositorCapabilities RenderCompositorLayersSWGL::GetCompositorCapabilities() {
CompositorCapabilities caps;
caps.virtual_surface_size = 0;
return caps;
}
void RenderCompositorLayersSWGL::Bind(wr::NativeTileId aId,
wr::DeviceIntPoint* aOffset,
uint32_t* aFboId,
wr::DeviceIntRect aDirtyRect,
wr::DeviceIntRect aValidRect) {
MOZ_RELEASE_ASSERT(false);
}
void RenderCompositorLayersSWGL::Unbind() { MOZ_RELEASE_ASSERT(false); }
bool RenderCompositorLayersSWGL::MapTile(wr::NativeTileId aId,
wr::DeviceIntRect aDirtyRect,
wr::DeviceIntRect aValidRect,
void** aData, int32_t* aStride) {
auto surfaceCursor = mSurfaces.find(aId.surface_id);
MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
Surface* surface = surfaceCursor->second.get();
auto layerCursor = surface->mTiles.find(TileKey(aId.x, aId.y));
MOZ_RELEASE_ASSERT(layerCursor != surface->mTiles.end());
mCurrentTile = layerCursor->second.get();
mCurrentTileId = aId;
mCurrentTileDirty =
gfx::IntRect(aDirtyRect.origin.x, aDirtyRect.origin.y,
aDirtyRect.size.width, aDirtyRect.size.height);
if (!mCurrentTile->Map(aDirtyRect, aValidRect, aData, aStride)) {
return false;
}
// Store the new valid rect, so that we can composite only those pixels
mCurrentTile->mValidRect =
gfx::Rect(aValidRect.origin.x, aValidRect.origin.y, aValidRect.size.width,
aValidRect.size.height);
return true;
}
void RenderCompositorLayersSWGL::UnmapTile() {
mCurrentTile->Unmap(mCurrentTileDirty);
mCurrentTile = nullptr;
}
void RenderCompositorLayersSWGL::CreateSurface(
wr::NativeSurfaceId aId, wr::DeviceIntPoint aVirtualOffset,
wr::DeviceIntSize aTileSize, bool aIsOpaque) {
MOZ_RELEASE_ASSERT(mSurfaces.find(aId) == mSurfaces.end());
auto surface = DoCreateSurface(aTileSize, aIsOpaque);
mSurfaces.insert({aId, std::move(surface)});
}
UniquePtr<RenderCompositorLayersSWGL::Surface>
RenderCompositorLayersSWGL::DoCreateSurface(wr::DeviceIntSize aTileSize,
bool aIsOpaque) {
return MakeUnique<Surface>(aTileSize, aIsOpaque);
}
void RenderCompositorLayersSWGL::CreateExternalSurface(wr::NativeSurfaceId aId,
bool aIsOpaque) {
MOZ_RELEASE_ASSERT(mSurfaces.find(aId) == mSurfaces.end());
auto surface = MakeUnique<Surface>(wr::DeviceIntSize{}, aIsOpaque);
surface->mIsExternal = true;
mSurfaces.insert({aId, std::move(surface)});
}
void RenderCompositorLayersSWGL::DestroySurface(NativeSurfaceId aId) {
auto surfaceCursor = mSurfaces.find(aId);
MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
mSurfaces.erase(surfaceCursor);
}
void RenderCompositorLayersSWGL::CreateTile(wr::NativeSurfaceId aId, int32_t aX,
int32_t aY) {
auto surfaceCursor = mSurfaces.find(aId);
MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
Surface* surface = surfaceCursor->second.get();
MOZ_RELEASE_ASSERT(!surface->mIsExternal);
auto tile = DoCreateTile(surface);
surface->mTiles.insert({TileKey(aX, aY), std::move(tile)});
}
void RenderCompositorLayersSWGL::DestroyTile(wr::NativeSurfaceId aId,
int32_t aX, int32_t aY) {
auto surfaceCursor = mSurfaces.find(aId);
MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
Surface* surface = surfaceCursor->second.get();
MOZ_RELEASE_ASSERT(!surface->mIsExternal);
auto layerCursor = surface->mTiles.find(TileKey(aX, aY));
MOZ_RELEASE_ASSERT(layerCursor != surface->mTiles.end());
surface->mTiles.erase(layerCursor);
}
void RenderCompositorLayersSWGL::AttachExternalImage(
wr::NativeSurfaceId aId, wr::ExternalImageId aExternalImage) {
RenderTextureHost* image =
RenderThread::Get()->GetRenderTexture(aExternalImage);
MOZ_ASSERT(image);
if (!image) {
gfxCriticalNoteOnce
<< "Failed to get RenderTextureHost for D3D11SWGL extId:"
<< AsUint64(aExternalImage);
return;
}
#if defined(XP_WIN)
MOZ_RELEASE_ASSERT(image->AsRenderDXGITextureHost() ||
image->AsRenderDXGIYCbCrTextureHost());
#endif
auto surfaceCursor = mSurfaces.find(aId);
MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
Surface* surface = surfaceCursor->second.get();
surface->mExternalImage = image;
MOZ_RELEASE_ASSERT(surface->mTiles.empty());
MOZ_RELEASE_ASSERT(surface->mIsExternal);
}
// static
gfx::SamplingFilter RenderCompositorLayersSWGL::ToSamplingFilter(
wr::ImageRendering aImageRendering) {
if (aImageRendering == wr::ImageRendering::Auto) {
return gfx::SamplingFilter::LINEAR;
}
return gfx::SamplingFilter::POINT;
}
void RenderCompositorLayersSWGL::AddSurface(
wr::NativeSurfaceId aId, const wr::CompositorSurfaceTransform& aTransform,
wr::DeviceIntRect aClipRect, wr::ImageRendering aImageRendering) {
gfx::Matrix4x4 transform(
aTransform.m11, aTransform.m12, aTransform.m13, aTransform.m14,
aTransform.m21, aTransform.m22, aTransform.m23, aTransform.m24,
aTransform.m31, aTransform.m32, aTransform.m33, aTransform.m34,
aTransform.m41, aTransform.m42, aTransform.m43, aTransform.m44);
gfx::IntRect clipRect(aClipRect.origin.x, aClipRect.origin.y,
aClipRect.size.width, aClipRect.size.height);
mFrameSurfaces.AppendElement(FrameSurface{aId, transform, clipRect,
ToSamplingFilter(aImageRendering)});
}
void RenderCompositorLayersSWGL::MaybeRequestAllowFrameRecording(
bool aWillRecord) {
mCompositor->RequestAllowFrameRecording(aWillRecord);
}
bool RenderCompositorLayersSWGL::MaybeRecordFrame(
layers::CompositionRecorder& aRecorder) {
layers::WindowLMC window(mCompositor);
gfx::IntSize size = GetBufferSize().ToUnknownSize();
RefPtr<layers::profiler_screenshots::RenderSource> snapshot =
window.GetWindowContents(size);
if (!snapshot) {
return true;
}
RefPtr<layers::profiler_screenshots::AsyncReadbackBuffer> buffer =
window.CreateAsyncReadbackBuffer(size);
buffer->CopyFrom(snapshot);
RefPtr<layers::RecordedFrame> frame =
new RenderCompositorRecordedFrame(TimeStamp::Now(), std::move(buffer));
aRecorder.RecordFrame(frame);
return false;
}
bool RenderCompositorLayersSWGL::MaybeGrabScreenshot(
const gfx::IntSize& aWindowSize) {
layers::WindowLMC window(mCompositor);
mProfilerScreenshotGrabber.MaybeGrabScreenshot(window, aWindowSize);
return true;
}
bool RenderCompositorLayersSWGL::MaybeProcessScreenshotQueue() {
mProfilerScreenshotGrabber.MaybeProcessQueue();
return true;
}
} // namespace wr
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,189 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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_GFX_RENDERCOMPOSITOR_Layers_H
#define MOZILLA_GFX_RENDERCOMPOSITOR_Layers_H
#include "mozilla/HashFunctions.h"
#include "mozilla/layers/Compositor.h"
#include "mozilla/layers/ScreenshotGrabber.h"
#include "mozilla/webrender/RenderCompositor.h"
#include "mozilla/webrender/RenderTextureHost.h"
namespace mozilla {
namespace wr {
class SurfaceD3D11SWGL;
class RenderCompositorLayersSWGL : public RenderCompositor {
public:
static UniquePtr<RenderCompositor> Create(
RefPtr<widget::CompositorWidget>&& aWidget, nsACString& aError);
RenderCompositorLayersSWGL(layers::Compositor* aCompositor,
RefPtr<widget::CompositorWidget>&& aWidget,
void* aContext);
virtual ~RenderCompositorLayersSWGL();
void* swgl() const override { return mContext; }
bool MakeCurrent() override;
bool BeginFrame() override;
void CancelFrame() override;
RenderedFrameId EndFrame(const nsTArray<DeviceIntRect>& aDirtyRects) final;
bool SurfaceOriginIsTopLeft() override { return true; }
LayoutDeviceIntSize GetBufferSize() override;
// Should we support this?
bool SupportsExternalBufferTextures() const override { return false; }
layers::WebRenderBackend BackendType() const override {
return layers::WebRenderBackend::SOFTWARE;
}
// Interface for wr::Compositor
CompositorCapabilities GetCompositorCapabilities() override;
bool ShouldUseNativeCompositor() override { return true; }
void CompositorBeginFrame() override {}
void CompositorEndFrame() override;
void Bind(wr::NativeTileId aId, wr::DeviceIntPoint* aOffset, uint32_t* aFboId,
wr::DeviceIntRect aDirtyRect,
wr::DeviceIntRect aValidRect) override;
void Unbind() override;
bool MapTile(wr::NativeTileId aId, wr::DeviceIntRect aDirtyRect,
wr::DeviceIntRect aValidRect, void** aData,
int32_t* aStride) override;
void UnmapTile() override;
void CreateSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aVirtualOffset,
wr::DeviceIntSize aTileSize, bool aIsOpaque) override;
void CreateExternalSurface(wr::NativeSurfaceId aId, bool aIsOpaque) override;
void DestroySurface(NativeSurfaceId aId) override;
void CreateTile(wr::NativeSurfaceId, int32_t aX, int32_t aY) override;
void DestroyTile(wr::NativeSurfaceId, int32_t aX, int32_t aY) override;
void AttachExternalImage(wr::NativeSurfaceId aId,
wr::ExternalImageId aExternalImage) override;
void AddSurface(wr::NativeSurfaceId aId,
const wr::CompositorSurfaceTransform& aTransform,
wr::DeviceIntRect aClipRect,
wr::ImageRendering aImageRendering) override;
void EnableNativeCompositor(bool aEnable) override {}
void DeInit() override {}
void MaybeRequestAllowFrameRecording(bool aWillRecord) override;
bool MaybeRecordFrame(layers::CompositionRecorder& aRecorder) override;
bool MaybeGrabScreenshot(const gfx::IntSize& aWindowSize) override;
bool MaybeProcessScreenshotQueue() override;
// TODO: Screenshots etc
struct TileKey {
TileKey(int32_t aX, int32_t aY) : mX(aX), mY(aY) {}
int32_t mX;
int32_t mY;
};
// Each tile retains a texture, and a DataSourceSurface of the
// same size. We draw into the source surface, and then copy the
// changed area into the texture.
class Tile {
public:
Tile() = default;
virtual ~Tile() = default;
virtual bool Map(wr::DeviceIntRect aDirtyRect, wr::DeviceIntRect aValidRect,
void** aData, int32_t* aStride) = 0;
virtual void Unmap(const gfx::IntRect& aDirtyRect) = 0;
virtual layers::DataTextureSource* GetTextureSource() = 0;
virtual bool IsValid() = 0;
gfx::Rect mValidRect;
struct KeyHashFn {
std::size_t operator()(const TileKey& aId) const {
return HashGeneric(aId.mX, aId.mY);
}
};
};
class Surface {
public:
explicit Surface(wr::DeviceIntSize aTileSize, bool aIsOpaque)
: mTileSize(aTileSize), mIsOpaque(aIsOpaque) {}
virtual ~Surface() {}
gfx::IntSize TileSize() {
return gfx::IntSize(mTileSize.width, mTileSize.height);
}
virtual SurfaceD3D11SWGL* AsSurfaceD3D11SWGL() { return nullptr; }
// External images can change size depending on which image
// is attached, so mTileSize will be 0,0 when mIsExternal
// is true.
wr::DeviceIntSize mTileSize;
bool mIsOpaque;
bool mIsExternal = false;
std::unordered_map<TileKey, UniquePtr<Tile>, Tile::KeyHashFn> mTiles;
RefPtr<RenderTextureHost> mExternalImage;
struct IdHashFn {
std::size_t operator()(const wr::NativeSurfaceId& aId) const {
return HashGeneric(wr::AsUint64(aId));
}
};
};
static gfx::SamplingFilter ToSamplingFilter(
wr::ImageRendering aImageRendering);
protected:
// The set of surfaces added to be composited for the current frame
struct FrameSurface {
wr::NativeSurfaceId mId;
gfx::Matrix4x4 mTransform;
gfx::IntRect mClipRect;
gfx::SamplingFilter mFilter;
};
virtual void HandleExternalImage(RenderTextureHost* aExternalImage,
FrameSurface& aFrameSurface) = 0;
virtual UniquePtr<RenderCompositorLayersSWGL::Surface> DoCreateSurface(
wr::DeviceIntSize aTileSize, bool aIsOpaque);
virtual UniquePtr<RenderCompositorLayersSWGL::Tile> DoCreateTile(
Surface* aSurface) = 0;
RefPtr<layers::Compositor> mCompositor;
void* mContext = nullptr;
std::unordered_map<wr::NativeSurfaceId, UniquePtr<Surface>, Surface::IdHashFn>
mSurfaces;
// Temporary state held between MapTile and UnmapTile
Tile* mCurrentTile = nullptr;
gfx::IntRect mCurrentTileDirty;
wr::NativeTileId mCurrentTileId;
nsTArray<FrameSurface> mFrameSurfaces;
bool mInFrame = false;
layers::ScreenshotGrabber mProfilerScreenshotGrabber;
};
static inline bool operator==(const RenderCompositorLayersSWGL::TileKey& a0,
const RenderCompositorLayersSWGL::TileKey& a1) {
return a0.mX == a1.mX && a0.mY == a1.mY;
}
} // namespace wr
} // namespace mozilla
#endif

Просмотреть файл

@ -12,6 +12,7 @@ EXPORTS.mozilla.webrender += [
"RenderBufferTextureHostSWGL.h",
"RenderCompositor.h",
"RenderCompositorEGL.h",
"RenderCompositorLayersSWGL.h",
"RenderCompositorOGL.h",
"RenderCompositorSWGL.h",
"RenderEGLImageTextureHost.h",
@ -35,6 +36,7 @@ UNIFIED_SOURCES += [
"RenderBufferTextureHostSWGL.cpp",
"RenderCompositor.cpp",
"RenderCompositorEGL.cpp",
"RenderCompositorLayersSWGL.cpp",
"RenderCompositorOGL.cpp",
"RenderCompositorSWGL.cpp",
"RenderEGLImageTextureHost.cpp",