Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/webrender_bindings/RendererOGL.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "RendererOGL.h"
8
#include "GLContext.h"
9
#include "mozilla/gfx/Logging.h"
10
#include "mozilla/gfx/gfxVars.h"
11
#include "mozilla/layers/CompositorBridgeParent.h"
12
#include "mozilla/layers/CompositorThread.h"
13
#include "mozilla/layers/LayersTypes.h"
14
#include "mozilla/webrender/RenderCompositor.h"
15
#include "mozilla/webrender/RenderTextureHost.h"
16
#include "mozilla/widget/CompositorWidget.h"
17
18
namespace mozilla {
19
namespace wr {
20
21
wr::WrExternalImage
22
LockExternalImage(void* aObj,
23
                  wr::WrExternalImageId aId,
24
                  uint8_t aChannelIndex,
25
                  wr::ImageRendering aRendering)
26
0
{
27
0
  RendererOGL* renderer = reinterpret_cast<RendererOGL*>(aObj);
28
0
  RenderTextureHost* texture = renderer->GetRenderTexture(aId);
29
0
  MOZ_ASSERT(texture);
30
0
  if (!texture) {
31
0
    gfxCriticalNote << "Failed to lock ExternalImage for extId:" << AsUint64(aId);
32
0
    return InvalidToWrExternalImage();
33
0
  }
34
0
  return texture->Lock(aChannelIndex, renderer->gl(), aRendering);
35
0
}
36
37
void UnlockExternalImage(void* aObj, wr::WrExternalImageId aId, uint8_t aChannelIndex)
38
0
{
39
0
  RendererOGL* renderer = reinterpret_cast<RendererOGL*>(aObj);
40
0
  RenderTextureHost* texture = renderer->GetRenderTexture(aId);
41
0
  MOZ_ASSERT(texture);
42
0
  if (!texture) {
43
0
    return;
44
0
  }
45
0
  texture->Unlock();
46
0
}
47
48
RendererOGL::RendererOGL(RefPtr<RenderThread>&& aThread,
49
                         UniquePtr<RenderCompositor> aCompositor,
50
                         wr::WindowId aWindowId,
51
                         wr::Renderer* aRenderer,
52
                         layers::CompositorBridgeParent* aBridge)
53
  : mThread(aThread)
54
  , mCompositor(std::move(aCompositor))
55
  , mRenderer(aRenderer)
56
  , mBridge(aBridge)
57
  , mWindowId(aWindowId)
58
  , mDebugFlags({ 0 })
59
0
{
60
0
  MOZ_ASSERT(mThread);
61
0
  MOZ_ASSERT(mCompositor);
62
0
  MOZ_ASSERT(mRenderer);
63
0
  MOZ_ASSERT(mBridge);
64
0
  MOZ_COUNT_CTOR(RendererOGL);
65
0
}
66
67
RendererOGL::~RendererOGL()
68
0
{
69
0
  MOZ_COUNT_DTOR(RendererOGL);
70
0
  if (!mCompositor->gl()->MakeCurrent()) {
71
0
    gfxCriticalNote << "Failed to make render context current during destroying.";
72
0
    // Leak resources!
73
0
    return;
74
0
  }
75
0
  wr_renderer_delete(mRenderer);
76
0
}
77
78
wr::WrExternalImageHandler
79
RendererOGL::GetExternalImageHandler()
80
0
{
81
0
  return wr::WrExternalImageHandler {
82
0
    this,
83
0
    LockExternalImage,
84
0
    UnlockExternalImage,
85
0
  };
86
0
}
87
88
void
89
RendererOGL::Update()
90
0
{
91
0
  uint32_t flags = gfx::gfxVars::WebRenderDebugFlags();
92
0
  if (mDebugFlags.mBits != flags) {
93
0
    mDebugFlags.mBits = flags;
94
0
    wr_renderer_set_debug_flags(mRenderer, mDebugFlags);
95
0
  }
96
0
97
0
  if (gl()->MakeCurrent()) {
98
0
    wr_renderer_update(mRenderer);
99
0
  }
100
0
}
101
102
static void
103
DoNotifyWebRenderContextPurge(layers::CompositorBridgeParent* aBridge)
104
0
{
105
0
  aBridge->NotifyWebRenderContextPurge();
106
0
}
107
108
bool
109
RendererOGL::UpdateAndRender(bool aReadback)
110
0
{
111
0
  uint32_t flags = gfx::gfxVars::WebRenderDebugFlags();
112
0
  // Disable debug flags during readback
113
0
  if (aReadback) {
114
0
    flags = 0;
115
0
  }
116
0
117
0
  if (mDebugFlags.mBits != flags) {
118
0
    mDebugFlags.mBits = flags;
119
0
    wr_renderer_set_debug_flags(mRenderer, mDebugFlags);
120
0
  }
121
0
122
0
  mozilla::widget::WidgetRenderingContext widgetContext;
123
0
124
#if defined(XP_MACOSX)
125
  widgetContext.mGL = mCompositor->gl();
126
// TODO: we don't have a notion of compositor here.
127
//#elif defined(MOZ_WIDGET_ANDROID)
128
//  widgetContext.mCompositor = mCompositor;
129
#endif
130
131
0
  if (!mCompositor->GetWidget()->PreRender(&widgetContext)) {
132
0
    // XXX This could cause oom in webrender since pending_texture_updates is not handled.
133
0
    // It needs to be addressed.
134
0
    return false;
135
0
  }
136
0
  // XXX set clear color if MOZ_WIDGET_ANDROID is defined.
137
0
138
0
  if (!mCompositor->BeginFrame()) {
139
0
    return false;
140
0
  }
141
0
142
0
  wr_renderer_update(mRenderer);
143
0
144
0
  auto size = mCompositor->GetBufferSize();
145
0
146
0
  if (!wr_renderer_render(mRenderer, size.width, size.height)) {
147
0
    NotifyWebRenderError(WebRenderError::RENDER);
148
0
  }
149
0
150
0
  mCompositor->EndFrame();
151
0
152
0
  mCompositor->GetWidget()->PostRender(&widgetContext);
153
0
154
#if defined(ENABLE_FRAME_LATENCY_LOG)
155
  if (mFrameStartTime) {
156
    uint32_t latencyMs = round((TimeStamp::Now() - mFrameStartTime).ToMilliseconds());
157
    printf_stderr("generate frame latencyMs latencyMs %d\n", latencyMs);
158
  }
159
  // Clear frame start time
160
  mFrameStartTime = TimeStamp();
161
#endif
162
163
0
  gl::GLContext* gl = mCompositor->gl();
164
0
  if (gl->IsSupported(gl::GLFeature::robustness)) {
165
0
    GLenum resetStatus = gl->fGetGraphicsResetStatus();
166
0
    if (resetStatus == LOCAL_GL_PURGED_CONTEXT_RESET_NV) {
167
0
      layers::CompositorThreadHolder::Loop()->PostTask(NewRunnableFunction(
168
0
        "DoNotifyWebRenderContextPurgeRunnable",
169
0
        &DoNotifyWebRenderContextPurge,
170
0
        mBridge
171
0
      ));
172
0
    }
173
0
  }
174
0
175
0
  // TODO: Flush pending actions such as texture deletions/unlocks and
176
0
  //       textureHosts recycling.
177
0
178
0
  return true;
179
0
}
180
181
void
182
RendererOGL::Pause()
183
0
{
184
0
  mCompositor->Pause();
185
0
}
186
187
bool
188
RendererOGL::Resume()
189
0
{
190
0
  return mCompositor->Resume();
191
0
}
192
193
layers::SyncObjectHost*
194
RendererOGL::GetSyncObject() const
195
0
{
196
0
  return mCompositor->GetSyncObject();
197
0
}
198
199
gl::GLContext*
200
RendererOGL::gl() const
201
0
{
202
0
  return mCompositor->gl();
203
0
}
204
205
void
206
RendererOGL::SetFrameStartTime(const TimeStamp& aTime)
207
0
{
208
0
  if (mFrameStartTime) {
209
0
    // frame start time is already set. This could happen when multiple
210
0
    // generate frame requests are merged by webrender.
211
0
    return;
212
0
  }
213
0
  mFrameStartTime = aTime;
214
0
}
215
216
wr::WrPipelineInfo
217
RendererOGL::FlushPipelineInfo()
218
0
{
219
0
  return wr_renderer_flush_pipeline_info(mRenderer);
220
0
}
221
222
RenderTextureHost*
223
RendererOGL::GetRenderTexture(wr::WrExternalImageId aExternalImageId)
224
0
{
225
0
  return mThread->GetRenderTexture(aExternalImageId);
226
0
}
227
228
static void
229
DoNotifyWebRenderError(layers::CompositorBridgeParent* aBridge, WebRenderError aError)
230
0
{
231
0
  aBridge->NotifyWebRenderError(aError);
232
0
}
233
234
void
235
RendererOGL::NotifyWebRenderError(WebRenderError aError)
236
0
{
237
0
  layers::CompositorThreadHolder::Loop()->PostTask(NewRunnableFunction(
238
0
    "DoNotifyWebRenderErrorRunnable",
239
0
    &DoNotifyWebRenderError,
240
0
    mBridge,
241
0
    aError
242
0
  ));
243
0
}
244
245
} // namespace wr
246
} // namespace mozilla