Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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/. */
6 #ifdef MOZ_WIDGET_GONK
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"
15 namespace mozilla {
16 namespace layers {
18 using namespace mozilla::gfx;
19 using namespace android;
21 class GrallocTextureClientData : public TextureClientData {
22 public:
23 GrallocTextureClientData(GrallocBufferActor* aActor)
24 : mGrallocActor(aActor)
25 {
26 MOZ_COUNT_CTOR(GrallocTextureClientData);
27 }
29 ~GrallocTextureClientData()
30 {
31 MOZ_COUNT_DTOR(GrallocTextureClientData);
32 MOZ_ASSERT(!mGrallocActor);
33 }
35 virtual void DeallocateSharedData(ISurfaceAllocator* allocator) MOZ_OVERRIDE
36 {
37 allocator->DeallocGrallocBuffer(mGrallocActor);
38 mGrallocActor = nullptr;
39 }
41 private:
42 GrallocBufferActor* mGrallocActor;
43 };
45 TextureClientData*
46 GrallocTextureClientOGL::DropTextureData()
47 {
48 TextureClientData* result = new GrallocTextureClientData(mGrallocActor);
49 mGrallocActor = nullptr;
50 mGraphicBuffer = nullptr;
51 return result;
52 }
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 }
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 }
77 GrallocTextureClientOGL::~GrallocTextureClientOGL()
78 {
79 MOZ_COUNT_DTOR(GrallocTextureClientOGL);
80 if (ShouldDeallocateInDestructor()) {
81 ISurfaceAllocator* allocator = GetAllocator();
82 allocator->DeallocGrallocBuffer(mGrallocActor);
83 }
84 }
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 }
97 bool
98 GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
99 {
100 MOZ_ASSERT(IsValid());
101 if (!IsAllocated()) {
102 return false;
103 }
105 aOutDescriptor = NewSurfaceDescriptorGralloc(nullptr, mGrallocActor, mSize);
106 return true;
107 }
109 void
110 GrallocTextureClientOGL::SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle)
111 {
112 mReleaseFenceHandle = aReleaseFenceHandle;
113 }
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 }
133 bool
134 GrallocTextureClientOGL::Lock(OpenMode aMode)
135 {
136 MOZ_ASSERT(IsValid());
137 if (!IsValid() || !IsAllocated()) {
138 return false;
139 }
141 if (mMappedBuffer) {
142 return true;
143 }
145 WaitReleaseFence();
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 }
163 void
164 GrallocTextureClientOGL::Unlock()
165 {
166 BufferTextureClient::Unlock();
167 mDrawTarget = nullptr;
168 if (mMappedBuffer) {
169 mMappedBuffer = nullptr;
170 mGraphicBuffer->unlock();
171 }
172 }
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 }
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 }
200 TemporaryRef<gfx::DrawTarget>
201 GrallocTextureClientOGL::GetAsDrawTarget()
202 {
203 MOZ_ASSERT(IsValid());
204 MOZ_ASSERT(mMappedBuffer, "Calling TextureClient::GetAsDrawTarget without locking :(");
206 if (mDrawTarget) {
207 return mDrawTarget;
208 }
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 }
220 bool
221 GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize,
222 TextureAllocationFlags)
223 {
224 MOZ_ASSERT(IsValid());
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;
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 }
257 return AllocateGralloc(aSize, format, usage);
258 }
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 }
269 bool
270 GrallocTextureClientOGL::AllocateForGLRendering(gfx::IntSize aSize)
271 {
272 MOZ_ASSERT(IsValid());
274 uint32_t format;
275 uint32_t usage = android::GraphicBuffer::USAGE_HW_RENDER |
276 android::GraphicBuffer::USAGE_HW_TEXTURE;
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 }
296 return AllocateGralloc(aSize, format, usage);
297 }
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();
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());
319 sp<GraphicBuffer> graphicBuffer = gba->GetGraphicBuffer();
320 if (!graphicBuffer.get()) {
321 return false;
322 }
324 if (graphicBuffer->initCheck() != NO_ERROR) {
325 return false;
326 }
328 mGrallocActor = gba;
329 mGraphicBuffer = graphicBuffer;
330 mSize = aSize;
331 return true;
332 }
334 bool
335 GrallocTextureClientOGL::IsAllocated() const
336 {
337 return !!mGraphicBuffer.get();
338 }
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 }
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 }
356 } // namesapace layers
357 } // namesapace mozilla
359 #endif // MOZ_WIDGET_GONK