NativeLayerRemoteMac.mm (8893B)
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "mozilla/layers/NativeLayerRemoteMac.h" 7 8 #include <algorithm> 9 #include <utility> 10 11 #include "CFTypeRefPtr.h" 12 #include "gfxUtils.h" 13 #include "GLBlitHelper.h" 14 #ifdef XP_MACOSX 15 # include "GLContextCGL.h" 16 #else 17 # include "GLContextEAGL.h" 18 #endif 19 #include "GLContextProvider.h" 20 #include "MozFramebuffer.h" 21 #include "mozilla/gfx/Swizzle.h" 22 #include "mozilla/glean/GfxMetrics.h" 23 #include "mozilla/webrender/RenderMacIOSurfaceTextureHost.h" 24 #include "NativeLayerCA.h" 25 #include "ScopedGLHelpers.h" 26 27 namespace mozilla { 28 namespace layers { 29 30 using gfx::IntPoint; 31 using gfx::IntRect; 32 using gfx::IntRegion; 33 using gfx::IntSize; 34 using gfx::Matrix4x4; 35 36 NativeLayerRemoteMac::NativeLayerRemoteMac( 37 const IntSize& aSize, bool aIsOpaque, 38 SurfacePoolHandleCA* aSurfacePoolHandle) 39 : mIsOpaque(aIsOpaque) { 40 // We need a surface handler for this type of layer. 41 mSurfaceHandler.emplace(aSize, aSurfacePoolHandle); 42 } 43 44 NativeLayerRemoteMac::NativeLayerRemoteMac(bool aIsOpaque) 45 : mIsOpaque(aIsOpaque) {} 46 47 NativeLayerRemoteMac::NativeLayerRemoteMac(gfx::DeviceColor aColor) 48 : mColor(Some(aColor)), mIsOpaque(aColor.a >= 1.0f) {} 49 50 NativeLayerRemoteMac::~NativeLayerRemoteMac() { 51 if (mCommandQueue) { 52 mCommandQueue->AppendCommand(mozilla::layers::CommandLayerDestroyed( 53 reinterpret_cast<uint64_t>(this))); 54 } 55 } 56 57 void NativeLayerRemoteMac::AttachExternalImage( 58 wr::RenderTextureHost* aExternalImage) { 59 MOZ_ASSERT(XRE_IsGPUProcess()); 60 MOZ_ASSERT(!mSurfaceHandler); 61 62 wr::RenderMacIOSurfaceTextureHost* texture = 63 aExternalImage->AsRenderMacIOSurfaceTextureHost(); 64 MOZ_ASSERT(texture); 65 66 auto externalImage = texture->GetSurface()->GetIOSurfaceRef(); 67 mExternalImage = externalImage; 68 69 auto texSize = texture->GetSize(0); 70 mSize = texSize; 71 72 auto displayRect = IntRect(IntPoint{}, mSize); 73 bool changedDisplayRect = !mDisplayRect.IsEqualInterior(displayRect); 74 mDisplayRect = displayRect; 75 76 bool isDRM = aExternalImage->IsFromDRMSource(); 77 bool changedIsDRM = mIsDRM != isDRM; 78 mIsDRM = isDRM; 79 80 bool isHDR = false; 81 MacIOSurface* macIOSurface = texture->GetSurface(); 82 if (macIOSurface->GetYUVColorSpace() == gfx::YUVColorSpace::BT2020 && 83 StaticPrefs::gfx_color_management_hdr_video_assume_rec2020_uses_pq()) { 84 // BT2020 colorSpace is a signifier of HDR. 85 isHDR = true; 86 } 87 88 if (macIOSurface->GetColorDepth() == gfx::ColorDepth::COLOR_10) { 89 // 10-bit color is a signifier of HDR. 90 isHDR = true; 91 } 92 mIsHDR = isHDR && StaticPrefs::gfx_color_management_hdr_video(); 93 94 mDirtyLayerInfo |= changedDisplayRect; 95 mSnapshotLayer.mMutatedFrontSurface = true; 96 mSnapshotLayer.mMutatedSize |= changedDisplayRect; 97 mSnapshotLayer.mMutatedDisplayRect |= changedDisplayRect; 98 mSnapshotLayer.mMutatedIsDRM |= changedIsDRM; 99 mDirtyChangedSurface = true; 100 } 101 102 GpuFence* NativeLayerRemoteMac::GetGpuFence() { return nullptr; } 103 104 IntSize NativeLayerRemoteMac::GetSize() { 105 if (mSurfaceHandler) { 106 return mSurfaceHandler->Size(); 107 } 108 return mSize; 109 } 110 111 void NativeLayerRemoteMac::SetPosition(const IntPoint& aPosition) { 112 if (mPosition != aPosition) { 113 mDirtyLayerInfo = true; 114 mSnapshotLayer.mMutatedPosition = true; 115 mPosition = aPosition; 116 } 117 } 118 119 IntPoint NativeLayerRemoteMac::GetPosition() { return mPosition; } 120 121 void NativeLayerRemoteMac::SetTransform(const Matrix4x4& aTransform) { 122 MOZ_ASSERT(aTransform.IsRectilinear()); 123 124 if (mTransform != aTransform) { 125 mDirtyLayerInfo = true; 126 mSnapshotLayer.mMutatedTransform = true; 127 mTransform = aTransform; 128 } 129 } 130 131 void NativeLayerRemoteMac::SetSamplingFilter( 132 gfx::SamplingFilter aSamplingFilter) { 133 if (mSamplingFilter != aSamplingFilter) { 134 mDirtyLayerInfo = true; 135 mSnapshotLayer.mMutatedSamplingFilter = true; 136 mSamplingFilter = aSamplingFilter; 137 } 138 } 139 140 gfx::SamplingFilter NativeLayerRemoteMac::SamplingFilter() { 141 return mSamplingFilter; 142 } 143 144 Matrix4x4 NativeLayerRemoteMac::GetTransform() { return mTransform; } 145 146 IntRect NativeLayerRemoteMac::GetRect() { 147 IntSize size = mSize; 148 if (mSurfaceHandler) { 149 size = mSurfaceHandler->Size(); 150 } 151 return IntRect(mPosition, size); 152 } 153 154 bool NativeLayerRemoteMac::IsOpaque() { return mIsOpaque; } 155 156 void NativeLayerRemoteMac::SetClipRect(const Maybe<gfx::IntRect>& aClipRect) { 157 if (mClipRect != aClipRect) { 158 mDirtyLayerInfo = true; 159 mClipRect = aClipRect; 160 } 161 } 162 163 Maybe<gfx::IntRect> NativeLayerRemoteMac::ClipRect() { return mClipRect; } 164 165 void NativeLayerRemoteMac::SetRoundedClipRect( 166 const Maybe<gfx::RoundedRect>& aRoundedClipRect) { 167 if (mRoundedClipRect != aRoundedClipRect) { 168 mDirtyLayerInfo = true; 169 mSnapshotLayer.mMutatedRoundedClipRect = true; 170 mRoundedClipRect = aRoundedClipRect; 171 } 172 } 173 174 Maybe<gfx::RoundedRect> NativeLayerRemoteMac::RoundedClipRect() { 175 return mRoundedClipRect; 176 } 177 178 gfx::IntRect NativeLayerRemoteMac::CurrentSurfaceDisplayRect() { 179 if (mSurfaceHandler) { 180 return mSurfaceHandler->DisplayRect(); 181 } 182 return mDisplayRect; 183 } 184 185 void NativeLayerRemoteMac::SetSurfaceIsFlipped(bool aIsFlipped) { 186 if (SurfaceIsFlipped() != aIsFlipped) { 187 mDirtyLayerInfo = true; 188 mSnapshotLayer.mMutatedSurfaceIsFlipped = true; 189 if (mSurfaceHandler) { 190 mSurfaceHandler->SetSurfaceIsFlipped(aIsFlipped); 191 } else { 192 mSurfaceIsFlipped = aIsFlipped; 193 } 194 } 195 } 196 197 bool NativeLayerRemoteMac::SurfaceIsFlipped() { 198 if (mSurfaceHandler) { 199 return mSurfaceHandler->SurfaceIsFlipped(); 200 } 201 return mSurfaceIsFlipped; 202 } 203 204 RefPtr<gfx::DrawTarget> NativeLayerRemoteMac::NextSurfaceAsDrawTarget( 205 const IntRect& aDisplayRect, const IntRegion& aUpdateRegion, 206 gfx::BackendType aBackendType) { 207 MOZ_ASSERT(mSurfaceHandler); 208 return mSurfaceHandler->NextSurfaceAsDrawTarget(aDisplayRect, aUpdateRegion, 209 aBackendType); 210 } 211 212 Maybe<GLuint> NativeLayerRemoteMac::NextSurfaceAsFramebuffer( 213 const IntRect& aDisplayRect, const IntRegion& aUpdateRegion, 214 bool aNeedsDepth) { 215 MOZ_ASSERT(mSurfaceHandler); 216 return mSurfaceHandler->NextSurfaceAsFramebuffer(aDisplayRect, aUpdateRegion, 217 aNeedsDepth); 218 } 219 220 Maybe<SurfaceWithInvalidRegion> NativeLayerRemoteMac::FrontSurface() { 221 if (mSurfaceHandler) { 222 return mSurfaceHandler->FrontSurface(); 223 } 224 if (mExternalImage) { 225 return Some(SurfaceWithInvalidRegion{mExternalImage, GetRect()}); 226 } 227 return Nothing(); 228 } 229 230 void NativeLayerRemoteMac::NotifySurfaceReady() { 231 MOZ_ASSERT(mSurfaceHandler); 232 233 // When we call the surface handler NotifySurfaceReady(), we get a 234 // return value indicating if the display rect has changed. Set our 235 // dirty flag (covering all non-surface changes) if that is true. 236 bool changedDisplayRect = mSurfaceHandler->NotifySurfaceReady(); 237 mDirtyLayerInfo |= changedDisplayRect; 238 mDirtyChangedSurface = true; 239 mSnapshotLayer.mMutatedFrontSurface = true; 240 } 241 242 void NativeLayerRemoteMac::DiscardBackbuffers() { 243 MOZ_ASSERT(mSurfaceHandler); 244 mSurfaceHandler->DiscardBackbuffers(); 245 } 246 247 void NativeLayerRemoteMac::FlushDirtyLayerInfoToCommandQueue() { 248 auto ID = reinterpret_cast<uint64_t>(this); 249 250 if (mDirtyChangedSurface) { 251 IOSurfacePort surfacePort; 252 auto surfaceWithInvalidRegion = FrontSurface(); 253 if (surfaceWithInvalidRegion) { 254 surfacePort = 255 IOSurfacePort::FromSurface(surfaceWithInvalidRegion->mSurface); 256 } 257 258 mCommandQueue->AppendCommand(mozilla::layers::CommandChangedSurface( 259 ID, std::move(surfacePort), IsDRM(), IsHDR(), GetSize())); 260 mDirtyChangedSurface = false; 261 } 262 263 if (mDirtyLayerInfo) { 264 mCommandQueue->AppendCommand(mozilla::layers::CommandLayerInfo( 265 ID, GetPosition(), CurrentSurfaceDisplayRect(), ClipRect(), 266 RoundedClipRect(), GetTransform(), 267 static_cast<int8_t>(SamplingFilter()), SurfaceIsFlipped())); 268 mDirtyLayerInfo = false; 269 } 270 } 271 272 void NativeLayerRemoteMac::UpdateSnapshotLayer() { 273 CFTypeRefPtr<IOSurfaceRef> surface; 274 if (auto frontSurface = FrontSurface()) { 275 surface = frontSurface->mSurface; 276 } 277 278 IntRect rect = GetRect(); 279 IntRect displayRect = CurrentSurfaceDisplayRect(); 280 281 bool specializeVideo = false; 282 bool isVideo = false; 283 mSnapshotLayer.ApplyChanges( 284 NativeLayerCAUpdateType::All, rect.Size(), mIsOpaque, rect.TopLeft(), 285 mTransform, displayRect, mClipRect, mRoundedClipRect, mBackingScale, 286 mSurfaceIsFlipped, mSamplingFilter, specializeVideo, surface, mColor, 287 mIsDRM, isVideo); 288 } 289 290 CALayer* NativeLayerRemoteMac::CALayerForSnapshot() { 291 return mSnapshotLayer.UnderlyingCALayer(); 292 } 293 294 } // namespace layers 295 } // namespace mozilla