зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1740127 - Combine copy/swizzle/premultiply operations in ClientWebGLContext::GetFrontBufferSnapshot. r=jgilbert
The swizzling operations were showing up in talos profiles on Linux with GLX and using OOP WebGL. If DMABuf has been disabled, similar performance should be observed with EGL as well. This patch combines the necessary copies, swizzling between RGBA and BGRA, and premultiplication operations as much as possible for GetFrontBufferSnapshot. It also has the advantage of unblocking the WebGL thread in the compositor process sooner since it is a sync IPC call and moving that work to the caller which would be blocked anyways. Differential Revision: https://phabricator.services.mozilla.com/D130690
This commit is contained in:
Родитель
487df1c1c4
Коммит
25fe6561f6
|
@ -21,6 +21,7 @@
|
|||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/gfx/CanvasManagerChild.h"
|
||||
#include "mozilla/ipc/Shmem.h"
|
||||
#include "mozilla/gfx/Swizzle.h"
|
||||
#include "mozilla/layers/CompositorBridgeChild.h"
|
||||
#include "mozilla/layers/ImageBridgeChild.h"
|
||||
#include "mozilla/layers/OOPCanvasRenderer.h"
|
||||
|
@ -884,53 +885,15 @@ RefPtr<gfx::SourceSurface> ClientWebGLContext::GetFrontBufferSnapshot(
|
|||
/*zero=*/true));
|
||||
};
|
||||
|
||||
auto snapshot = [&]() -> RefPtr<gfx::DataSourceSurface> {
|
||||
const auto& inProcess = mNotLost->inProcess;
|
||||
if (inProcess) {
|
||||
const auto maybeSize = inProcess->FrontBufferSnapshotInto({});
|
||||
if (!maybeSize) return nullptr;
|
||||
const auto& surfSize = *maybeSize;
|
||||
const auto stride = surfSize.x * 4;
|
||||
const auto byteSize = stride * surfSize.y;
|
||||
const auto surf = fnNewSurf(surfSize);
|
||||
if (!surf) return nullptr;
|
||||
{
|
||||
const gfx::DataSourceSurface::ScopedMap map(
|
||||
surf, gfx::DataSourceSurface::READ_WRITE);
|
||||
if (!map.IsMapped()) {
|
||||
MOZ_ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(map.GetStride() == static_cast<int64_t>(stride));
|
||||
auto range = Range<uint8_t>{map.GetData(), byteSize};
|
||||
if (!inProcess->FrontBufferSnapshotInto(Some(range))) {
|
||||
gfxCriticalNote << "ClientWebGLContext::GetFrontBufferSnapshot: "
|
||||
"FrontBufferSnapshotInto(some) failed after "
|
||||
"FrontBufferSnapshotInto(none)";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return surf;
|
||||
}
|
||||
const auto& child = mNotLost->outOfProcess;
|
||||
child->FlushPendingCmds();
|
||||
webgl::FrontBufferSnapshotIpc res;
|
||||
if (!child->SendGetFrontBufferSnapshot(&res)) {
|
||||
res = {};
|
||||
}
|
||||
if (!res.shmem) return nullptr;
|
||||
|
||||
const auto& surfSize = res.surfSize;
|
||||
const webgl::RaiiShmem shmem{child, res.shmem.ref()};
|
||||
const auto& shmemBytes = shmem.ByteRange();
|
||||
if (!surfSize.x) return nullptr; // Zero means failure.
|
||||
|
||||
const auto& inProcess = mNotLost->inProcess;
|
||||
if (inProcess) {
|
||||
const auto maybeSize = inProcess->FrontBufferSnapshotInto({});
|
||||
if (!maybeSize) return nullptr;
|
||||
const auto& surfSize = *maybeSize;
|
||||
const auto stride = surfSize.x * 4;
|
||||
const auto byteSize = stride * surfSize.y;
|
||||
|
||||
const auto surf = fnNewSurf(surfSize);
|
||||
if (!surf) return nullptr;
|
||||
|
||||
{
|
||||
const gfx::DataSourceSurface::ScopedMap map(
|
||||
surf, gfx::DataSourceSurface::READ_WRITE);
|
||||
|
@ -939,26 +902,71 @@ RefPtr<gfx::SourceSurface> ClientWebGLContext::GetFrontBufferSnapshot(
|
|||
return nullptr;
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(map.GetStride() == static_cast<int64_t>(stride));
|
||||
MOZ_RELEASE_ASSERT(shmemBytes.length() == byteSize);
|
||||
memcpy(map.GetData(), shmemBytes.begin().get(), byteSize);
|
||||
auto range = Range<uint8_t>{map.GetData(), byteSize};
|
||||
if (!inProcess->FrontBufferSnapshotInto(Some(range))) {
|
||||
gfxCriticalNote << "ClientWebGLContext::GetFrontBufferSnapshot: "
|
||||
"FrontBufferSnapshotInto(some) failed after "
|
||||
"FrontBufferSnapshotInto(none)";
|
||||
return nullptr;
|
||||
}
|
||||
if (requireAlphaPremult && options.alpha && !options.premultipliedAlpha) {
|
||||
bool rv = gfx::PremultiplyData(
|
||||
map.GetData(), map.GetStride(), gfx::SurfaceFormat::R8G8B8A8,
|
||||
map.GetData(), map.GetStride(), gfx::SurfaceFormat::B8G8R8A8,
|
||||
surf->GetSize());
|
||||
MOZ_RELEASE_ASSERT(rv, "PremultiplyData failed!");
|
||||
} else {
|
||||
bool rv = gfx::SwizzleData(
|
||||
map.GetData(), map.GetStride(), gfx::SurfaceFormat::R8G8B8A8,
|
||||
map.GetData(), map.GetStride(), gfx::SurfaceFormat::B8G8R8A8,
|
||||
surf->GetSize());
|
||||
MOZ_RELEASE_ASSERT(rv, "SwizzleData failed!");
|
||||
}
|
||||
}
|
||||
return surf;
|
||||
}();
|
||||
if (!snapshot) return nullptr;
|
||||
|
||||
if (requireAlphaPremult && options.alpha && !options.premultipliedAlpha) {
|
||||
const auto nonPremultSurf = snapshot;
|
||||
const auto& size = nonPremultSurf->GetSize();
|
||||
const auto format = nonPremultSurf->GetFormat();
|
||||
snapshot =
|
||||
gfx::Factory::CreateDataSourceSurface(size, format, /*zero=*/false);
|
||||
if (!snapshot) {
|
||||
gfxCriticalNote << "CreateDataSourceSurface failed for size " << size;
|
||||
}
|
||||
gfxUtils::PremultiplyDataSurface(nonPremultSurf, snapshot);
|
||||
}
|
||||
const auto& child = mNotLost->outOfProcess;
|
||||
child->FlushPendingCmds();
|
||||
webgl::FrontBufferSnapshotIpc res;
|
||||
if (!child->SendGetFrontBufferSnapshot(&res)) {
|
||||
res = {};
|
||||
}
|
||||
if (!res.shmem) return nullptr;
|
||||
|
||||
return snapshot;
|
||||
const auto& surfSize = res.surfSize;
|
||||
const webgl::RaiiShmem shmem{child, res.shmem.ref()};
|
||||
const auto& shmemBytes = shmem.ByteRange();
|
||||
if (!surfSize.x) return nullptr; // Zero means failure.
|
||||
|
||||
const auto stride = surfSize.x * 4;
|
||||
const auto byteSize = stride * surfSize.y;
|
||||
|
||||
const auto surf = fnNewSurf(surfSize);
|
||||
if (!surf) return nullptr;
|
||||
|
||||
{
|
||||
const gfx::DataSourceSurface::ScopedMap map(
|
||||
surf, gfx::DataSourceSurface::READ_WRITE);
|
||||
if (!map.IsMapped()) {
|
||||
MOZ_ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(shmemBytes.length() == byteSize);
|
||||
if (requireAlphaPremult && options.alpha && !options.premultipliedAlpha) {
|
||||
bool rv = gfx::PremultiplyData(
|
||||
shmemBytes.begin().get(), stride, gfx::SurfaceFormat::R8G8B8A8,
|
||||
map.GetData(), map.GetStride(), gfx::SurfaceFormat::B8G8R8A8,
|
||||
surf->GetSize());
|
||||
MOZ_RELEASE_ASSERT(rv, "PremultiplyData failed!");
|
||||
} else {
|
||||
bool rv = gfx::SwizzleData(shmemBytes.begin().get(), stride,
|
||||
gfx::SurfaceFormat::R8G8B8A8, map.GetData(),
|
||||
map.GetStride(), gfx::SurfaceFormat::B8G8R8A8,
|
||||
surf->GetSize());
|
||||
MOZ_RELEASE_ASSERT(rv, "SwizzleData failed!");
|
||||
}
|
||||
}
|
||||
return surf;
|
||||
}
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> ClientWebGLContext::BackBufferSnapshot() {
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "gfxCrashReporterUtils.h"
|
||||
#include "gfxEnv.h"
|
||||
#include "gfxPattern.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "MozFramebuffer.h"
|
||||
#include "GLBlitHelper.h"
|
||||
#include "GLContext.h"
|
||||
|
@ -1017,7 +1016,6 @@ Maybe<uvec2> WebGLContext::FrontBufferSnapshotInto(
|
|||
}
|
||||
gl->fReadPixels(0, 0, size.width, size.height, LOCAL_GL_RGBA,
|
||||
LOCAL_GL_UNSIGNED_BYTE, dest.begin().get());
|
||||
gfxUtils::ConvertBGRAtoRGBA(dest.begin().get(), dstByteCount);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче