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