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
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * You can obtain one at http://mozilla.org/MPL/2.0/. */
9 #include "RenderCompositorLayersSWGL.h"
11 #include "GLContext.h"
12 #include "GLContextEGL.h"
13 #include "mozilla/layers/BuildConstants.h"
14 #include "mozilla/layers/Effects.h"
15 #include "mozilla/layers/TextureHostOGL.h"
16 #include "mozilla/widget/CompositorWidget.h"
17 #include "RenderCompositorRecordedFrame.h"
20 # include "mozilla/webrender/RenderCompositorD3D11SWGL.h"
22 # include "mozilla/webrender/RenderCompositorOGLSWGL.h"
26 using namespace layers
;
31 UniquePtr
<RenderCompositor
> RenderCompositorLayersSWGL::Create(
32 const RefPtr
<widget::CompositorWidget
>& aWidget
, nsACString
& aError
) {
34 return RenderCompositorD3D11SWGL::Create(aWidget
, aError
);
36 return RenderCompositorOGLSWGL::Create(aWidget
, aError
);
40 RenderCompositorLayersSWGL::RenderCompositorLayersSWGL(
41 Compositor
* aCompositor
, const RefPtr
<widget::CompositorWidget
>& aWidget
,
43 : RenderCompositor(aWidget
),
44 mCompositor(aCompositor
),
46 mCurrentTileId(wr::NativeTileId()) {
47 MOZ_ASSERT(mCompositor
);
51 RenderCompositorLayersSWGL::~RenderCompositorLayersSWGL() {
52 wr_swgl_destroy_context(mContext
);
55 bool RenderCompositorLayersSWGL::MakeCurrent() {
56 wr_swgl_make_current(mContext
);
60 bool RenderCompositorLayersSWGL::BeginFrame() {
61 MOZ_ASSERT(!mInFrame
);
67 void RenderCompositorLayersSWGL::CancelFrame() {
70 if (mCompositingStarted
) {
71 mCompositor
->CancelFrame();
72 mCompositingStarted
= false;
76 void RenderCompositorLayersSWGL::StartCompositing(
77 wr::ColorF aClearColor
, const wr::DeviceIntRect
* aDirtyRects
,
78 size_t aNumDirtyRects
, const wr::DeviceIntRect
* aOpaqueRects
,
79 size_t aNumOpaqueRects
) {
80 MOZ_RELEASE_ASSERT(!mCompositingStarted
);
82 if (!mInFrame
|| aNumDirtyRects
== 0) {
86 gfx::IntRect
bounds(gfx::IntPoint(0, 0), GetBufferSize().ToUnknownSize());
89 MOZ_RELEASE_ASSERT(aNumDirtyRects
> 0);
90 for (size_t i
= 0; i
< aNumDirtyRects
; i
++) {
91 const auto& rect
= aDirtyRects
[i
];
93 gfx::IntRect(rect
.min
.x
, rect
.min
.y
, rect
.width(), rect
.height()));
95 dirty
.AndWith(bounds
);
97 nsIntRegion
opaque(bounds
);
98 opaque
.SubOut(mWidget
->GetTransparentRegion().ToUnknownRegion());
99 for (size_t i
= 0; i
< aNumOpaqueRects
; i
++) {
100 const auto& rect
= aOpaqueRects
[i
];
102 gfx::IntRect(rect
.min
.x
, rect
.min
.y
, rect
.width(), rect
.height()));
105 mCompositor
->SetClearColor(gfx::DeviceColor(aClearColor
.r
, aClearColor
.g
,
106 aClearColor
.b
, aClearColor
.a
));
108 if (!mCompositor
->BeginFrameForWindow(dirty
, Nothing(), bounds
, opaque
)) {
111 mCompositingStarted
= true;
114 void RenderCompositorLayersSWGL::CompositorEndFrame() {
115 nsTArray
<FrameSurface
> frameSurfaces
= std::move(mFrameSurfaces
);
117 if (!mCompositingStarted
) {
121 for (auto& frameSurface
: frameSurfaces
) {
122 auto surfaceCursor
= mSurfaces
.find(frameSurface
.mId
);
123 MOZ_RELEASE_ASSERT(surfaceCursor
!= mSurfaces
.end());
124 Surface
* surface
= surfaceCursor
->second
.get();
126 for (auto it
= surface
->mTiles
.begin(); it
!= surface
->mTiles
.end(); ++it
) {
127 if (!it
->second
->IsValid()) {
131 gfx::Point
tileOffset(it
->first
.mX
* surface
->mTileSize
.width
,
132 it
->first
.mY
* surface
->mTileSize
.height
);
133 gfx::Rect drawRect
= it
->second
->mValidRect
+ tileOffset
;
135 RefPtr
<TexturedEffect
> texturedEffect
=
136 new EffectRGB(it
->second
->GetTextureSource(),
137 /* aPremultiplied */ true, frameSurface
.mFilter
);
138 if (surface
->mIsOpaque
) {
139 texturedEffect
->mPremultipliedCopy
= true;
142 texturedEffect
->mTextureCoords
=
143 gfx::Rect(it
->second
->mValidRect
.x
/ surface
->mTileSize
.width
,
144 it
->second
->mValidRect
.y
/ surface
->mTileSize
.height
,
145 it
->second
->mValidRect
.width
/ surface
->mTileSize
.width
,
146 it
->second
->mValidRect
.height
/ surface
->mTileSize
.height
);
149 effect
.mPrimaryEffect
= texturedEffect
;
150 mCompositor
->DrawQuad(drawRect
, frameSurface
.mClipRect
, effect
, 1.0,
151 frameSurface
.mTransform
, drawRect
);
154 if (surface
->mExternalImage
) {
155 HandleExternalImage(surface
->mExternalImage
, frameSurface
);
160 RenderedFrameId
RenderCompositorLayersSWGL::EndFrame(
161 const nsTArray
<DeviceIntRect
>& aDirtyRects
) {
162 MOZ_ASSERT(mInFrame
);
164 if (mCompositingStarted
) {
165 mCompositor
->EndFrame();
166 mCompositingStarted
= false;
168 return GetNextRenderFrameId();
171 LayoutDeviceIntSize
RenderCompositorLayersSWGL::GetBufferSize() {
172 return mWidget
->GetClientSize();
175 void RenderCompositorLayersSWGL::Bind(wr::NativeTileId aId
,
176 wr::DeviceIntPoint
* aOffset
,
178 wr::DeviceIntRect aDirtyRect
,
179 wr::DeviceIntRect aValidRect
) {
180 MOZ_RELEASE_ASSERT(false);
183 void RenderCompositorLayersSWGL::Unbind() { MOZ_RELEASE_ASSERT(false); }
185 bool RenderCompositorLayersSWGL::MapTile(wr::NativeTileId aId
,
186 wr::DeviceIntRect aDirtyRect
,
187 wr::DeviceIntRect aValidRect
,
188 void** aData
, int32_t* aStride
) {
189 auto surfaceCursor
= mSurfaces
.find(aId
.surface_id
);
190 MOZ_RELEASE_ASSERT(surfaceCursor
!= mSurfaces
.end());
191 Surface
* surface
= surfaceCursor
->second
.get();
193 auto layerCursor
= surface
->mTiles
.find(TileKey(aId
.x
, aId
.y
));
194 MOZ_RELEASE_ASSERT(layerCursor
!= surface
->mTiles
.end());
196 mCurrentTile
= layerCursor
->second
.get();
197 mCurrentTileId
= aId
;
198 mCurrentTileDirty
= gfx::IntRect(aDirtyRect
.min
.x
, aDirtyRect
.min
.y
,
199 aDirtyRect
.width(), aDirtyRect
.height());
201 if (!mCurrentTile
->Map(aDirtyRect
, aValidRect
, aData
, aStride
)) {
202 gfxCriticalNote
<< "MapTile failed aValidRect: "
203 << gfx::Rect(aValidRect
.min
.x
, aValidRect
.min
.y
,
204 aValidRect
.width(), aValidRect
.height());
208 // Store the new valid rect, so that we can composite only those pixels
209 mCurrentTile
->mValidRect
= gfx::Rect(aValidRect
.min
.x
, aValidRect
.min
.y
,
210 aValidRect
.width(), aValidRect
.height());
214 void RenderCompositorLayersSWGL::UnmapTile() {
215 mCurrentTile
->Unmap(mCurrentTileDirty
);
216 mCurrentTile
= nullptr;
219 void RenderCompositorLayersSWGL::CreateSurface(
220 wr::NativeSurfaceId aId
, wr::DeviceIntPoint aVirtualOffset
,
221 wr::DeviceIntSize aTileSize
, bool aIsOpaque
) {
222 MOZ_RELEASE_ASSERT(mSurfaces
.find(aId
) == mSurfaces
.end());
223 auto surface
= DoCreateSurface(aTileSize
, aIsOpaque
);
224 mSurfaces
.insert({aId
, std::move(surface
)});
227 UniquePtr
<RenderCompositorLayersSWGL::Surface
>
228 RenderCompositorLayersSWGL::DoCreateSurface(wr::DeviceIntSize aTileSize
,
230 return MakeUnique
<Surface
>(aTileSize
, aIsOpaque
);
233 void RenderCompositorLayersSWGL::CreateExternalSurface(wr::NativeSurfaceId aId
,
235 MOZ_RELEASE_ASSERT(mSurfaces
.find(aId
) == mSurfaces
.end());
236 auto surface
= MakeUnique
<Surface
>(wr::DeviceIntSize
{}, aIsOpaque
);
237 surface
->mIsExternal
= true;
238 mSurfaces
.insert({aId
, std::move(surface
)});
241 void RenderCompositorLayersSWGL::DestroySurface(NativeSurfaceId aId
) {
242 auto surfaceCursor
= mSurfaces
.find(aId
);
243 MOZ_RELEASE_ASSERT(surfaceCursor
!= mSurfaces
.end());
244 mSurfaces
.erase(surfaceCursor
);
247 void RenderCompositorLayersSWGL::CreateTile(wr::NativeSurfaceId aId
, int32_t aX
,
249 auto surfaceCursor
= mSurfaces
.find(aId
);
250 MOZ_RELEASE_ASSERT(surfaceCursor
!= mSurfaces
.end());
251 Surface
* surface
= surfaceCursor
->second
.get();
252 MOZ_RELEASE_ASSERT(!surface
->mIsExternal
);
254 auto tile
= DoCreateTile(surface
);
255 surface
->mTiles
.insert({TileKey(aX
, aY
), std::move(tile
)});
258 void RenderCompositorLayersSWGL::DestroyTile(wr::NativeSurfaceId aId
,
259 int32_t aX
, int32_t aY
) {
260 auto surfaceCursor
= mSurfaces
.find(aId
);
261 MOZ_RELEASE_ASSERT(surfaceCursor
!= mSurfaces
.end());
262 Surface
* surface
= surfaceCursor
->second
.get();
263 MOZ_RELEASE_ASSERT(!surface
->mIsExternal
);
265 auto layerCursor
= surface
->mTiles
.find(TileKey(aX
, aY
));
266 MOZ_RELEASE_ASSERT(layerCursor
!= surface
->mTiles
.end());
267 surface
->mTiles
.erase(layerCursor
);
270 void RenderCompositorLayersSWGL::AttachExternalImage(
271 wr::NativeSurfaceId aId
, wr::ExternalImageId aExternalImage
) {
272 RenderTextureHost
* image
=
273 RenderThread::Get()->GetRenderTexture(aExternalImage
);
277 << "Failed to get RenderTextureHost for D3D11SWGL extId:"
278 << AsUint64(aExternalImage
);
282 MOZ_RELEASE_ASSERT(image
->AsRenderDXGITextureHost() ||
283 image
->AsRenderDXGIYCbCrTextureHost());
284 #elif defined(ANDROID)
285 MOZ_RELEASE_ASSERT(image
->AsRenderAndroidHardwareBufferTextureHost() ||
286 image
->AsRenderAndroidSurfaceTextureHost() ||
287 image
->AsRenderEGLImageTextureHost());
290 auto surfaceCursor
= mSurfaces
.find(aId
);
291 MOZ_RELEASE_ASSERT(surfaceCursor
!= mSurfaces
.end());
293 Surface
* surface
= surfaceCursor
->second
.get();
294 surface
->mExternalImage
= image
;
295 MOZ_RELEASE_ASSERT(surface
->mTiles
.empty());
296 MOZ_RELEASE_ASSERT(surface
->mIsExternal
);
300 gfx::SamplingFilter
RenderCompositorLayersSWGL::ToSamplingFilter(
301 wr::ImageRendering aImageRendering
) {
302 if (aImageRendering
== wr::ImageRendering::Auto
) {
303 return gfx::SamplingFilter::LINEAR
;
305 return gfx::SamplingFilter::POINT
;
308 void RenderCompositorLayersSWGL::AddSurface(
309 wr::NativeSurfaceId aId
, const wr::CompositorSurfaceTransform
& aTransform
,
310 wr::DeviceIntRect aClipRect
, wr::ImageRendering aImageRendering
) {
311 float sx
= aTransform
.scale
.x
;
312 float sy
= aTransform
.scale
.y
;
313 float tx
= aTransform
.offset
.x
;
314 float ty
= aTransform
.offset
.y
;
315 gfx::Matrix4x4
transform(sx
, 0.0, 0.0, 0.0, 0.0, sy
, 0.0, 0.0, 0.0, 0.0, 1.0,
316 0.0, tx
, ty
, 0.0, 1.0);
317 gfx::IntRect
clipRect(aClipRect
.min
.x
, aClipRect
.min
.y
, aClipRect
.width(),
320 mFrameSurfaces
.AppendElement(FrameSurface
{aId
, transform
, clipRect
,
321 ToSamplingFilter(aImageRendering
)});
324 void RenderCompositorLayersSWGL::MaybeRequestAllowFrameRecording(
326 mCompositor
->RequestAllowFrameRecording(aWillRecord
);
329 class WindowLMC
: public profiler_screenshots::Window
{
331 explicit WindowLMC(Compositor
* aCompositor
) : mCompositor(aCompositor
) {}
333 already_AddRefed
<profiler_screenshots::RenderSource
> GetWindowContents(
334 const gfx::IntSize
& aWindowSize
) override
;
335 already_AddRefed
<profiler_screenshots::DownscaleTarget
> CreateDownscaleTarget(
336 const gfx::IntSize
& aSize
) override
;
337 already_AddRefed
<profiler_screenshots::AsyncReadbackBuffer
>
338 CreateAsyncReadbackBuffer(const gfx::IntSize
& aSize
) override
;
341 Compositor
* mCompositor
;
344 class RenderSourceLMC
: public profiler_screenshots::RenderSource
{
346 explicit RenderSourceLMC(CompositingRenderTarget
* aRT
)
347 : RenderSource(aRT
->GetSize()), mRT(aRT
) {}
349 const auto& RenderTarget() { return mRT
; }
352 virtual ~RenderSourceLMC() {}
354 RefPtr
<CompositingRenderTarget
> mRT
;
357 class DownscaleTargetLMC
: public profiler_screenshots::DownscaleTarget
{
359 explicit DownscaleTargetLMC(CompositingRenderTarget
* aRT
,
360 Compositor
* aCompositor
)
361 : profiler_screenshots::DownscaleTarget(aRT
->GetSize()),
362 mRenderSource(new RenderSourceLMC(aRT
)),
363 mCompositor(aCompositor
) {}
365 already_AddRefed
<profiler_screenshots::RenderSource
> AsRenderSource()
367 return do_AddRef(mRenderSource
);
370 bool DownscaleFrom(profiler_screenshots::RenderSource
* aSource
,
371 const IntRect
& aSourceRect
,
372 const IntRect
& aDestRect
) override
{
373 MOZ_RELEASE_ASSERT(aSourceRect
.TopLeft() == IntPoint());
374 MOZ_RELEASE_ASSERT(aDestRect
.TopLeft() == IntPoint());
375 RefPtr
<CompositingRenderTarget
> previousTarget
=
376 mCompositor
->GetCurrentRenderTarget();
378 mCompositor
->SetRenderTarget(mRenderSource
->RenderTarget());
379 bool result
= mCompositor
->BlitRenderTarget(
380 static_cast<RenderSourceLMC
*>(aSource
)->RenderTarget(),
381 aSourceRect
.Size(), aDestRect
.Size());
383 // Restore the old render target.
384 mCompositor
->SetRenderTarget(previousTarget
);
390 virtual ~DownscaleTargetLMC() {}
392 RefPtr
<RenderSourceLMC
> mRenderSource
;
393 Compositor
* mCompositor
;
396 class AsyncReadbackBufferLMC
397 : public profiler_screenshots::AsyncReadbackBuffer
{
399 AsyncReadbackBufferLMC(mozilla::layers::AsyncReadbackBuffer
* aARB
,
400 Compositor
* aCompositor
)
401 : profiler_screenshots::AsyncReadbackBuffer(aARB
->GetSize()),
403 mCompositor(aCompositor
) {}
404 void CopyFrom(profiler_screenshots::RenderSource
* aSource
) override
{
405 mCompositor
->ReadbackRenderTarget(
406 static_cast<RenderSourceLMC
*>(aSource
)->RenderTarget(), mARB
);
408 bool MapAndCopyInto(DataSourceSurface
* aSurface
,
409 const IntSize
& aReadSize
) override
{
410 return mARB
->MapAndCopyInto(aSurface
, aReadSize
);
414 virtual ~AsyncReadbackBufferLMC() {}
416 RefPtr
<mozilla::layers::AsyncReadbackBuffer
> mARB
;
417 Compositor
* mCompositor
;
420 already_AddRefed
<profiler_screenshots::RenderSource
>
421 WindowLMC::GetWindowContents(const gfx::IntSize
& aWindowSize
) {
422 RefPtr
<CompositingRenderTarget
> rt
= mCompositor
->GetWindowRenderTarget();
426 return MakeAndAddRef
<RenderSourceLMC
>(rt
);
429 already_AddRefed
<profiler_screenshots::DownscaleTarget
>
430 WindowLMC::CreateDownscaleTarget(const gfx::IntSize
& aSize
) {
431 RefPtr
<CompositingRenderTarget
> rt
=
432 mCompositor
->CreateRenderTarget(IntRect({}, aSize
), INIT_MODE_NONE
);
433 return MakeAndAddRef
<DownscaleTargetLMC
>(rt
, mCompositor
);
436 already_AddRefed
<profiler_screenshots::AsyncReadbackBuffer
>
437 WindowLMC::CreateAsyncReadbackBuffer(const gfx::IntSize
& aSize
) {
438 RefPtr
<AsyncReadbackBuffer
> carb
=
439 mCompositor
->CreateAsyncReadbackBuffer(aSize
);
443 return MakeAndAddRef
<AsyncReadbackBufferLMC
>(carb
, mCompositor
);
446 bool RenderCompositorLayersSWGL::MaybeRecordFrame(
447 layers::CompositionRecorder
& aRecorder
) {
448 WindowLMC
window(mCompositor
);
449 gfx::IntSize size
= GetBufferSize().ToUnknownSize();
450 RefPtr
<layers::profiler_screenshots::RenderSource
> snapshot
=
451 window
.GetWindowContents(size
);
456 RefPtr
<layers::profiler_screenshots::AsyncReadbackBuffer
> buffer
=
457 window
.CreateAsyncReadbackBuffer(size
);
458 buffer
->CopyFrom(snapshot
);
460 RefPtr
<layers::RecordedFrame
> frame
=
461 new RenderCompositorRecordedFrame(TimeStamp::Now(), std::move(buffer
));
462 aRecorder
.RecordFrame(frame
);
466 bool RenderCompositorLayersSWGL::MaybeGrabScreenshot(
467 const gfx::IntSize
& aWindowSize
) {
468 if (!mCompositingStarted
) {
471 WindowLMC
window(mCompositor
);
472 mProfilerScreenshotGrabber
.MaybeGrabScreenshot(window
, aWindowSize
);
476 bool RenderCompositorLayersSWGL::MaybeProcessScreenshotQueue() {
477 mProfilerScreenshotGrabber
.MaybeProcessQueue();
482 } // namespace mozilla