|
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 #ifdef MOZ_WIDGET_GONK |
|
7 |
|
8 #include "mozilla/gfx/2D.h" |
|
9 #include "mozilla/layers/GrallocTextureClient.h" |
|
10 #include "mozilla/layers/CompositableForwarder.h" |
|
11 #include "mozilla/layers/ISurfaceAllocator.h" |
|
12 #include "mozilla/layers/ShadowLayerUtilsGralloc.h" |
|
13 #include "gfx2DGlue.h" |
|
14 |
|
15 namespace mozilla { |
|
16 namespace layers { |
|
17 |
|
18 using namespace mozilla::gfx; |
|
19 using namespace android; |
|
20 |
|
21 class GrallocTextureClientData : public TextureClientData { |
|
22 public: |
|
23 GrallocTextureClientData(GrallocBufferActor* aActor) |
|
24 : mGrallocActor(aActor) |
|
25 { |
|
26 MOZ_COUNT_CTOR(GrallocTextureClientData); |
|
27 } |
|
28 |
|
29 ~GrallocTextureClientData() |
|
30 { |
|
31 MOZ_COUNT_DTOR(GrallocTextureClientData); |
|
32 MOZ_ASSERT(!mGrallocActor); |
|
33 } |
|
34 |
|
35 virtual void DeallocateSharedData(ISurfaceAllocator* allocator) MOZ_OVERRIDE |
|
36 { |
|
37 allocator->DeallocGrallocBuffer(mGrallocActor); |
|
38 mGrallocActor = nullptr; |
|
39 } |
|
40 |
|
41 private: |
|
42 GrallocBufferActor* mGrallocActor; |
|
43 }; |
|
44 |
|
45 TextureClientData* |
|
46 GrallocTextureClientOGL::DropTextureData() |
|
47 { |
|
48 TextureClientData* result = new GrallocTextureClientData(mGrallocActor); |
|
49 mGrallocActor = nullptr; |
|
50 mGraphicBuffer = nullptr; |
|
51 return result; |
|
52 } |
|
53 |
|
54 GrallocTextureClientOGL::GrallocTextureClientOGL(GrallocBufferActor* aActor, |
|
55 gfx::IntSize aSize, |
|
56 gfx::BackendType aMoz2dBackend, |
|
57 TextureFlags aFlags) |
|
58 : BufferTextureClient(nullptr, gfx::SurfaceFormat::UNKNOWN, aMoz2dBackend, aFlags) |
|
59 , mMappedBuffer(nullptr) |
|
60 , mMediaBuffer(nullptr) |
|
61 { |
|
62 InitWith(aActor, aSize); |
|
63 MOZ_COUNT_CTOR(GrallocTextureClientOGL); |
|
64 } |
|
65 |
|
66 GrallocTextureClientOGL::GrallocTextureClientOGL(ISurfaceAllocator* aAllocator, |
|
67 gfx::SurfaceFormat aFormat, |
|
68 gfx::BackendType aMoz2dBackend, |
|
69 TextureFlags aFlags) |
|
70 : BufferTextureClient(aAllocator, aFormat, aMoz2dBackend, aFlags) |
|
71 , mMappedBuffer(nullptr) |
|
72 , mMediaBuffer(nullptr) |
|
73 { |
|
74 MOZ_COUNT_CTOR(GrallocTextureClientOGL); |
|
75 } |
|
76 |
|
77 GrallocTextureClientOGL::~GrallocTextureClientOGL() |
|
78 { |
|
79 MOZ_COUNT_DTOR(GrallocTextureClientOGL); |
|
80 if (ShouldDeallocateInDestructor()) { |
|
81 ISurfaceAllocator* allocator = GetAllocator(); |
|
82 allocator->DeallocGrallocBuffer(mGrallocActor); |
|
83 } |
|
84 } |
|
85 |
|
86 void |
|
87 GrallocTextureClientOGL::InitWith(GrallocBufferActor* aActor, gfx::IntSize aSize) |
|
88 { |
|
89 MOZ_ASSERT(aActor); |
|
90 MOZ_ASSERT(!IsAllocated()); |
|
91 MOZ_ASSERT(IsValid()); |
|
92 mGrallocActor = aActor; |
|
93 mGraphicBuffer = aActor->GetGraphicBuffer(); |
|
94 mSize = aSize; |
|
95 } |
|
96 |
|
97 bool |
|
98 GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) |
|
99 { |
|
100 MOZ_ASSERT(IsValid()); |
|
101 if (!IsAllocated()) { |
|
102 return false; |
|
103 } |
|
104 |
|
105 aOutDescriptor = NewSurfaceDescriptorGralloc(nullptr, mGrallocActor, mSize); |
|
106 return true; |
|
107 } |
|
108 |
|
109 void |
|
110 GrallocTextureClientOGL::SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle) |
|
111 { |
|
112 mReleaseFenceHandle = aReleaseFenceHandle; |
|
113 } |
|
114 |
|
115 void |
|
116 GrallocTextureClientOGL::WaitReleaseFence() |
|
117 { |
|
118 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 |
|
119 if (mReleaseFenceHandle.IsValid()) { |
|
120 android::sp<Fence> fence = mReleaseFenceHandle.mFence; |
|
121 #if ANDROID_VERSION == 17 |
|
122 fence->waitForever(1000, "GrallocTextureClientOGL::Lock"); |
|
123 // 1000 is what Android uses. It is warning timeout ms. |
|
124 // This timeous is removed since ANDROID_VERSION 18. |
|
125 #else |
|
126 fence->waitForever("GrallocTextureClientOGL::Lock"); |
|
127 #endif |
|
128 mReleaseFenceHandle = FenceHandle(); |
|
129 } |
|
130 #endif |
|
131 } |
|
132 |
|
133 bool |
|
134 GrallocTextureClientOGL::Lock(OpenMode aMode) |
|
135 { |
|
136 MOZ_ASSERT(IsValid()); |
|
137 if (!IsValid() || !IsAllocated()) { |
|
138 return false; |
|
139 } |
|
140 |
|
141 if (mMappedBuffer) { |
|
142 return true; |
|
143 } |
|
144 |
|
145 WaitReleaseFence(); |
|
146 |
|
147 uint32_t usage = 0; |
|
148 if (aMode & OPEN_READ) { |
|
149 usage |= GRALLOC_USAGE_SW_READ_OFTEN; |
|
150 } |
|
151 if (aMode & OPEN_WRITE) { |
|
152 usage |= GRALLOC_USAGE_SW_WRITE_OFTEN; |
|
153 } |
|
154 int32_t rv = mGraphicBuffer->lock(usage, reinterpret_cast<void**>(&mMappedBuffer)); |
|
155 if (rv) { |
|
156 mMappedBuffer = nullptr; |
|
157 NS_WARNING("Couldn't lock graphic buffer"); |
|
158 return false; |
|
159 } |
|
160 return BufferTextureClient::Lock(aMode); |
|
161 } |
|
162 |
|
163 void |
|
164 GrallocTextureClientOGL::Unlock() |
|
165 { |
|
166 BufferTextureClient::Unlock(); |
|
167 mDrawTarget = nullptr; |
|
168 if (mMappedBuffer) { |
|
169 mMappedBuffer = nullptr; |
|
170 mGraphicBuffer->unlock(); |
|
171 } |
|
172 } |
|
173 |
|
174 uint8_t* |
|
175 GrallocTextureClientOGL::GetBuffer() const |
|
176 { |
|
177 MOZ_ASSERT(IsValid()); |
|
178 NS_WARN_IF_FALSE(mMappedBuffer, "Trying to get a gralloc buffer without getting the lock?"); |
|
179 return mMappedBuffer; |
|
180 } |
|
181 |
|
182 static gfx::SurfaceFormat |
|
183 SurfaceFormatForPixelFormat(android::PixelFormat aFormat) |
|
184 { |
|
185 switch (aFormat) { |
|
186 case PIXEL_FORMAT_RGBA_8888: |
|
187 return gfx::SurfaceFormat::R8G8B8A8; |
|
188 case PIXEL_FORMAT_BGRA_8888: |
|
189 return gfx::SurfaceFormat::B8G8R8A8; |
|
190 case PIXEL_FORMAT_RGBX_8888: |
|
191 return gfx::SurfaceFormat::R8G8B8X8; |
|
192 case PIXEL_FORMAT_RGB_565: |
|
193 return gfx::SurfaceFormat::R5G6B5; |
|
194 default: |
|
195 MOZ_CRASH("Unknown gralloc pixel format"); |
|
196 } |
|
197 return gfx::SurfaceFormat::R8G8B8A8; |
|
198 } |
|
199 |
|
200 TemporaryRef<gfx::DrawTarget> |
|
201 GrallocTextureClientOGL::GetAsDrawTarget() |
|
202 { |
|
203 MOZ_ASSERT(IsValid()); |
|
204 MOZ_ASSERT(mMappedBuffer, "Calling TextureClient::GetAsDrawTarget without locking :("); |
|
205 |
|
206 if (mDrawTarget) { |
|
207 return mDrawTarget; |
|
208 } |
|
209 |
|
210 gfx::SurfaceFormat format = SurfaceFormatForPixelFormat(mGraphicBuffer->getPixelFormat()); |
|
211 long pixelStride = mGraphicBuffer->getStride(); |
|
212 long byteStride = pixelStride * BytesPerPixel(format); |
|
213 mDrawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForData(GetBuffer(), |
|
214 mSize, |
|
215 byteStride, |
|
216 mFormat); |
|
217 return mDrawTarget; |
|
218 } |
|
219 |
|
220 bool |
|
221 GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize, |
|
222 TextureAllocationFlags) |
|
223 { |
|
224 MOZ_ASSERT(IsValid()); |
|
225 |
|
226 uint32_t format; |
|
227 uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN | |
|
228 android::GraphicBuffer::USAGE_SW_WRITE_OFTEN | |
|
229 android::GraphicBuffer::USAGE_HW_TEXTURE; |
|
230 |
|
231 switch (mFormat) { |
|
232 case gfx::SurfaceFormat::R8G8B8A8: |
|
233 format = android::PIXEL_FORMAT_RGBA_8888; |
|
234 break; |
|
235 case gfx::SurfaceFormat::B8G8R8A8: |
|
236 format = android::PIXEL_FORMAT_RGBA_8888; |
|
237 mFlags |= TEXTURE_RB_SWAPPED; |
|
238 break; |
|
239 case gfx::SurfaceFormat::R8G8B8X8: |
|
240 format = android::PIXEL_FORMAT_RGBX_8888; |
|
241 break; |
|
242 case gfx::SurfaceFormat::B8G8R8X8: |
|
243 format = android::PIXEL_FORMAT_RGBX_8888; |
|
244 mFlags |= TEXTURE_RB_SWAPPED; |
|
245 break; |
|
246 case gfx::SurfaceFormat::R5G6B5: |
|
247 format = android::PIXEL_FORMAT_RGB_565; |
|
248 break; |
|
249 case gfx::SurfaceFormat::A8: |
|
250 NS_WARNING("gralloc does not support gfx::SurfaceFormat::A8"); |
|
251 return false; |
|
252 default: |
|
253 NS_WARNING("Unsupported surface format"); |
|
254 return false; |
|
255 } |
|
256 |
|
257 return AllocateGralloc(aSize, format, usage); |
|
258 } |
|
259 |
|
260 bool |
|
261 GrallocTextureClientOGL::AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize, StereoMode aStereoMode) |
|
262 { |
|
263 MOZ_ASSERT(IsValid()); |
|
264 return AllocateGralloc(aYSize, |
|
265 HAL_PIXEL_FORMAT_YV12, |
|
266 android::GraphicBuffer::USAGE_SW_READ_OFTEN); |
|
267 } |
|
268 |
|
269 bool |
|
270 GrallocTextureClientOGL::AllocateForGLRendering(gfx::IntSize aSize) |
|
271 { |
|
272 MOZ_ASSERT(IsValid()); |
|
273 |
|
274 uint32_t format; |
|
275 uint32_t usage = android::GraphicBuffer::USAGE_HW_RENDER | |
|
276 android::GraphicBuffer::USAGE_HW_TEXTURE; |
|
277 |
|
278 switch (mFormat) { |
|
279 case gfx::SurfaceFormat::R8G8B8A8: |
|
280 case gfx::SurfaceFormat::B8G8R8A8: |
|
281 format = android::PIXEL_FORMAT_RGBA_8888; |
|
282 break; |
|
283 case gfx::SurfaceFormat::R8G8B8X8: |
|
284 case gfx::SurfaceFormat::B8G8R8X8: |
|
285 // there is no android BGRX format? |
|
286 format = android::PIXEL_FORMAT_RGBX_8888; |
|
287 break; |
|
288 case gfx::SurfaceFormat::R5G6B5: |
|
289 format = android::PIXEL_FORMAT_RGB_565; |
|
290 break; |
|
291 default: |
|
292 NS_WARNING("Unsupported surface format"); |
|
293 return false; |
|
294 } |
|
295 |
|
296 return AllocateGralloc(aSize, format, usage); |
|
297 } |
|
298 |
|
299 bool |
|
300 GrallocTextureClientOGL::AllocateGralloc(gfx::IntSize aSize, |
|
301 uint32_t aAndroidFormat, |
|
302 uint32_t aUsage) |
|
303 { |
|
304 MOZ_ASSERT(IsValid()); |
|
305 ISurfaceAllocator* allocator = GetAllocator(); |
|
306 |
|
307 MaybeMagicGrallocBufferHandle handle; |
|
308 PGrallocBufferChild* actor = |
|
309 allocator->AllocGrallocBuffer(aSize, |
|
310 aAndroidFormat, |
|
311 aUsage, |
|
312 &handle); |
|
313 if (!actor) { |
|
314 return false; |
|
315 } |
|
316 GrallocBufferActor* gba = static_cast<GrallocBufferActor*>(actor); |
|
317 gba->InitFromHandle(handle.get_MagicGrallocBufferHandle()); |
|
318 |
|
319 sp<GraphicBuffer> graphicBuffer = gba->GetGraphicBuffer(); |
|
320 if (!graphicBuffer.get()) { |
|
321 return false; |
|
322 } |
|
323 |
|
324 if (graphicBuffer->initCheck() != NO_ERROR) { |
|
325 return false; |
|
326 } |
|
327 |
|
328 mGrallocActor = gba; |
|
329 mGraphicBuffer = graphicBuffer; |
|
330 mSize = aSize; |
|
331 return true; |
|
332 } |
|
333 |
|
334 bool |
|
335 GrallocTextureClientOGL::IsAllocated() const |
|
336 { |
|
337 return !!mGraphicBuffer.get(); |
|
338 } |
|
339 |
|
340 bool |
|
341 GrallocTextureClientOGL::Allocate(uint32_t aSize) |
|
342 { |
|
343 // see Bug 908196 |
|
344 MOZ_CRASH("This method should never be called."); |
|
345 return false; |
|
346 } |
|
347 |
|
348 size_t |
|
349 GrallocTextureClientOGL::GetBufferSize() const |
|
350 { |
|
351 // see Bug 908196 |
|
352 MOZ_CRASH("This method should never be called."); |
|
353 return 0; |
|
354 } |
|
355 |
|
356 } // namesapace layers |
|
357 } // namesapace mozilla |
|
358 |
|
359 #endif // MOZ_WIDGET_GONK |