gecko-dev/gfx/webrender_bindings/RendererOGL.cpp
Bobby Holley 8446df67e8 Bug 1510490 - Measure shader cache memory usage and remove total_gpu_bytes. r=mattwoodrow
The latter causes confusion in the memory reports because it gets summed
up and thus effectively doubles the reported texture memory usage. I've
decided it's best to drop, and so might as well do that while we're
already messing around with the memory reports and the associated
boilerplate.

Depends on D13439

Differential Revision: https://phabricator.services.mozilla.com/D13440
2018-12-01 10:43:03 -08:00

226 lines
7.2 KiB
C++

/* -*- 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 "RendererOGL.h"
#include "GLContext.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/Types.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/webrender/RenderCompositor.h"
#include "mozilla/webrender/RenderTextureHost.h"
#include "mozilla/widget/CompositorWidget.h"
namespace mozilla {
namespace wr {
wr::WrExternalImage LockExternalImage(void* aObj, wr::WrExternalImageId aId,
uint8_t aChannelIndex,
wr::ImageRendering aRendering) {
RendererOGL* renderer = reinterpret_cast<RendererOGL*>(aObj);
RenderTextureHost* texture = renderer->GetRenderTexture(aId);
MOZ_ASSERT(texture);
if (!texture) {
gfxCriticalNote << "Failed to lock ExternalImage for extId:"
<< AsUint64(aId);
return InvalidToWrExternalImage();
}
return texture->Lock(aChannelIndex, renderer->gl(), aRendering);
}
void UnlockExternalImage(void* aObj, wr::WrExternalImageId aId,
uint8_t aChannelIndex) {
RendererOGL* renderer = reinterpret_cast<RendererOGL*>(aObj);
RenderTextureHost* texture = renderer->GetRenderTexture(aId);
MOZ_ASSERT(texture);
if (!texture) {
return;
}
texture->Unlock();
}
RendererOGL::RendererOGL(RefPtr<RenderThread>&& aThread,
UniquePtr<RenderCompositor> aCompositor,
wr::WindowId aWindowId, wr::Renderer* aRenderer,
layers::CompositorBridgeParent* aBridge)
: mThread(aThread),
mCompositor(std::move(aCompositor)),
mRenderer(aRenderer),
mBridge(aBridge),
mWindowId(aWindowId) {
MOZ_ASSERT(mThread);
MOZ_ASSERT(mCompositor);
MOZ_ASSERT(mRenderer);
MOZ_ASSERT(mBridge);
MOZ_COUNT_CTOR(RendererOGL);
}
RendererOGL::~RendererOGL() {
MOZ_COUNT_DTOR(RendererOGL);
if (!mCompositor->MakeCurrent()) {
gfxCriticalNote
<< "Failed to make render context current during destroying.";
// Leak resources!
return;
}
wr_renderer_delete(mRenderer);
}
wr::WrExternalImageHandler RendererOGL::GetExternalImageHandler() {
return wr::WrExternalImageHandler{
this,
LockExternalImage,
UnlockExternalImage,
};
}
void RendererOGL::Update() {
if (mCompositor->MakeCurrent()) {
wr_renderer_update(mRenderer);
}
}
static void DoNotifyWebRenderContextPurge(
layers::CompositorBridgeParent* aBridge) {
aBridge->NotifyWebRenderContextPurge();
}
bool RendererOGL::UpdateAndRender(const Maybe<gfx::IntSize>& aReadbackSize,
const Maybe<Range<uint8_t>>& aReadbackBuffer,
bool aHadSlowFrame,
RendererStats* aOutStats) {
mozilla::widget::WidgetRenderingContext widgetContext;
#if defined(XP_MACOSX)
widgetContext.mGL = mCompositor->gl();
// TODO: we don't have a notion of compositor here.
//#elif defined(MOZ_WIDGET_ANDROID)
// widgetContext.mCompositor = mCompositor;
#endif
if (!mCompositor->GetWidget()->PreRender(&widgetContext)) {
// XXX This could cause oom in webrender since pending_texture_updates is
// not handled. It needs to be addressed.
return false;
}
// XXX set clear color if MOZ_WIDGET_ANDROID is defined.
if (!mCompositor->BeginFrame()) {
return false;
}
wr_renderer_update(mRenderer);
auto size = mCompositor->GetBufferSize();
if (!wr_renderer_render(mRenderer, size.width, size.height, aHadSlowFrame,
aOutStats)) {
NotifyWebRenderError(WebRenderError::RENDER);
}
if (aReadbackBuffer.isSome()) {
MOZ_ASSERT(aReadbackSize.isSome());
wr_renderer_readback(mRenderer, aReadbackSize.ref().width,
aReadbackSize.ref().height, &aReadbackBuffer.ref()[0],
aReadbackBuffer.ref().length());
}
mCompositor->EndFrame();
mCompositor->GetWidget()->PostRender(&widgetContext);
#if defined(ENABLE_FRAME_LATENCY_LOG)
if (mFrameStartTime) {
uint32_t latencyMs =
round((TimeStamp::Now() - mFrameStartTime).ToMilliseconds());
printf_stderr("generate frame latencyMs latencyMs %d\n", latencyMs);
}
// Clear frame start time
mFrameStartTime = TimeStamp();
#endif
// TODO: Flush pending actions such as texture deletions/unlocks and
// textureHosts recycling.
return true;
}
void RendererOGL::CheckGraphicsResetStatus() {
if (!mCompositor || !mCompositor->gl()) {
return;
}
gl::GLContext* gl = mCompositor->gl();
if (gl->IsSupported(gl::GLFeature::robustness)) {
GLenum resetStatus = gl->fGetGraphicsResetStatus();
if (resetStatus == LOCAL_GL_PURGED_CONTEXT_RESET_NV) {
layers::CompositorThreadHolder::Loop()->PostTask(
NewRunnableFunction("DoNotifyWebRenderContextPurgeRunnable",
&DoNotifyWebRenderContextPurge, mBridge));
}
}
}
void RendererOGL::WaitForGPU() { mCompositor->WaitForGPU(); }
void RendererOGL::Pause() { mCompositor->Pause(); }
bool RendererOGL::Resume() { return mCompositor->Resume(); }
layers::SyncObjectHost* RendererOGL::GetSyncObject() const {
return mCompositor->GetSyncObject();
}
gl::GLContext* RendererOGL::gl() const { return mCompositor->gl(); }
void RendererOGL::SetFrameStartTime(const TimeStamp& aTime) {
if (mFrameStartTime) {
// frame start time is already set. This could happen when multiple
// generate frame requests are merged by webrender.
return;
}
mFrameStartTime = aTime;
}
RefPtr<WebRenderPipelineInfo> RendererOGL::FlushPipelineInfo() {
auto info = wr_renderer_flush_pipeline_info(mRenderer);
return new WebRenderPipelineInfo(info);
}
RenderTextureHost* RendererOGL::GetRenderTexture(
wr::WrExternalImageId aExternalImageId) {
return mThread->GetRenderTexture(aExternalImageId);
}
void RendererOGL::AccumulateMemoryReport(MemoryReport* aReport) {
wr_renderer_accumulate_memory_report(GetRenderer(), aReport);
LayoutDeviceIntSize size = mCompositor->GetBufferSize();
// Assume BGRA8 for the format since it's not exposed anywhere,
// and all compositor backends should be using that.
uintptr_t swapChainSize = size.width * size.height *
BytesPerPixel(SurfaceFormat::B8G8R8A8) *
(mCompositor->UseTripleBuffering() ? 3 : 2);
aReport->swap_chain += swapChainSize;
}
static void DoNotifyWebRenderError(layers::CompositorBridgeParent* aBridge,
WebRenderError aError) {
aBridge->NotifyWebRenderError(aError);
}
void RendererOGL::NotifyWebRenderError(WebRenderError aError) {
layers::CompositorThreadHolder::Loop()->PostTask(
NewRunnableFunction("DoNotifyWebRenderErrorRunnable",
&DoNotifyWebRenderError, mBridge, aError));
}
} // namespace wr
} // namespace mozilla