Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
michael@0 | 2 | * This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #include "mozilla/layers/TextureHost.h" |
michael@0 | 7 | #include "CompositableHost.h" // for CompositableHost |
michael@0 | 8 | #include "LayersLogging.h" // for AppendToString |
michael@0 | 9 | #include "gfx2DGlue.h" // for ToIntSize |
michael@0 | 10 | #include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory |
michael@0 | 11 | #include "mozilla/ipc/Shmem.h" // for Shmem |
michael@0 | 12 | #include "mozilla/layers/Compositor.h" // for Compositor |
michael@0 | 13 | #include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator |
michael@0 | 14 | #include "mozilla/layers/ImageDataSerializer.h" |
michael@0 | 15 | #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc |
michael@0 | 16 | #include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL |
michael@0 | 17 | #ifdef MOZ_X11 |
michael@0 | 18 | #include "mozilla/layers/X11TextureHost.h" |
michael@0 | 19 | #endif |
michael@0 | 20 | #include "mozilla/layers/YCbCrImageDataSerializer.h" |
michael@0 | 21 | #include "nsAString.h" |
michael@0 | 22 | #include "nsAutoPtr.h" // for nsRefPtr |
michael@0 | 23 | #include "nsPrintfCString.h" // for nsPrintfCString |
michael@0 | 24 | #include "mozilla/layers/PTextureParent.h" |
michael@0 | 25 | #include "mozilla/unused.h" |
michael@0 | 26 | #include <limits> |
michael@0 | 27 | |
michael@0 | 28 | #if 0 |
michael@0 | 29 | #define RECYCLE_LOG(...) printf_stderr(__VA_ARGS__) |
michael@0 | 30 | #else |
michael@0 | 31 | #define RECYCLE_LOG(...) do { } while (0) |
michael@0 | 32 | #endif |
michael@0 | 33 | |
michael@0 | 34 | struct nsIntPoint; |
michael@0 | 35 | |
michael@0 | 36 | namespace mozilla { |
michael@0 | 37 | namespace layers { |
michael@0 | 38 | |
michael@0 | 39 | /** |
michael@0 | 40 | * TextureParent is the host-side IPDL glue between TextureClient and TextureHost. |
michael@0 | 41 | * It is an IPDL actor just like LayerParent, CompositableParent, etc. |
michael@0 | 42 | */ |
michael@0 | 43 | class TextureParent : public PTextureParent |
michael@0 | 44 | { |
michael@0 | 45 | public: |
michael@0 | 46 | TextureParent(ISurfaceAllocator* aAllocator); |
michael@0 | 47 | |
michael@0 | 48 | ~TextureParent(); |
michael@0 | 49 | |
michael@0 | 50 | bool Init(const SurfaceDescriptor& aSharedData, |
michael@0 | 51 | const TextureFlags& aFlags); |
michael@0 | 52 | |
michael@0 | 53 | void CompositorRecycle(); |
michael@0 | 54 | virtual bool RecvClientRecycle() MOZ_OVERRIDE; |
michael@0 | 55 | |
michael@0 | 56 | virtual bool RecvRemoveTexture() MOZ_OVERRIDE; |
michael@0 | 57 | |
michael@0 | 58 | virtual bool RecvRemoveTextureSync() MOZ_OVERRIDE; |
michael@0 | 59 | |
michael@0 | 60 | TextureHost* GetTextureHost() { return mTextureHost; } |
michael@0 | 61 | |
michael@0 | 62 | void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; |
michael@0 | 63 | |
michael@0 | 64 | ISurfaceAllocator* mAllocator; |
michael@0 | 65 | RefPtr<TextureHost> mWaitForClientRecycle; |
michael@0 | 66 | RefPtr<TextureHost> mTextureHost; |
michael@0 | 67 | }; |
michael@0 | 68 | |
michael@0 | 69 | // static |
michael@0 | 70 | PTextureParent* |
michael@0 | 71 | TextureHost::CreateIPDLActor(ISurfaceAllocator* aAllocator, |
michael@0 | 72 | const SurfaceDescriptor& aSharedData, |
michael@0 | 73 | TextureFlags aFlags) |
michael@0 | 74 | { |
michael@0 | 75 | if (aSharedData.type() == SurfaceDescriptor::TSurfaceDescriptorMemory && |
michael@0 | 76 | !aAllocator->IsSameProcess()) |
michael@0 | 77 | { |
michael@0 | 78 | NS_ERROR("A client process is trying to peek at our address space using a MemoryTexture!"); |
michael@0 | 79 | return nullptr; |
michael@0 | 80 | } |
michael@0 | 81 | TextureParent* actor = new TextureParent(aAllocator); |
michael@0 | 82 | if (!actor->Init(aSharedData, aFlags)) { |
michael@0 | 83 | delete actor; |
michael@0 | 84 | return nullptr; |
michael@0 | 85 | } |
michael@0 | 86 | return actor; |
michael@0 | 87 | } |
michael@0 | 88 | |
michael@0 | 89 | // static |
michael@0 | 90 | bool |
michael@0 | 91 | TextureHost::DestroyIPDLActor(PTextureParent* actor) |
michael@0 | 92 | { |
michael@0 | 93 | delete actor; |
michael@0 | 94 | return true; |
michael@0 | 95 | } |
michael@0 | 96 | |
michael@0 | 97 | // static |
michael@0 | 98 | bool |
michael@0 | 99 | TextureHost::SendDeleteIPDLActor(PTextureParent* actor) |
michael@0 | 100 | { |
michael@0 | 101 | return PTextureParent::Send__delete__(actor); |
michael@0 | 102 | } |
michael@0 | 103 | |
michael@0 | 104 | // static |
michael@0 | 105 | TextureHost* |
michael@0 | 106 | TextureHost::AsTextureHost(PTextureParent* actor) |
michael@0 | 107 | { |
michael@0 | 108 | return actor? static_cast<TextureParent*>(actor)->mTextureHost : nullptr; |
michael@0 | 109 | } |
michael@0 | 110 | |
michael@0 | 111 | PTextureParent* |
michael@0 | 112 | TextureHost::GetIPDLActor() |
michael@0 | 113 | { |
michael@0 | 114 | return mActor; |
michael@0 | 115 | } |
michael@0 | 116 | |
michael@0 | 117 | // implemented in TextureHostOGL.cpp |
michael@0 | 118 | TemporaryRef<TextureHost> CreateTextureHostOGL(const SurfaceDescriptor& aDesc, |
michael@0 | 119 | ISurfaceAllocator* aDeallocator, |
michael@0 | 120 | TextureFlags aFlags); |
michael@0 | 121 | |
michael@0 | 122 | // implemented in TextureHostBasic.cpp |
michael@0 | 123 | TemporaryRef<TextureHost> CreateTextureHostBasic(const SurfaceDescriptor& aDesc, |
michael@0 | 124 | ISurfaceAllocator* aDeallocator, |
michael@0 | 125 | TextureFlags aFlags); |
michael@0 | 126 | |
michael@0 | 127 | // implemented in TextureD3D11.cpp |
michael@0 | 128 | TemporaryRef<TextureHost> CreateTextureHostD3D11(const SurfaceDescriptor& aDesc, |
michael@0 | 129 | ISurfaceAllocator* aDeallocator, |
michael@0 | 130 | TextureFlags aFlags); |
michael@0 | 131 | |
michael@0 | 132 | // implemented in TextureD3D9.cpp |
michael@0 | 133 | TemporaryRef<TextureHost> CreateTextureHostD3D9(const SurfaceDescriptor& aDesc, |
michael@0 | 134 | ISurfaceAllocator* aDeallocator, |
michael@0 | 135 | TextureFlags aFlags); |
michael@0 | 136 | |
michael@0 | 137 | // static |
michael@0 | 138 | TemporaryRef<TextureHost> |
michael@0 | 139 | TextureHost::Create(const SurfaceDescriptor& aDesc, |
michael@0 | 140 | ISurfaceAllocator* aDeallocator, |
michael@0 | 141 | TextureFlags aFlags) |
michael@0 | 142 | { |
michael@0 | 143 | switch (aDesc.type()) { |
michael@0 | 144 | case SurfaceDescriptor::TSurfaceDescriptorShmem: |
michael@0 | 145 | case SurfaceDescriptor::TSurfaceDescriptorMemory: |
michael@0 | 146 | return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags); |
michael@0 | 147 | case SurfaceDescriptor::TSharedTextureDescriptor: |
michael@0 | 148 | case SurfaceDescriptor::TNewSurfaceDescriptorGralloc: |
michael@0 | 149 | case SurfaceDescriptor::TSurfaceStreamDescriptor: |
michael@0 | 150 | return CreateTextureHostOGL(aDesc, aDeallocator, aFlags); |
michael@0 | 151 | case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: |
michael@0 | 152 | if (Compositor::GetBackend() == LayersBackend::LAYERS_OPENGL) { |
michael@0 | 153 | return CreateTextureHostOGL(aDesc, aDeallocator, aFlags); |
michael@0 | 154 | } else { |
michael@0 | 155 | return CreateTextureHostBasic(aDesc, aDeallocator, aFlags); |
michael@0 | 156 | } |
michael@0 | 157 | #ifdef MOZ_X11 |
michael@0 | 158 | case SurfaceDescriptor::TSurfaceDescriptorX11: { |
michael@0 | 159 | const SurfaceDescriptorX11& desc = aDesc.get_SurfaceDescriptorX11(); |
michael@0 | 160 | RefPtr<TextureHost> result = new X11TextureHost(aFlags, desc); |
michael@0 | 161 | return result; |
michael@0 | 162 | } |
michael@0 | 163 | #endif |
michael@0 | 164 | #ifdef XP_WIN |
michael@0 | 165 | case SurfaceDescriptor::TSurfaceDescriptorD3D9: |
michael@0 | 166 | case SurfaceDescriptor::TSurfaceDescriptorDIB: |
michael@0 | 167 | return CreateTextureHostD3D9(aDesc, aDeallocator, aFlags); |
michael@0 | 168 | case SurfaceDescriptor::TSurfaceDescriptorD3D10: |
michael@0 | 169 | if (Compositor::GetBackend() == LayersBackend::LAYERS_D3D9) { |
michael@0 | 170 | return CreateTextureHostD3D9(aDesc, aDeallocator, aFlags); |
michael@0 | 171 | } else { |
michael@0 | 172 | return CreateTextureHostD3D11(aDesc, aDeallocator, aFlags); |
michael@0 | 173 | } |
michael@0 | 174 | #endif |
michael@0 | 175 | default: |
michael@0 | 176 | MOZ_CRASH("Unsupported Surface type"); |
michael@0 | 177 | } |
michael@0 | 178 | } |
michael@0 | 179 | |
michael@0 | 180 | TemporaryRef<TextureHost> |
michael@0 | 181 | CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc, |
michael@0 | 182 | ISurfaceAllocator* aDeallocator, |
michael@0 | 183 | TextureFlags aFlags) |
michael@0 | 184 | { |
michael@0 | 185 | RefPtr<TextureHost> result; |
michael@0 | 186 | switch (aDesc.type()) { |
michael@0 | 187 | case SurfaceDescriptor::TSurfaceDescriptorShmem: { |
michael@0 | 188 | const SurfaceDescriptorShmem& descriptor = aDesc.get_SurfaceDescriptorShmem(); |
michael@0 | 189 | result = new ShmemTextureHost(descriptor.data(), |
michael@0 | 190 | descriptor.format(), |
michael@0 | 191 | aDeallocator, |
michael@0 | 192 | aFlags); |
michael@0 | 193 | break; |
michael@0 | 194 | } |
michael@0 | 195 | case SurfaceDescriptor::TSurfaceDescriptorMemory: { |
michael@0 | 196 | const SurfaceDescriptorMemory& descriptor = aDesc.get_SurfaceDescriptorMemory(); |
michael@0 | 197 | result = new MemoryTextureHost(reinterpret_cast<uint8_t*>(descriptor.data()), |
michael@0 | 198 | descriptor.format(), |
michael@0 | 199 | aFlags); |
michael@0 | 200 | break; |
michael@0 | 201 | } |
michael@0 | 202 | default: { |
michael@0 | 203 | NS_WARNING("No backend independent TextureHost for this descriptor type"); |
michael@0 | 204 | } |
michael@0 | 205 | } |
michael@0 | 206 | return result; |
michael@0 | 207 | } |
michael@0 | 208 | |
michael@0 | 209 | void |
michael@0 | 210 | TextureHost::CompositorRecycle() |
michael@0 | 211 | { |
michael@0 | 212 | if (!mActor) { |
michael@0 | 213 | return; |
michael@0 | 214 | } |
michael@0 | 215 | static_cast<TextureParent*>(mActor)->CompositorRecycle(); |
michael@0 | 216 | } |
michael@0 | 217 | |
michael@0 | 218 | void |
michael@0 | 219 | TextureHost::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) |
michael@0 | 220 | { |
michael@0 | 221 | mCompositableBackendData = aBackendData; |
michael@0 | 222 | } |
michael@0 | 223 | |
michael@0 | 224 | |
michael@0 | 225 | TextureHost::TextureHost(TextureFlags aFlags) |
michael@0 | 226 | : mActor(nullptr) |
michael@0 | 227 | , mFlags(aFlags) |
michael@0 | 228 | {} |
michael@0 | 229 | |
michael@0 | 230 | TextureHost::~TextureHost() |
michael@0 | 231 | { |
michael@0 | 232 | } |
michael@0 | 233 | |
michael@0 | 234 | void TextureHost::Finalize() |
michael@0 | 235 | { |
michael@0 | 236 | if (!(GetFlags() & TEXTURE_DEALLOCATE_CLIENT)) { |
michael@0 | 237 | DeallocateSharedData(); |
michael@0 | 238 | DeallocateDeviceData(); |
michael@0 | 239 | } |
michael@0 | 240 | } |
michael@0 | 241 | |
michael@0 | 242 | void |
michael@0 | 243 | TextureHost::PrintInfo(nsACString& aTo, const char* aPrefix) |
michael@0 | 244 | { |
michael@0 | 245 | aTo += aPrefix; |
michael@0 | 246 | aTo += nsPrintfCString("%s (0x%p)", Name(), this); |
michael@0 | 247 | // Note: the TextureHost needs to be locked before it is safe to call |
michael@0 | 248 | // GetSize() and GetFormat() on it. |
michael@0 | 249 | if (Lock()) { |
michael@0 | 250 | AppendToString(aTo, GetSize(), " [size=", "]"); |
michael@0 | 251 | AppendToString(aTo, GetFormat(), " [format=", "]"); |
michael@0 | 252 | Unlock(); |
michael@0 | 253 | } |
michael@0 | 254 | AppendToString(aTo, mFlags, " [flags=", "]"); |
michael@0 | 255 | } |
michael@0 | 256 | |
michael@0 | 257 | void |
michael@0 | 258 | TextureSource::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) |
michael@0 | 259 | { |
michael@0 | 260 | mCompositableBackendData = aBackendData; |
michael@0 | 261 | } |
michael@0 | 262 | |
michael@0 | 263 | TextureSource::TextureSource() |
michael@0 | 264 | { |
michael@0 | 265 | MOZ_COUNT_CTOR(TextureSource); |
michael@0 | 266 | } |
michael@0 | 267 | TextureSource::~TextureSource() |
michael@0 | 268 | { |
michael@0 | 269 | MOZ_COUNT_DTOR(TextureSource); |
michael@0 | 270 | } |
michael@0 | 271 | |
michael@0 | 272 | BufferTextureHost::BufferTextureHost(gfx::SurfaceFormat aFormat, |
michael@0 | 273 | TextureFlags aFlags) |
michael@0 | 274 | : TextureHost(aFlags) |
michael@0 | 275 | , mCompositor(nullptr) |
michael@0 | 276 | , mFormat(aFormat) |
michael@0 | 277 | , mUpdateSerial(1) |
michael@0 | 278 | , mLocked(false) |
michael@0 | 279 | , mPartialUpdate(false) |
michael@0 | 280 | {} |
michael@0 | 281 | |
michael@0 | 282 | BufferTextureHost::~BufferTextureHost() |
michael@0 | 283 | {} |
michael@0 | 284 | |
michael@0 | 285 | void |
michael@0 | 286 | BufferTextureHost::Updated(const nsIntRegion* aRegion) |
michael@0 | 287 | { |
michael@0 | 288 | ++mUpdateSerial; |
michael@0 | 289 | if (aRegion) { |
michael@0 | 290 | mPartialUpdate = true; |
michael@0 | 291 | mMaybeUpdatedRegion = *aRegion; |
michael@0 | 292 | } else { |
michael@0 | 293 | mPartialUpdate = false; |
michael@0 | 294 | } |
michael@0 | 295 | if (GetFlags() & TEXTURE_IMMEDIATE_UPLOAD) { |
michael@0 | 296 | DebugOnly<bool> result = MaybeUpload(mPartialUpdate ? &mMaybeUpdatedRegion : nullptr); |
michael@0 | 297 | NS_WARN_IF_FALSE(result, "Failed to upload a texture"); |
michael@0 | 298 | } |
michael@0 | 299 | } |
michael@0 | 300 | |
michael@0 | 301 | void |
michael@0 | 302 | BufferTextureHost::SetCompositor(Compositor* aCompositor) |
michael@0 | 303 | { |
michael@0 | 304 | if (mCompositor == aCompositor) { |
michael@0 | 305 | return; |
michael@0 | 306 | } |
michael@0 | 307 | RefPtr<NewTextureSource> it = mFirstSource; |
michael@0 | 308 | while (it) { |
michael@0 | 309 | it->SetCompositor(aCompositor); |
michael@0 | 310 | it = it->GetNextSibling(); |
michael@0 | 311 | } |
michael@0 | 312 | mCompositor = aCompositor; |
michael@0 | 313 | } |
michael@0 | 314 | |
michael@0 | 315 | void |
michael@0 | 316 | BufferTextureHost::DeallocateDeviceData() |
michael@0 | 317 | { |
michael@0 | 318 | RefPtr<NewTextureSource> it = mFirstSource; |
michael@0 | 319 | while (it) { |
michael@0 | 320 | it->DeallocateDeviceData(); |
michael@0 | 321 | it = it->GetNextSibling(); |
michael@0 | 322 | } |
michael@0 | 323 | } |
michael@0 | 324 | |
michael@0 | 325 | bool |
michael@0 | 326 | BufferTextureHost::Lock() |
michael@0 | 327 | { |
michael@0 | 328 | mLocked = true; |
michael@0 | 329 | return true; |
michael@0 | 330 | } |
michael@0 | 331 | |
michael@0 | 332 | void |
michael@0 | 333 | BufferTextureHost::Unlock() |
michael@0 | 334 | { |
michael@0 | 335 | mLocked = false; |
michael@0 | 336 | } |
michael@0 | 337 | |
michael@0 | 338 | NewTextureSource* |
michael@0 | 339 | BufferTextureHost::GetTextureSources() |
michael@0 | 340 | { |
michael@0 | 341 | MOZ_ASSERT(mLocked, "should never be called while not locked"); |
michael@0 | 342 | if (!MaybeUpload(mPartialUpdate ? &mMaybeUpdatedRegion : nullptr)) { |
michael@0 | 343 | return nullptr; |
michael@0 | 344 | } |
michael@0 | 345 | return mFirstSource; |
michael@0 | 346 | } |
michael@0 | 347 | |
michael@0 | 348 | gfx::SurfaceFormat |
michael@0 | 349 | BufferTextureHost::GetFormat() const |
michael@0 | 350 | { |
michael@0 | 351 | // mFormat is the format of the data that we share with the content process. |
michael@0 | 352 | // GetFormat, on the other hand, expects the format that we present to the |
michael@0 | 353 | // Compositor (it is used to choose the effect type). |
michael@0 | 354 | // if the compositor does not support YCbCr effects, we give it a RGBX texture |
michael@0 | 355 | // instead (see BufferTextureHost::Upload) |
michael@0 | 356 | if (mFormat == gfx::SurfaceFormat::YUV && |
michael@0 | 357 | mCompositor && |
michael@0 | 358 | !mCompositor->SupportsEffect(EFFECT_YCBCR)) { |
michael@0 | 359 | return gfx::SurfaceFormat::R8G8B8X8; |
michael@0 | 360 | } |
michael@0 | 361 | return mFormat; |
michael@0 | 362 | } |
michael@0 | 363 | |
michael@0 | 364 | bool |
michael@0 | 365 | BufferTextureHost::MaybeUpload(nsIntRegion *aRegion) |
michael@0 | 366 | { |
michael@0 | 367 | if (mFirstSource && mFirstSource->GetUpdateSerial() == mUpdateSerial) { |
michael@0 | 368 | return true; |
michael@0 | 369 | } |
michael@0 | 370 | if (!Upload(aRegion)) { |
michael@0 | 371 | return false; |
michael@0 | 372 | } |
michael@0 | 373 | mFirstSource->SetUpdateSerial(mUpdateSerial); |
michael@0 | 374 | return true; |
michael@0 | 375 | } |
michael@0 | 376 | |
michael@0 | 377 | bool |
michael@0 | 378 | BufferTextureHost::Upload(nsIntRegion *aRegion) |
michael@0 | 379 | { |
michael@0 | 380 | if (!GetBuffer()) { |
michael@0 | 381 | // We don't have a buffer; a possible cause is that the IPDL actor |
michael@0 | 382 | // is already dead. This inevitably happens as IPDL actors can die |
michael@0 | 383 | // at any time, so we want to silently return in this case. |
michael@0 | 384 | return false; |
michael@0 | 385 | } |
michael@0 | 386 | if (!mCompositor) { |
michael@0 | 387 | NS_WARNING("Tried to upload without a compositor. Skipping texture upload..."); |
michael@0 | 388 | // If we are in this situation it means we should have called SetCompositor |
michael@0 | 389 | // earlier. It is conceivable that on certain rare conditions with async-video |
michael@0 | 390 | // we may end up here for the first frame, but this should not happen repeatedly. |
michael@0 | 391 | return false; |
michael@0 | 392 | } |
michael@0 | 393 | if (mFormat == gfx::SurfaceFormat::UNKNOWN) { |
michael@0 | 394 | NS_WARNING("BufferTextureHost: unsupported format!"); |
michael@0 | 395 | return false; |
michael@0 | 396 | } else if (mFormat == gfx::SurfaceFormat::YUV) { |
michael@0 | 397 | YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize()); |
michael@0 | 398 | MOZ_ASSERT(yuvDeserializer.IsValid()); |
michael@0 | 399 | |
michael@0 | 400 | if (!mCompositor->SupportsEffect(EFFECT_YCBCR)) { |
michael@0 | 401 | RefPtr<gfx::DataSourceSurface> surf = yuvDeserializer.ToDataSourceSurface(); |
michael@0 | 402 | if (!mFirstSource) { |
michael@0 | 403 | mFirstSource = mCompositor->CreateDataTextureSource(mFlags); |
michael@0 | 404 | } |
michael@0 | 405 | mFirstSource->Update(surf, aRegion); |
michael@0 | 406 | return true; |
michael@0 | 407 | } |
michael@0 | 408 | |
michael@0 | 409 | RefPtr<DataTextureSource> srcY; |
michael@0 | 410 | RefPtr<DataTextureSource> srcU; |
michael@0 | 411 | RefPtr<DataTextureSource> srcV; |
michael@0 | 412 | if (!mFirstSource) { |
michael@0 | 413 | // We don't support BigImages for YCbCr compositing. |
michael@0 | 414 | srcY = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE); |
michael@0 | 415 | srcU = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE); |
michael@0 | 416 | srcV = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE); |
michael@0 | 417 | mFirstSource = srcY; |
michael@0 | 418 | srcY->SetNextSibling(srcU); |
michael@0 | 419 | srcU->SetNextSibling(srcV); |
michael@0 | 420 | } else { |
michael@0 | 421 | // mFormat never changes so if this was created as a YCbCr host and already |
michael@0 | 422 | // contains a source it should already have 3 sources. |
michael@0 | 423 | // BufferTextureHost only uses DataTextureSources so it is safe to assume |
michael@0 | 424 | // all 3 sources are DataTextureSource. |
michael@0 | 425 | MOZ_ASSERT(mFirstSource->GetNextSibling()); |
michael@0 | 426 | MOZ_ASSERT(mFirstSource->GetNextSibling()->GetNextSibling()); |
michael@0 | 427 | srcY = mFirstSource; |
michael@0 | 428 | srcU = mFirstSource->GetNextSibling()->AsDataTextureSource(); |
michael@0 | 429 | srcV = mFirstSource->GetNextSibling()->GetNextSibling()->AsDataTextureSource(); |
michael@0 | 430 | } |
michael@0 | 431 | |
michael@0 | 432 | |
michael@0 | 433 | RefPtr<gfx::DataSourceSurface> tempY = |
michael@0 | 434 | gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetYData(), |
michael@0 | 435 | yuvDeserializer.GetYStride(), |
michael@0 | 436 | yuvDeserializer.GetYSize(), |
michael@0 | 437 | gfx::SurfaceFormat::A8); |
michael@0 | 438 | RefPtr<gfx::DataSourceSurface> tempCb = |
michael@0 | 439 | gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCbData(), |
michael@0 | 440 | yuvDeserializer.GetCbCrStride(), |
michael@0 | 441 | yuvDeserializer.GetCbCrSize(), |
michael@0 | 442 | gfx::SurfaceFormat::A8); |
michael@0 | 443 | RefPtr<gfx::DataSourceSurface> tempCr = |
michael@0 | 444 | gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCrData(), |
michael@0 | 445 | yuvDeserializer.GetCbCrStride(), |
michael@0 | 446 | yuvDeserializer.GetCbCrSize(), |
michael@0 | 447 | gfx::SurfaceFormat::A8); |
michael@0 | 448 | // We don't support partial updates for Y U V textures |
michael@0 | 449 | NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures"); |
michael@0 | 450 | if (!srcY->Update(tempY) || |
michael@0 | 451 | !srcU->Update(tempCb) || |
michael@0 | 452 | !srcV->Update(tempCr)) { |
michael@0 | 453 | NS_WARNING("failed to update the DataTextureSource"); |
michael@0 | 454 | return false; |
michael@0 | 455 | } |
michael@0 | 456 | } else { |
michael@0 | 457 | // non-YCbCr case |
michael@0 | 458 | if (!mFirstSource) { |
michael@0 | 459 | mFirstSource = mCompositor->CreateDataTextureSource(); |
michael@0 | 460 | } |
michael@0 | 461 | ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize()); |
michael@0 | 462 | if (!deserializer.IsValid()) { |
michael@0 | 463 | NS_ERROR("Failed to deserialize image!"); |
michael@0 | 464 | return false; |
michael@0 | 465 | } |
michael@0 | 466 | |
michael@0 | 467 | RefPtr<gfx::DataSourceSurface> surf = deserializer.GetAsSurface(); |
michael@0 | 468 | if (!surf) { |
michael@0 | 469 | return false; |
michael@0 | 470 | } |
michael@0 | 471 | |
michael@0 | 472 | if (!mFirstSource->Update(surf.get(), aRegion)) { |
michael@0 | 473 | NS_WARNING("failed to update the DataTextureSource"); |
michael@0 | 474 | return false; |
michael@0 | 475 | } |
michael@0 | 476 | } |
michael@0 | 477 | return true; |
michael@0 | 478 | } |
michael@0 | 479 | |
michael@0 | 480 | TemporaryRef<gfx::DataSourceSurface> |
michael@0 | 481 | BufferTextureHost::GetAsSurface() |
michael@0 | 482 | { |
michael@0 | 483 | RefPtr<gfx::DataSourceSurface> result; |
michael@0 | 484 | if (mFormat == gfx::SurfaceFormat::UNKNOWN) { |
michael@0 | 485 | NS_WARNING("BufferTextureHost: unsupported format!"); |
michael@0 | 486 | return nullptr; |
michael@0 | 487 | } else if (mFormat == gfx::SurfaceFormat::YUV) { |
michael@0 | 488 | YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize()); |
michael@0 | 489 | if (!yuvDeserializer.IsValid()) { |
michael@0 | 490 | return nullptr; |
michael@0 | 491 | } |
michael@0 | 492 | result = yuvDeserializer.ToDataSourceSurface(); |
michael@0 | 493 | } else { |
michael@0 | 494 | ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize()); |
michael@0 | 495 | if (!deserializer.IsValid()) { |
michael@0 | 496 | NS_ERROR("Failed to deserialize image!"); |
michael@0 | 497 | return nullptr; |
michael@0 | 498 | } |
michael@0 | 499 | result = deserializer.GetAsSurface(); |
michael@0 | 500 | } |
michael@0 | 501 | return result.forget(); |
michael@0 | 502 | } |
michael@0 | 503 | |
michael@0 | 504 | ShmemTextureHost::ShmemTextureHost(const ipc::Shmem& aShmem, |
michael@0 | 505 | gfx::SurfaceFormat aFormat, |
michael@0 | 506 | ISurfaceAllocator* aDeallocator, |
michael@0 | 507 | TextureFlags aFlags) |
michael@0 | 508 | : BufferTextureHost(aFormat, aFlags) |
michael@0 | 509 | , mShmem(new ipc::Shmem(aShmem)) |
michael@0 | 510 | , mDeallocator(aDeallocator) |
michael@0 | 511 | { |
michael@0 | 512 | MOZ_COUNT_CTOR(ShmemTextureHost); |
michael@0 | 513 | } |
michael@0 | 514 | |
michael@0 | 515 | ShmemTextureHost::~ShmemTextureHost() |
michael@0 | 516 | { |
michael@0 | 517 | DeallocateDeviceData(); |
michael@0 | 518 | delete mShmem; |
michael@0 | 519 | MOZ_COUNT_DTOR(ShmemTextureHost); |
michael@0 | 520 | } |
michael@0 | 521 | |
michael@0 | 522 | void |
michael@0 | 523 | ShmemTextureHost::DeallocateSharedData() |
michael@0 | 524 | { |
michael@0 | 525 | if (mShmem) { |
michael@0 | 526 | MOZ_ASSERT(mDeallocator, |
michael@0 | 527 | "Shared memory would leak without a ISurfaceAllocator"); |
michael@0 | 528 | mDeallocator->DeallocShmem(*mShmem); |
michael@0 | 529 | delete mShmem; |
michael@0 | 530 | mShmem = nullptr; |
michael@0 | 531 | } |
michael@0 | 532 | } |
michael@0 | 533 | |
michael@0 | 534 | void |
michael@0 | 535 | ShmemTextureHost::ForgetSharedData() |
michael@0 | 536 | { |
michael@0 | 537 | if (mShmem) { |
michael@0 | 538 | delete mShmem; |
michael@0 | 539 | mShmem = nullptr; |
michael@0 | 540 | } |
michael@0 | 541 | } |
michael@0 | 542 | |
michael@0 | 543 | void |
michael@0 | 544 | ShmemTextureHost::OnShutdown() |
michael@0 | 545 | { |
michael@0 | 546 | delete mShmem; |
michael@0 | 547 | mShmem = nullptr; |
michael@0 | 548 | } |
michael@0 | 549 | |
michael@0 | 550 | uint8_t* ShmemTextureHost::GetBuffer() |
michael@0 | 551 | { |
michael@0 | 552 | return mShmem ? mShmem->get<uint8_t>() : nullptr; |
michael@0 | 553 | } |
michael@0 | 554 | |
michael@0 | 555 | size_t ShmemTextureHost::GetBufferSize() |
michael@0 | 556 | { |
michael@0 | 557 | return mShmem ? mShmem->Size<uint8_t>() : 0; |
michael@0 | 558 | } |
michael@0 | 559 | |
michael@0 | 560 | MemoryTextureHost::MemoryTextureHost(uint8_t* aBuffer, |
michael@0 | 561 | gfx::SurfaceFormat aFormat, |
michael@0 | 562 | TextureFlags aFlags) |
michael@0 | 563 | : BufferTextureHost(aFormat, aFlags) |
michael@0 | 564 | , mBuffer(aBuffer) |
michael@0 | 565 | { |
michael@0 | 566 | MOZ_COUNT_CTOR(MemoryTextureHost); |
michael@0 | 567 | } |
michael@0 | 568 | |
michael@0 | 569 | MemoryTextureHost::~MemoryTextureHost() |
michael@0 | 570 | { |
michael@0 | 571 | DeallocateDeviceData(); |
michael@0 | 572 | NS_ASSERTION(!mBuffer || (mFlags & TEXTURE_DEALLOCATE_CLIENT), |
michael@0 | 573 | "Leaking our buffer"); |
michael@0 | 574 | MOZ_COUNT_DTOR(MemoryTextureHost); |
michael@0 | 575 | } |
michael@0 | 576 | |
michael@0 | 577 | void |
michael@0 | 578 | MemoryTextureHost::DeallocateSharedData() |
michael@0 | 579 | { |
michael@0 | 580 | if (mBuffer) { |
michael@0 | 581 | GfxMemoryImageReporter::WillFree(mBuffer); |
michael@0 | 582 | } |
michael@0 | 583 | delete[] mBuffer; |
michael@0 | 584 | mBuffer = nullptr; |
michael@0 | 585 | } |
michael@0 | 586 | |
michael@0 | 587 | void |
michael@0 | 588 | MemoryTextureHost::ForgetSharedData() |
michael@0 | 589 | { |
michael@0 | 590 | mBuffer = nullptr; |
michael@0 | 591 | } |
michael@0 | 592 | |
michael@0 | 593 | uint8_t* MemoryTextureHost::GetBuffer() |
michael@0 | 594 | { |
michael@0 | 595 | return mBuffer; |
michael@0 | 596 | } |
michael@0 | 597 | |
michael@0 | 598 | size_t MemoryTextureHost::GetBufferSize() |
michael@0 | 599 | { |
michael@0 | 600 | // MemoryTextureHost just trusts that the buffer size is large enough to read |
michael@0 | 601 | // anything we need to. That's because MemoryTextureHost has to trust the buffer |
michael@0 | 602 | // pointer anyway, so the security model here is just that MemoryTexture's |
michael@0 | 603 | // are restricted to same-process clients. |
michael@0 | 604 | return std::numeric_limits<size_t>::max(); |
michael@0 | 605 | } |
michael@0 | 606 | |
michael@0 | 607 | TextureParent::TextureParent(ISurfaceAllocator* aAllocator) |
michael@0 | 608 | : mAllocator(aAllocator) |
michael@0 | 609 | { |
michael@0 | 610 | MOZ_COUNT_CTOR(TextureParent); |
michael@0 | 611 | } |
michael@0 | 612 | |
michael@0 | 613 | TextureParent::~TextureParent() |
michael@0 | 614 | { |
michael@0 | 615 | MOZ_COUNT_DTOR(TextureParent); |
michael@0 | 616 | if (mTextureHost) { |
michael@0 | 617 | mTextureHost->ClearRecycleCallback(); |
michael@0 | 618 | } |
michael@0 | 619 | } |
michael@0 | 620 | |
michael@0 | 621 | static void RecycleCallback(TextureHost* textureHost, void* aClosure) { |
michael@0 | 622 | TextureParent* tp = reinterpret_cast<TextureParent*>(aClosure); |
michael@0 | 623 | tp->CompositorRecycle(); |
michael@0 | 624 | } |
michael@0 | 625 | |
michael@0 | 626 | void |
michael@0 | 627 | TextureParent::CompositorRecycle() |
michael@0 | 628 | { |
michael@0 | 629 | mTextureHost->ClearRecycleCallback(); |
michael@0 | 630 | |
michael@0 | 631 | MaybeFenceHandle handle = null_t(); |
michael@0 | 632 | #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 |
michael@0 | 633 | if (mTextureHost) { |
michael@0 | 634 | TextureHostOGL* hostOGL = mTextureHost->AsHostOGL(); |
michael@0 | 635 | android::sp<android::Fence> fence = hostOGL->GetAndResetReleaseFence(); |
michael@0 | 636 | if (fence.get() && fence->isValid()) { |
michael@0 | 637 | handle = FenceHandle(fence); |
michael@0 | 638 | // HWC might not provide Fence. |
michael@0 | 639 | // In this case, HWC implicitly handles buffer's fence. |
michael@0 | 640 | } |
michael@0 | 641 | } |
michael@0 | 642 | #endif |
michael@0 | 643 | mozilla::unused << SendCompositorRecycle(handle); |
michael@0 | 644 | |
michael@0 | 645 | // Don't forget to prepare for the next reycle |
michael@0 | 646 | // if TextureClient request it. |
michael@0 | 647 | if (mTextureHost->GetFlags() & TEXTURE_RECYCLE) { |
michael@0 | 648 | mWaitForClientRecycle = mTextureHost; |
michael@0 | 649 | } |
michael@0 | 650 | } |
michael@0 | 651 | |
michael@0 | 652 | bool |
michael@0 | 653 | TextureParent::RecvClientRecycle() |
michael@0 | 654 | { |
michael@0 | 655 | // This will allow the RecycleCallback to be called once the compositor |
michael@0 | 656 | // releases any external references to TextureHost. |
michael@0 | 657 | mTextureHost->SetRecycleCallback(RecycleCallback, this); |
michael@0 | 658 | if (!mWaitForClientRecycle) { |
michael@0 | 659 | RECYCLE_LOG("Not a recycable tile"); |
michael@0 | 660 | } |
michael@0 | 661 | mWaitForClientRecycle = nullptr; |
michael@0 | 662 | return true; |
michael@0 | 663 | } |
michael@0 | 664 | |
michael@0 | 665 | bool |
michael@0 | 666 | TextureParent::Init(const SurfaceDescriptor& aSharedData, |
michael@0 | 667 | const TextureFlags& aFlags) |
michael@0 | 668 | { |
michael@0 | 669 | mTextureHost = TextureHost::Create(aSharedData, |
michael@0 | 670 | mAllocator, |
michael@0 | 671 | aFlags); |
michael@0 | 672 | if (mTextureHost) { |
michael@0 | 673 | mTextureHost->mActor = this; |
michael@0 | 674 | if (aFlags & TEXTURE_RECYCLE) { |
michael@0 | 675 | mWaitForClientRecycle = mTextureHost; |
michael@0 | 676 | RECYCLE_LOG("Setup recycling for tile %p\n", this); |
michael@0 | 677 | } |
michael@0 | 678 | } |
michael@0 | 679 | |
michael@0 | 680 | return !!mTextureHost; |
michael@0 | 681 | } |
michael@0 | 682 | |
michael@0 | 683 | bool |
michael@0 | 684 | TextureParent::RecvRemoveTexture() |
michael@0 | 685 | { |
michael@0 | 686 | return PTextureParent::Send__delete__(this); |
michael@0 | 687 | } |
michael@0 | 688 | |
michael@0 | 689 | bool |
michael@0 | 690 | TextureParent::RecvRemoveTextureSync() |
michael@0 | 691 | { |
michael@0 | 692 | // we don't need to send a reply in the synchronous case since the child side |
michael@0 | 693 | // has the guarantee that this message has been handled synchronously. |
michael@0 | 694 | return PTextureParent::Send__delete__(this); |
michael@0 | 695 | } |
michael@0 | 696 | |
michael@0 | 697 | void |
michael@0 | 698 | TextureParent::ActorDestroy(ActorDestroyReason why) |
michael@0 | 699 | { |
michael@0 | 700 | if (!mTextureHost) { |
michael@0 | 701 | return; |
michael@0 | 702 | } |
michael@0 | 703 | |
michael@0 | 704 | switch (why) { |
michael@0 | 705 | case AncestorDeletion: |
michael@0 | 706 | case Deletion: |
michael@0 | 707 | case NormalShutdown: |
michael@0 | 708 | case AbnormalShutdown: |
michael@0 | 709 | break; |
michael@0 | 710 | case FailedConstructor: |
michael@0 | 711 | NS_RUNTIMEABORT("FailedConstructor isn't possible in PTexture"); |
michael@0 | 712 | } |
michael@0 | 713 | |
michael@0 | 714 | if (mTextureHost->GetFlags() & TEXTURE_RECYCLE) { |
michael@0 | 715 | RECYCLE_LOG("clear recycling for tile %p\n", this); |
michael@0 | 716 | mTextureHost->ClearRecycleCallback(); |
michael@0 | 717 | } |
michael@0 | 718 | if (mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) { |
michael@0 | 719 | mTextureHost->ForgetSharedData(); |
michael@0 | 720 | } |
michael@0 | 721 | |
michael@0 | 722 | // Clear recycle callback. |
michael@0 | 723 | mTextureHost->ClearRecycleCallback(); |
michael@0 | 724 | mWaitForClientRecycle = nullptr; |
michael@0 | 725 | |
michael@0 | 726 | mTextureHost->mActor = nullptr; |
michael@0 | 727 | mTextureHost = nullptr; |
michael@0 | 728 | } |
michael@0 | 729 | |
michael@0 | 730 | } // namespace |
michael@0 | 731 | } // namespace |