Line data Source code
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_SOURCESURFACESHAREDDATA_H_
7 : #define MOZILLA_GFX_SOURCESURFACESHAREDDATA_H_
8 :
9 : #include "mozilla/gfx/2D.h"
10 : #include "mozilla/Mutex.h"
11 : #include "mozilla/ipc/SharedMemoryBasic.h"
12 :
13 : namespace mozilla {
14 : namespace gfx {
15 :
16 : /**
17 : * This class is used to wrap shared (as in process) data buffers used by a
18 : * source surface.
19 : */
20 : class SourceSurfaceSharedData final : public DataSourceSurface
21 : {
22 : typedef mozilla::ipc::SharedMemoryBasic SharedMemoryBasic;
23 :
24 : public:
25 0 : MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceSharedData, override)
26 :
27 0 : SourceSurfaceSharedData()
28 0 : : mMutex("SourceSurfaceSharedData")
29 : , mStride(0)
30 : , mMapCount(0)
31 : , mFormat(SurfaceFormat::UNKNOWN)
32 : , mClosed(false)
33 : , mFinalized(false)
34 0 : , mShared(false)
35 : {
36 0 : }
37 :
38 : bool Init(const IntSize &aSize,
39 : int32_t aStride,
40 : SurfaceFormat aFormat);
41 :
42 0 : uint8_t* GetData() override
43 : {
44 0 : MutexAutoLock lock(mMutex);
45 0 : return GetDataInternal();
46 : }
47 :
48 0 : int32_t Stride() override { return mStride; }
49 :
50 0 : SurfaceType GetType() const override { return SurfaceType::DATA_SHARED; }
51 0 : IntSize GetSize() const override { return mSize; }
52 0 : SurfaceFormat GetFormat() const override { return mFormat; }
53 :
54 : void GuaranteePersistance() override;
55 :
56 : void AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
57 : size_t& aHeapSizeOut,
58 : size_t& aNonHeapSizeOut) const override;
59 :
60 0 : bool OnHeap() const override
61 : {
62 0 : return false;
63 : }
64 :
65 : /**
66 : * Although Map (and Moz2D in general) isn't normally threadsafe,
67 : * we want to allow it for SourceSurfaceSharedData since it should
68 : * always be fine (for reading at least).
69 : *
70 : * This is the same as the base class implementation except using
71 : * mMapCount instead of mIsMapped since that breaks for multithread.
72 : *
73 : * Additionally if a reallocation happened while there were active
74 : * mappings, then we guarantee that GetData will continue to return
75 : * the same data pointer by retaining the old shared buffer until
76 : * the last mapping is freed via Unmap.
77 : */
78 0 : bool Map(MapType, MappedSurface *aMappedSurface) override
79 : {
80 0 : MutexAutoLock lock(mMutex);
81 0 : ++mMapCount;
82 0 : aMappedSurface->mData = GetDataInternal();
83 0 : aMappedSurface->mStride = mStride;
84 0 : return true;
85 : }
86 :
87 0 : void Unmap() override
88 : {
89 0 : MutexAutoLock lock(mMutex);
90 0 : MOZ_ASSERT(mMapCount > 0);
91 0 : if (--mMapCount == 0) {
92 0 : mOldBuf = nullptr;
93 : }
94 0 : }
95 :
96 : /**
97 : * Get a handle to share to another process for this buffer. Returns:
98 : * NS_OK -- success, aHandle is valid.
99 : * NS_ERROR_NOT_AVAILABLE -- handle was closed, need to reallocate.
100 : * NS_ERROR_FAILURE -- failed to create a handle to share.
101 : */
102 : nsresult ShareToProcess(base::ProcessId aPid,
103 : SharedMemoryBasic::Handle& aHandle);
104 :
105 : /**
106 : * Indicates the buffer is not expected to be shared with any more processes.
107 : * May release the handle if possible (see CloseHandleInternal).
108 : */
109 0 : void FinishedSharing()
110 : {
111 0 : MutexAutoLock lock(mMutex);
112 0 : mShared = true;
113 0 : CloseHandleInternal();
114 0 : }
115 :
116 : /**
117 : * Indicates whether or not the buffer can be shared with another process
118 : * without reallocating. Note that this is racy and should only be used for
119 : * informational/reporting purposes.
120 : */
121 0 : bool CanShare() const
122 : {
123 0 : MutexAutoLock lock(mMutex);
124 0 : return !mClosed;
125 : }
126 :
127 : /**
128 : * Allocate a new shared memory buffer so that we can get a new handle for
129 : * sharing to new processes. ShareToProcess must have failed with
130 : * NS_ERROR_NOT_AVAILABLE in order for this to be safe to call. Returns true
131 : * if the operation succeeds. If it fails, there is no state change.
132 : */
133 : bool ReallocHandle();
134 :
135 : /**
136 : * Indicates we have finished writing to the buffer and it may be marked as
137 : * read only. May release the handle if possible (see CloseHandleInternal).
138 : */
139 : void Finalize();
140 :
141 : private:
142 0 : ~SourceSurfaceSharedData() override
143 0 : {
144 0 : MOZ_ASSERT(mMapCount == 0);
145 0 : }
146 :
147 : uint8_t* GetDataInternal() const;
148 :
149 0 : size_t GetDataLength() const
150 : {
151 0 : return static_cast<size_t>(mStride) * mSize.height;
152 : }
153 :
154 0 : size_t GetAlignedDataLength() const
155 : {
156 0 : return mozilla::ipc::SharedMemory::PageAlignedSize(GetDataLength());
157 : }
158 :
159 : /**
160 : * Attempt to close the handle. Only if the buffer has been both finalized
161 : * and we have completed sharing will it be released.
162 : */
163 : void CloseHandleInternal();
164 :
165 : mutable Mutex mMutex;
166 : int32_t mStride;
167 : int32_t mMapCount;
168 : IntSize mSize;
169 : RefPtr<SharedMemoryBasic> mBuf;
170 : RefPtr<SharedMemoryBasic> mOldBuf;
171 : SurfaceFormat mFormat;
172 : bool mClosed : 1;
173 : bool mFinalized : 1;
174 : bool mShared : 1;
175 : };
176 :
177 : } // namespace gfx
178 : } // namespace mozilla
179 :
180 : #endif /* MOZILLA_GFX_SOURCESURFACESHAREDDATA_H_ */
|