|
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 #ifndef MOZILLA_GFX_TEXTURECLIENT_H |
|
7 #define MOZILLA_GFX_TEXTURECLIENT_H |
|
8 |
|
9 #include <stddef.h> // for size_t |
|
10 #include <stdint.h> // for uint32_t, uint8_t, uint64_t |
|
11 #include "GLContextTypes.h" // for GLContext (ptr only), etc |
|
12 #include "GLTextureImage.h" // for TextureImage |
|
13 #include "ImageTypes.h" // for StereoMode |
|
14 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc |
|
15 #include "mozilla/Attributes.h" // for MOZ_OVERRIDE |
|
16 #include "mozilla/RefPtr.h" // for RefPtr, RefCounted |
|
17 #include "mozilla/gfx/2D.h" // for DrawTarget |
|
18 #include "mozilla/gfx/Point.h" // for IntSize |
|
19 #include "mozilla/gfx/Types.h" // for SurfaceFormat |
|
20 #include "mozilla/layers/FenceUtils.h" // for FenceHandle |
|
21 #include "mozilla/ipc/Shmem.h" // for Shmem |
|
22 #include "mozilla/layers/AtomicRefCountedWithFinalize.h" |
|
23 #include "mozilla/layers/CompositorTypes.h" // for TextureFlags, etc |
|
24 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor |
|
25 #include "mozilla/layers/PTextureChild.h" // for PTextureChild |
|
26 #include "mozilla/mozalloc.h" // for operator delete |
|
27 #include "nsAutoPtr.h" // for nsRefPtr |
|
28 #include "nsCOMPtr.h" // for already_AddRefed |
|
29 #include "nsISupportsImpl.h" // for TextureImage::AddRef, etc |
|
30 |
|
31 class gfxReusableSurfaceWrapper; |
|
32 class gfxImageSurface; |
|
33 |
|
34 namespace mozilla { |
|
35 namespace layers { |
|
36 |
|
37 class ContentClient; |
|
38 class CompositableForwarder; |
|
39 class ISurfaceAllocator; |
|
40 class CompositableClient; |
|
41 class PlanarYCbCrImage; |
|
42 class PlanarYCbCrData; |
|
43 class Image; |
|
44 class PTextureChild; |
|
45 class TextureChild; |
|
46 class BufferTextureClient; |
|
47 class TextureClient; |
|
48 |
|
49 /** |
|
50 * TextureClient is the abstraction that allows us to share data between the |
|
51 * content and the compositor side. |
|
52 */ |
|
53 |
|
54 enum TextureAllocationFlags { |
|
55 ALLOC_DEFAULT = 0, |
|
56 ALLOC_CLEAR_BUFFER = 1 |
|
57 }; |
|
58 |
|
59 /** |
|
60 * Interface for TextureClients that can be updated using YCbCr data. |
|
61 */ |
|
62 class TextureClientYCbCr |
|
63 { |
|
64 public: |
|
65 /** |
|
66 * Copy aData into this texture client. |
|
67 * |
|
68 * This must never be called on a TextureClient that is not sucessfully locked. |
|
69 */ |
|
70 virtual bool UpdateYCbCr(const PlanarYCbCrData& aData) = 0; |
|
71 |
|
72 /** |
|
73 * Allocates for a given surface size, taking into account the pixel format |
|
74 * which is part of the state of the TextureClient. |
|
75 * |
|
76 * Does not clear the surface, since we consider that the surface |
|
77 * be painted entirely with opaque content. |
|
78 */ |
|
79 virtual bool AllocateForYCbCr(gfx::IntSize aYSize, |
|
80 gfx::IntSize aCbCrSize, |
|
81 StereoMode aStereoMode) = 0; |
|
82 }; |
|
83 |
|
84 /** |
|
85 * Holds the shared data of a TextureClient, to be destroyed later. |
|
86 * |
|
87 * TextureClient's destructor initiates the destruction sequence of the |
|
88 * texture client/host pair. If the shared data is to be deallocated on the |
|
89 * host side, there is nothing to do. |
|
90 * On the other hand, if the client data must be deallocated on the client |
|
91 * side, the CompositableClient will ask the TextureClient to drop its shared |
|
92 * data in the form of a TextureClientData object. This data will be kept alive |
|
93 * until the host side confirms that it is not using the data anymore and that |
|
94 * it is completely safe to deallocate the shared data. |
|
95 * |
|
96 * See: |
|
97 * - The PTexture IPDL protocol |
|
98 * - CompositableChild in TextureClient.cpp |
|
99 */ |
|
100 class TextureClientData { |
|
101 public: |
|
102 virtual void DeallocateSharedData(ISurfaceAllocator* allocator) = 0; |
|
103 virtual ~TextureClientData() {} |
|
104 }; |
|
105 |
|
106 /** |
|
107 * TextureClient is a thin abstraction over texture data that need to be shared |
|
108 * between the content process and the compositor process. It is the |
|
109 * content-side half of a TextureClient/TextureHost pair. A corresponding |
|
110 * TextureHost lives on the compositor-side. |
|
111 * |
|
112 * TextureClient's primary purpose is to present texture data in a way that is |
|
113 * understood by the IPC system. There are two ways to use it: |
|
114 * - Use it to serialize image data that is not IPC-friendly (most likely |
|
115 * involving a copy into shared memory) |
|
116 * - preallocate it and paint directly into it, which avoids copy but requires |
|
117 * the painting code to be aware of TextureClient (or at least the underlying |
|
118 * shared memory). |
|
119 * |
|
120 * There is always one and only one TextureClient per TextureHost, and the |
|
121 * TextureClient/Host pair only owns one buffer of image data through its |
|
122 * lifetime. This means that the lifetime of the underlying shared data |
|
123 * matches the lifetime of the TextureClient/Host pair. It also means |
|
124 * TextureClient/Host do not implement double buffering, which is the |
|
125 * responsibility of the compositable (which would use two Texture pairs). |
|
126 * In order to send several different buffers to the compositor side, use |
|
127 * several TextureClients. |
|
128 */ |
|
129 class TextureClient |
|
130 : public AtomicRefCountedWithFinalize<TextureClient> |
|
131 { |
|
132 public: |
|
133 TextureClient(TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT); |
|
134 virtual ~TextureClient(); |
|
135 |
|
136 static TemporaryRef<BufferTextureClient> |
|
137 CreateBufferTextureClient(ISurfaceAllocator* aAllocator, |
|
138 gfx::SurfaceFormat aFormat, |
|
139 TextureFlags aTextureFlags, |
|
140 gfx::BackendType aMoz2dBackend); |
|
141 |
|
142 static TemporaryRef<TextureClient> |
|
143 CreateTextureClientForDrawing(ISurfaceAllocator* aAllocator, |
|
144 gfx::SurfaceFormat aFormat, |
|
145 TextureFlags aTextureFlags, |
|
146 gfx::BackendType aMoz2dBackend, |
|
147 const gfx::IntSize& aSizeHint); |
|
148 |
|
149 virtual TextureClientYCbCr* AsTextureClientYCbCr() { return nullptr; } |
|
150 |
|
151 /** |
|
152 * Locks the shared data, allowing the caller to get access to it. |
|
153 * |
|
154 * Please always lock/unlock when accessing the shared data. |
|
155 * If Lock() returns false, you should not attempt to access the shared data. |
|
156 */ |
|
157 virtual bool Lock(OpenMode aMode) { return IsValid(); } |
|
158 |
|
159 virtual void Unlock() {} |
|
160 |
|
161 virtual bool IsLocked() const = 0; |
|
162 |
|
163 virtual bool CanExposeDrawTarget() const { return false; } |
|
164 |
|
165 /** |
|
166 * Returns a DrawTarget to draw into the TextureClient. |
|
167 * |
|
168 * This must never be called on a TextureClient that is not sucessfully locked. |
|
169 * When called several times within one Lock/Unlock pair, this method should |
|
170 * return the same DrawTarget. |
|
171 * The DrawTarget is automatically flushed by the TextureClient when the latter |
|
172 * is unlocked, and the DrawTarget that will be returned within the next |
|
173 * lock/unlock pair may or may not be the same object. |
|
174 * Do not keep references to the DrawTarget outside of the lock/unlock pair. |
|
175 * |
|
176 * This is typically used as follows: |
|
177 * |
|
178 * if (!texture->Lock(OPEN_READ_WRITE)) { |
|
179 * return false; |
|
180 * } |
|
181 * { |
|
182 * // Restrict this code's scope to ensure all references to dt are gone |
|
183 * // when Unlock is called. |
|
184 * RefPtr<DrawTarget> dt = texture->GetAsDrawTarget(); |
|
185 * // use the draw target ... |
|
186 * } |
|
187 * texture->Unlock(); |
|
188 * |
|
189 */ |
|
190 virtual TemporaryRef<gfx::DrawTarget> GetAsDrawTarget() { return nullptr; } |
|
191 |
|
192 // TextureClients that can expose a DrawTarget should override this method. |
|
193 virtual gfx::SurfaceFormat GetFormat() const |
|
194 { |
|
195 return gfx::SurfaceFormat::UNKNOWN; |
|
196 } |
|
197 |
|
198 /** |
|
199 * Allocates for a given surface size, taking into account the pixel format |
|
200 * which is part of the state of the TextureClient. |
|
201 * |
|
202 * Does not clear the surface by default, clearing the surface can be done |
|
203 * by passing the CLEAR_BUFFER flag. |
|
204 * |
|
205 * TextureClients that can expose a DrawTarget should override this method. |
|
206 */ |
|
207 virtual bool AllocateForSurface(gfx::IntSize aSize, |
|
208 TextureAllocationFlags flags = ALLOC_DEFAULT) |
|
209 { |
|
210 return false; |
|
211 } |
|
212 |
|
213 /** |
|
214 * Copies a rectangle from this texture client to a position in aTarget. |
|
215 * It is assumed that the necessary locks are in place; so this should at |
|
216 * least have a read lock and aTarget should at least have a write lock. |
|
217 */ |
|
218 virtual bool CopyToTextureClient(TextureClient* aTarget, |
|
219 const gfx::IntRect* aRect, |
|
220 const gfx::IntPoint* aPoint); |
|
221 |
|
222 /** |
|
223 * Returns true if this texture has a lock/unlock mechanism. |
|
224 * Textures that do not implement locking should be immutable or should |
|
225 * use immediate uploads (see TextureFlags in CompositorTypes.h) |
|
226 */ |
|
227 virtual bool ImplementsLocking() const { return false; } |
|
228 |
|
229 /** |
|
230 * Indicates whether the TextureClient implementation is backed by an |
|
231 * in-memory buffer. The consequence of this is that locking the |
|
232 * TextureClient does not contend with locking the texture on the host side. |
|
233 */ |
|
234 virtual bool HasInternalBuffer() const = 0; |
|
235 |
|
236 /** |
|
237 * Allocate and deallocate a TextureChild actor. |
|
238 * |
|
239 * TextureChild is an implementation detail of TextureClient that is not |
|
240 * exposed to the rest of the code base. CreateIPDLActor and DestroyIPDLActor |
|
241 * are for use with the managing IPDL protocols only (so that they can |
|
242 * implement AllocPextureChild and DeallocPTextureChild). |
|
243 */ |
|
244 static PTextureChild* CreateIPDLActor(); |
|
245 static bool DestroyIPDLActor(PTextureChild* actor); |
|
246 |
|
247 /** |
|
248 * Get the TextureClient corresponding to the actor passed in parameter. |
|
249 */ |
|
250 static TextureClient* AsTextureClient(PTextureChild* actor); |
|
251 |
|
252 virtual bool IsAllocated() const = 0; |
|
253 |
|
254 virtual gfx::IntSize GetSize() const = 0; |
|
255 |
|
256 /** |
|
257 * TextureFlags contain important information about various aspects |
|
258 * of the texture, like how its liferime is managed, and how it |
|
259 * should be displayed. |
|
260 * See TextureFlags in CompositorTypes.h. |
|
261 */ |
|
262 TextureFlags GetFlags() const { return mFlags; } |
|
263 |
|
264 /** |
|
265 * valid only for TEXTURE_RECYCLE TextureClient. |
|
266 * When called this texture client will grab a strong reference and release |
|
267 * it once the compositor notifies that it is done with the texture. |
|
268 * NOTE: In this stage the texture client can no longer be used by the |
|
269 * client in a transaction. |
|
270 */ |
|
271 void WaitForCompositorRecycle(); |
|
272 |
|
273 /** |
|
274 * After being shared with the compositor side, an immutable texture is never |
|
275 * modified, it can only be read. It is safe to not Lock/Unlock immutable |
|
276 * textures. |
|
277 */ |
|
278 bool IsImmutable() const { return mFlags & TEXTURE_IMMUTABLE; } |
|
279 |
|
280 void MarkImmutable() { AddFlags(TEXTURE_IMMUTABLE); } |
|
281 |
|
282 bool IsSharedWithCompositor() const { return mShared; } |
|
283 |
|
284 bool ShouldDeallocateInDestructor() const; |
|
285 |
|
286 /** |
|
287 * If this method returns false users of TextureClient are not allowed |
|
288 * to access the shared data. |
|
289 */ |
|
290 bool IsValid() const { return mValid; } |
|
291 |
|
292 /** |
|
293 * Create and init the TextureChild/Parent IPDL actor pair. |
|
294 * |
|
295 * Should be called only once per TextureClient. |
|
296 */ |
|
297 bool InitIPDLActor(CompositableForwarder* aForwarder); |
|
298 |
|
299 /** |
|
300 * Return a pointer to the IPDLActor. |
|
301 * |
|
302 * This is to be used with IPDL messages only. Do not store the returned |
|
303 * pointer. |
|
304 */ |
|
305 PTextureChild* GetIPDLActor(); |
|
306 |
|
307 /** |
|
308 * Triggers the destruction of the shared data and the corresponding TextureHost. |
|
309 * |
|
310 * If the texture flags contain TEXTURE_DEALLOCATE_CLIENT, the destruction |
|
311 * will be synchronously coordinated with the compositor side, otherwise it |
|
312 * will be done asynchronously. |
|
313 */ |
|
314 void ForceRemove(); |
|
315 |
|
316 virtual void SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle) {} |
|
317 |
|
318 const FenceHandle& GetReleaseFenceHandle() const |
|
319 { |
|
320 return mReleaseFenceHandle; |
|
321 } |
|
322 |
|
323 /** |
|
324 * Wait until the current buffer is no longer being read. |
|
325 * |
|
326 * Platform support is necessary. gonk JB supports this function. |
|
327 */ |
|
328 virtual void WaitReleaseFence() {} |
|
329 |
|
330 private: |
|
331 /** |
|
332 * Called once, just before the destructor. |
|
333 * |
|
334 * Here goes the shut-down code that uses virtual methods. |
|
335 * Must only be called by Release(). |
|
336 */ |
|
337 void Finalize(); |
|
338 |
|
339 friend class AtomicRefCountedWithFinalize<TextureClient>; |
|
340 |
|
341 protected: |
|
342 /** |
|
343 * An invalid TextureClient cannot provide access to its shared data |
|
344 * anymore. This usually means it will soon be destroyed. |
|
345 */ |
|
346 void MarkInvalid() { mValid = false; } |
|
347 |
|
348 /** |
|
349 * Drop the shared data into a TextureClientData object and mark this |
|
350 * TextureClient as invalid. |
|
351 * |
|
352 * The TextureClient must not hold any reference to the shared data |
|
353 * after this method has been called. |
|
354 * The TextureClientData is owned by the caller. |
|
355 */ |
|
356 virtual TextureClientData* DropTextureData() = 0; |
|
357 |
|
358 /** |
|
359 * Should only be called *once* per texture, in TextureClient::InitIPDLActor. |
|
360 * Some texture implementations rely on the fact that the descriptor will be |
|
361 * deserialized. |
|
362 * Calling ToSurfaceDescriptor again after it has already returned true, |
|
363 * or never constructing a TextureHost with aDescriptor may result in a memory |
|
364 * leak (see CairoTextureClientD3D9 for example). |
|
365 */ |
|
366 virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) = 0; |
|
367 |
|
368 void AddFlags(TextureFlags aFlags) |
|
369 { |
|
370 MOZ_ASSERT(!IsSharedWithCompositor()); |
|
371 mFlags |= aFlags; |
|
372 } |
|
373 |
|
374 RefPtr<TextureChild> mActor; |
|
375 TextureFlags mFlags; |
|
376 bool mShared; |
|
377 bool mValid; |
|
378 FenceHandle mReleaseFenceHandle; |
|
379 |
|
380 friend class TextureChild; |
|
381 friend void TestTextureClientSurface(TextureClient*, gfxImageSurface*); |
|
382 friend void TestTextureClientYCbCr(TextureClient*, PlanarYCbCrData&); |
|
383 }; |
|
384 |
|
385 /** |
|
386 * TextureClient that wraps a random access buffer such as a Shmem or raw memory. |
|
387 * This class must be inherited to implement the memory allocation and access bits. |
|
388 * (see ShmemTextureClient and MemoryTextureClient) |
|
389 */ |
|
390 class BufferTextureClient : public TextureClient |
|
391 , public TextureClientYCbCr |
|
392 { |
|
393 public: |
|
394 BufferTextureClient(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, |
|
395 gfx::BackendType aBackend, TextureFlags aFlags); |
|
396 |
|
397 virtual ~BufferTextureClient(); |
|
398 |
|
399 virtual bool IsAllocated() const = 0; |
|
400 |
|
401 virtual uint8_t* GetBuffer() const = 0; |
|
402 |
|
403 virtual gfx::IntSize GetSize() const { return mSize; } |
|
404 |
|
405 virtual bool Lock(OpenMode aMode) MOZ_OVERRIDE; |
|
406 |
|
407 virtual void Unlock() MOZ_OVERRIDE; |
|
408 |
|
409 virtual bool IsLocked() const MOZ_OVERRIDE { return mLocked; } |
|
410 |
|
411 virtual bool CanExposeDrawTarget() const MOZ_OVERRIDE { return true; } |
|
412 |
|
413 virtual TemporaryRef<gfx::DrawTarget> GetAsDrawTarget() MOZ_OVERRIDE; |
|
414 |
|
415 virtual bool AllocateForSurface(gfx::IntSize aSize, |
|
416 TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE; |
|
417 |
|
418 // TextureClientYCbCr |
|
419 |
|
420 virtual TextureClientYCbCr* AsTextureClientYCbCr() MOZ_OVERRIDE { return this; } |
|
421 |
|
422 virtual bool UpdateYCbCr(const PlanarYCbCrData& aData) MOZ_OVERRIDE; |
|
423 |
|
424 virtual bool AllocateForYCbCr(gfx::IntSize aYSize, |
|
425 gfx::IntSize aCbCrSize, |
|
426 StereoMode aStereoMode) MOZ_OVERRIDE; |
|
427 |
|
428 virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; } |
|
429 |
|
430 // XXX - Bug 908196 - Make Allocate(uint32_t) and GetBufferSize() protected. |
|
431 // these two methods should only be called by methods of BufferTextureClient |
|
432 // that are overridden in GrallocTextureClient (which does not implement the |
|
433 // two methods below) |
|
434 virtual bool Allocate(uint32_t aSize) = 0; |
|
435 |
|
436 virtual size_t GetBufferSize() const = 0; |
|
437 |
|
438 virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; } |
|
439 |
|
440 ISurfaceAllocator* GetAllocator() const; |
|
441 |
|
442 protected: |
|
443 RefPtr<gfx::DrawTarget> mDrawTarget; |
|
444 RefPtr<ISurfaceAllocator> mAllocator; |
|
445 gfx::SurfaceFormat mFormat; |
|
446 gfx::IntSize mSize; |
|
447 gfx::BackendType mBackend; |
|
448 OpenMode mOpenMode; |
|
449 bool mUsingFallbackDrawTarget; |
|
450 bool mLocked; |
|
451 }; |
|
452 |
|
453 /** |
|
454 * TextureClient that wraps shared memory. |
|
455 * the corresponding texture on the host side is ShmemTextureHost. |
|
456 */ |
|
457 class ShmemTextureClient : public BufferTextureClient |
|
458 { |
|
459 public: |
|
460 ShmemTextureClient(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, |
|
461 gfx::BackendType aBackend, TextureFlags aFlags); |
|
462 |
|
463 ~ShmemTextureClient(); |
|
464 |
|
465 virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE; |
|
466 |
|
467 virtual bool Allocate(uint32_t aSize) MOZ_OVERRIDE; |
|
468 |
|
469 virtual uint8_t* GetBuffer() const MOZ_OVERRIDE; |
|
470 |
|
471 virtual size_t GetBufferSize() const MOZ_OVERRIDE; |
|
472 |
|
473 virtual bool IsAllocated() const MOZ_OVERRIDE { return mAllocated; } |
|
474 |
|
475 virtual TextureClientData* DropTextureData() MOZ_OVERRIDE; |
|
476 |
|
477 virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; } |
|
478 |
|
479 mozilla::ipc::Shmem& GetShmem() { return mShmem; } |
|
480 |
|
481 protected: |
|
482 mozilla::ipc::Shmem mShmem; |
|
483 bool mAllocated; |
|
484 }; |
|
485 |
|
486 /** |
|
487 * TextureClient that wraps raw memory. |
|
488 * The corresponding texture on the host side is MemoryTextureHost. |
|
489 * Can obviously not be used in a cross process setup. |
|
490 */ |
|
491 class MemoryTextureClient : public BufferTextureClient |
|
492 { |
|
493 public: |
|
494 MemoryTextureClient(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, |
|
495 gfx::BackendType aBackend, TextureFlags aFlags); |
|
496 |
|
497 ~MemoryTextureClient(); |
|
498 |
|
499 virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE; |
|
500 |
|
501 virtual bool Allocate(uint32_t aSize) MOZ_OVERRIDE; |
|
502 |
|
503 virtual uint8_t* GetBuffer() const MOZ_OVERRIDE { return mBuffer; } |
|
504 |
|
505 virtual size_t GetBufferSize() const MOZ_OVERRIDE { return mBufSize; } |
|
506 |
|
507 virtual bool IsAllocated() const MOZ_OVERRIDE { return mBuffer != nullptr; } |
|
508 |
|
509 virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; } |
|
510 |
|
511 virtual TextureClientData* DropTextureData() MOZ_OVERRIDE; |
|
512 |
|
513 protected: |
|
514 uint8_t* mBuffer; |
|
515 size_t mBufSize; |
|
516 }; |
|
517 |
|
518 struct TextureClientAutoUnlock |
|
519 { |
|
520 TextureClient* mTexture; |
|
521 |
|
522 TextureClientAutoUnlock(TextureClient* aTexture) |
|
523 : mTexture(aTexture) {} |
|
524 |
|
525 ~TextureClientAutoUnlock() |
|
526 { |
|
527 mTexture->Unlock(); |
|
528 } |
|
529 }; |
|
530 |
|
531 } |
|
532 } |
|
533 #endif |