Bug 977880 - Handle ReleaseFence on tiled thebes layer r=cwiiis,nical,BenWa
[gecko.git] / gfx / layers / opengl / GrallocTextureClient.cpp
blob62de43a32d37e0bfe2f9116056e9345b9bcb7b59
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"
14 #include "gfxASurface.h"
15 #include "gfxImageSurface.h" // for gfxImageSurface
16 #include "GrallocImages.h"
18 namespace mozilla {
19 namespace layers {
21 using namespace mozilla::gfx;
22 using namespace android;
24 class GraphicBufferLockedTextureClientData : public TextureClientData {
25 public:
26 GraphicBufferLockedTextureClientData(GraphicBufferLocked* aBufferLocked)
27 : mBufferLocked(aBufferLocked)
29 MOZ_COUNT_CTOR(GrallocTextureClientData);
32 ~GraphicBufferLockedTextureClientData()
34 MOZ_COUNT_DTOR(GrallocTextureClientData);
35 MOZ_ASSERT(!mBufferLocked, "Forgot to unlock the GraphicBufferLocked?");
38 virtual void DeallocateSharedData(ISurfaceAllocator*) MOZ_OVERRIDE
40 mBufferLocked = nullptr;
43 private:
44 RefPtr<GraphicBufferLocked> mBufferLocked;
47 class GrallocTextureClientData : public TextureClientData {
48 public:
49 GrallocTextureClientData(GrallocBufferActor* aActor)
50 : mGrallocActor(aActor)
52 MOZ_COUNT_CTOR(GrallocTextureClientData);
55 ~GrallocTextureClientData()
57 MOZ_COUNT_DTOR(GrallocTextureClientData);
58 MOZ_ASSERT(!mGrallocActor, "Forgot to unlock the GraphicBufferLocked?");
61 virtual void DeallocateSharedData(ISurfaceAllocator* allocator) MOZ_OVERRIDE
63 // We just need to wrap the actor in a SurfaceDescriptor because that's what
64 // ISurfaceAllocator uses as input, we don't care about the other parameters.
65 SurfaceDescriptor sd = SurfaceDescriptorGralloc(nullptr, mGrallocActor,
66 IntSize(0, 0),
67 false, false);
68 allocator->DestroySharedSurface(&sd);
69 mGrallocActor = nullptr;
72 private:
73 GrallocBufferActor* mGrallocActor;
76 TextureClientData*
77 GrallocTextureClientOGL::DropTextureData()
79 if (mBufferLocked) {
80 TextureClientData* result = new GraphicBufferLockedTextureClientData(mBufferLocked);
81 mBufferLocked = nullptr;
82 mGrallocActor = nullptr;
83 mGraphicBuffer = nullptr;
84 return result;
85 } else {
86 TextureClientData* result = new GrallocTextureClientData(mGrallocActor);
87 mGrallocActor = nullptr;
88 mGraphicBuffer = nullptr;
89 return result;
93 GrallocTextureClientOGL::GrallocTextureClientOGL(GrallocBufferActor* aActor,
94 gfx::IntSize aSize,
95 gfx::BackendType aMoz2dBackend,
96 TextureFlags aFlags)
97 : BufferTextureClient(nullptr, gfx::SurfaceFormat::UNKNOWN, aMoz2dBackend, aFlags)
98 , mMappedBuffer(nullptr)
100 InitWith(aActor, aSize);
101 MOZ_COUNT_CTOR(GrallocTextureClientOGL);
104 GrallocTextureClientOGL::GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
105 gfx::SurfaceFormat aFormat,
106 gfx::BackendType aMoz2dBackend,
107 TextureFlags aFlags)
108 : BufferTextureClient(aAllocator, aFormat, aMoz2dBackend, aFlags)
109 , mMappedBuffer(nullptr)
111 MOZ_COUNT_CTOR(GrallocTextureClientOGL);
114 GrallocTextureClientOGL::~GrallocTextureClientOGL()
116 MOZ_COUNT_DTOR(GrallocTextureClientOGL);
117 if (ShouldDeallocateInDestructor()) {
118 // If the buffer has never been shared we must deallocate it or it would
119 // leak.
120 if (!mBufferLocked) {
121 // We just need to wrap the actor in a SurfaceDescriptor because that's what
122 // ISurfaceAllocator uses as input, we don't care about the other parameters.
123 SurfaceDescriptor sd = SurfaceDescriptorGralloc(nullptr, mGrallocActor,
124 IntSize(0, 0),
125 false, false);
127 ISurfaceAllocator* allocator = GetAllocator();
128 allocator->DestroySharedSurface(&sd);
133 void
134 GrallocTextureClientOGL::InitWith(GrallocBufferActor* aActor, gfx::IntSize aSize)
136 MOZ_ASSERT(aActor);
137 MOZ_ASSERT(!IsAllocated());
138 MOZ_ASSERT(IsValid());
139 mGrallocActor = aActor;
140 mGraphicBuffer = aActor->GetGraphicBuffer();
141 mSize = aSize;
144 void
145 GrallocTextureClientOGL::SetGraphicBufferLocked(GraphicBufferLocked* aBufferLocked)
147 mBufferLocked = aBufferLocked;
150 bool
151 GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
153 MOZ_ASSERT(IsValid());
154 if (!IsAllocated()) {
155 return false;
158 aOutDescriptor = NewSurfaceDescriptorGralloc(nullptr, mGrallocActor, mSize);
159 return true;
162 bool
163 GrallocTextureClientOGL::UpdateSurface(gfxASurface* aSurface)
165 MOZ_ASSERT(aSurface);
166 MOZ_ASSERT(!IsImmutable());
167 MOZ_ASSERT(IsValid());
168 if (!IsValid() || !IsAllocated()) {
169 return false;
172 RefPtr<DrawTarget> dt = GetAsDrawTarget();
173 RefPtr<SourceSurface> source = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, aSurface);
175 dt->CopySurface(source, IntRect(IntPoint(), GetSize()), IntPoint());
177 return true;
180 void
181 GrallocTextureClientOGL::SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle)
183 if (mBufferLocked) {
184 mBufferLocked->SetReleaseFenceHandle(aReleaseFenceHandle);
185 } else {
186 mReleaseFenceHandle = aReleaseFenceHandle;
190 void
191 GrallocTextureClientOGL::WaitReleaseFence()
193 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
194 if (mReleaseFenceHandle.IsValid()) {
195 android::sp<Fence> fence = mReleaseFenceHandle.mFence;
196 #if ANDROID_VERSION == 17
197 fence->waitForever(1000, "GrallocTextureClientOGL::Lock");
198 // 1000 is what Android uses. It is warning timeout ms.
199 // This timeous is removed since ANDROID_VERSION 18.
200 #else
201 fence->waitForever("GrallocTextureClientOGL::Lock");
202 #endif
203 mReleaseFenceHandle = FenceHandle();
205 #endif
208 bool
209 GrallocTextureClientOGL::Lock(OpenMode aMode)
211 MOZ_ASSERT(IsValid());
212 if (!IsValid() || !IsAllocated()) {
213 return false;
216 if (mMappedBuffer) {
217 return true;
220 WaitReleaseFence();
222 uint32_t usage = 0;
223 if (aMode & OPEN_READ) {
224 usage |= GRALLOC_USAGE_SW_READ_OFTEN;
226 if (aMode & OPEN_WRITE) {
227 usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
229 int32_t rv = mGraphicBuffer->lock(usage, reinterpret_cast<void**>(&mMappedBuffer));
230 if (rv) {
231 mMappedBuffer = nullptr;
232 NS_WARNING("Couldn't lock graphic buffer");
233 return false;
235 return BufferTextureClient::Lock(aMode);
238 void
239 GrallocTextureClientOGL::Unlock()
241 BufferTextureClient::Unlock();
242 mDrawTarget = nullptr;
243 if (mMappedBuffer) {
244 mMappedBuffer = nullptr;
245 mGraphicBuffer->unlock();
249 uint8_t*
250 GrallocTextureClientOGL::GetBuffer() const
252 MOZ_ASSERT(IsValid());
253 NS_WARN_IF_FALSE(mMappedBuffer, "Trying to get a gralloc buffer without getting the lock?");
254 return mMappedBuffer;
257 static gfx::SurfaceFormat
258 SurfaceFormatForPixelFormat(android::PixelFormat aFormat)
260 switch (aFormat) {
261 case PIXEL_FORMAT_RGBA_8888:
262 return gfx::SurfaceFormat::R8G8B8A8;
263 case PIXEL_FORMAT_BGRA_8888:
264 return gfx::SurfaceFormat::B8G8R8A8;
265 case PIXEL_FORMAT_RGBX_8888:
266 return gfx::SurfaceFormat::R8G8B8X8;
267 case PIXEL_FORMAT_RGB_565:
268 return gfx::SurfaceFormat::R5G6B5;
269 default:
270 MOZ_CRASH("Unknown gralloc pixel format");
272 return gfx::SurfaceFormat::R8G8B8A8;
275 TemporaryRef<gfx::DrawTarget>
276 GrallocTextureClientOGL::GetAsDrawTarget()
278 MOZ_ASSERT(IsValid());
279 MOZ_ASSERT(mMappedBuffer, "Calling TextureClient::GetAsDrawTarget without locking :(");
281 if (mDrawTarget) {
282 return mDrawTarget;
285 gfx::SurfaceFormat format = SurfaceFormatForPixelFormat(mGraphicBuffer->getPixelFormat());
286 long pixelStride = mGraphicBuffer->getStride();
287 long byteStride = pixelStride * BytesPerPixel(format);
288 mDrawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForData(GetBuffer(),
289 mSize,
290 byteStride,
291 mFormat);
292 return mDrawTarget;
295 already_AddRefed<gfxASurface>
296 GrallocTextureClientOGL::GetAsSurface()
298 MOZ_ASSERT(IsValid());
299 MOZ_ASSERT(mMappedBuffer, "Calling TextureClient::GetAsSurface without locking :(");
301 gfx::SurfaceFormat format = SurfaceFormatForPixelFormat(mGraphicBuffer->getPixelFormat());
302 long pixelStride = mGraphicBuffer->getStride();
303 long byteStride = pixelStride * BytesPerPixel(format);
304 nsRefPtr<gfxImageSurface> surface =
305 new gfxImageSurface(GetBuffer(),
306 gfxIntSize(mSize.width, mSize.height),
307 byteStride,
308 SurfaceFormatToImageFormat(mFormat));
309 return surface.forget();
312 bool
313 GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize,
314 TextureAllocationFlags)
316 MOZ_ASSERT(IsValid());
318 uint32_t format;
319 uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN |
320 android::GraphicBuffer::USAGE_SW_WRITE_OFTEN |
321 android::GraphicBuffer::USAGE_HW_TEXTURE;
323 switch (mFormat) {
324 case gfx::SurfaceFormat::R8G8B8A8:
325 format = android::PIXEL_FORMAT_RGBA_8888;
326 break;
327 case gfx::SurfaceFormat::B8G8R8A8:
328 format = android::PIXEL_FORMAT_RGBA_8888;
329 mFlags |= TEXTURE_RB_SWAPPED;
330 break;
331 case gfx::SurfaceFormat::R8G8B8X8:
332 format = android::PIXEL_FORMAT_RGBX_8888;
333 break;
334 case gfx::SurfaceFormat::B8G8R8X8:
335 format = android::PIXEL_FORMAT_RGBX_8888;
336 mFlags |= TEXTURE_RB_SWAPPED;
337 break;
338 case gfx::SurfaceFormat::R5G6B5:
339 format = android::PIXEL_FORMAT_RGB_565;
340 break;
341 case gfx::SurfaceFormat::A8:
342 NS_WARNING("gralloc does not support gfx::SurfaceFormat::A8");
343 return false;
344 default:
345 NS_WARNING("Unsupported surface format");
346 return false;
349 return AllocateGralloc(aSize, format, usage);
352 bool
353 GrallocTextureClientOGL::AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize, StereoMode aStereoMode)
355 MOZ_ASSERT(IsValid());
356 return AllocateGralloc(aYSize,
357 HAL_PIXEL_FORMAT_YV12,
358 android::GraphicBuffer::USAGE_SW_READ_OFTEN);
361 bool
362 GrallocTextureClientOGL::AllocateForGLRendering(gfx::IntSize aSize)
364 MOZ_ASSERT(IsValid());
366 uint32_t format;
367 uint32_t usage = android::GraphicBuffer::USAGE_HW_RENDER |
368 android::GraphicBuffer::USAGE_HW_TEXTURE;
370 switch (mFormat) {
371 case gfx::SurfaceFormat::R8G8B8A8:
372 case gfx::SurfaceFormat::B8G8R8A8:
373 format = android::PIXEL_FORMAT_RGBA_8888;
374 break;
375 case gfx::SurfaceFormat::R8G8B8X8:
376 case gfx::SurfaceFormat::B8G8R8X8:
377 // there is no android BGRX format?
378 format = android::PIXEL_FORMAT_RGBX_8888;
379 break;
380 case gfx::SurfaceFormat::R5G6B5:
381 format = android::PIXEL_FORMAT_RGB_565;
382 break;
383 default:
384 NS_WARNING("Unsupported surface format");
385 return false;
388 return AllocateGralloc(aSize, format, usage);
391 bool
392 GrallocTextureClientOGL::AllocateGralloc(gfx::IntSize aSize,
393 uint32_t aAndroidFormat,
394 uint32_t aUsage)
396 MOZ_ASSERT(IsValid());
397 ISurfaceAllocator* allocator = GetAllocator();
399 MaybeMagicGrallocBufferHandle handle;
400 PGrallocBufferChild* actor =
401 allocator->AllocGrallocBuffer(aSize,
402 aAndroidFormat,
403 aUsage,
404 &handle);
405 if (!actor) {
406 return false;
408 GrallocBufferActor* gba = static_cast<GrallocBufferActor*>(actor);
409 gba->InitFromHandle(handle.get_MagicGrallocBufferHandle());
411 sp<GraphicBuffer> graphicBuffer = gba->GetGraphicBuffer();
412 if (!graphicBuffer.get()) {
413 return false;
416 if (graphicBuffer->initCheck() != NO_ERROR) {
417 return false;
420 mGrallocActor = gba;
421 mGraphicBuffer = graphicBuffer;
422 mSize = aSize;
423 return true;
426 bool
427 GrallocTextureClientOGL::IsAllocated() const
429 return !!mGraphicBuffer.get();
432 bool
433 GrallocTextureClientOGL::Allocate(uint32_t aSize)
435 // see Bug 908196
436 MOZ_CRASH("This method should never be called.");
437 return false;
440 size_t
441 GrallocTextureClientOGL::GetBufferSize() const
443 // see Bug 908196
444 MOZ_CRASH("This method should never be called.");
445 return 0;
448 } // namesapace layers
449 } // namesapace mozilla
451 #endif // MOZ_WIDGET_GONK