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/. */
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"
21 using namespace mozilla::gfx
;
22 using namespace android
;
24 class GraphicBufferLockedTextureClientData
: public TextureClientData
{
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;
44 RefPtr
<GraphicBufferLocked
> mBufferLocked
;
47 class GrallocTextureClientData
: public TextureClientData
{
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
,
68 allocator
->DestroySharedSurface(&sd
);
69 mGrallocActor
= nullptr;
73 GrallocBufferActor
* mGrallocActor
;
77 GrallocTextureClientOGL::DropTextureData()
80 TextureClientData
* result
= new GraphicBufferLockedTextureClientData(mBufferLocked
);
81 mBufferLocked
= nullptr;
82 mGrallocActor
= nullptr;
83 mGraphicBuffer
= nullptr;
86 TextureClientData
* result
= new GrallocTextureClientData(mGrallocActor
);
87 mGrallocActor
= nullptr;
88 mGraphicBuffer
= nullptr;
93 GrallocTextureClientOGL::GrallocTextureClientOGL(GrallocBufferActor
* aActor
,
95 gfx::BackendType aMoz2dBackend
,
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
,
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
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
,
127 ISurfaceAllocator
* allocator
= GetAllocator();
128 allocator
->DestroySharedSurface(&sd
);
134 GrallocTextureClientOGL::InitWith(GrallocBufferActor
* aActor
, gfx::IntSize aSize
)
137 MOZ_ASSERT(!IsAllocated());
138 MOZ_ASSERT(IsValid());
139 mGrallocActor
= aActor
;
140 mGraphicBuffer
= aActor
->GetGraphicBuffer();
145 GrallocTextureClientOGL::SetGraphicBufferLocked(GraphicBufferLocked
* aBufferLocked
)
147 mBufferLocked
= aBufferLocked
;
151 GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor
& aOutDescriptor
)
153 MOZ_ASSERT(IsValid());
154 if (!IsAllocated()) {
158 aOutDescriptor
= NewSurfaceDescriptorGralloc(nullptr, mGrallocActor
, mSize
);
163 GrallocTextureClientOGL::UpdateSurface(gfxASurface
* aSurface
)
165 MOZ_ASSERT(aSurface
);
166 MOZ_ASSERT(!IsImmutable());
167 MOZ_ASSERT(IsValid());
168 if (!IsValid() || !IsAllocated()) {
172 RefPtr
<DrawTarget
> dt
= GetAsDrawTarget();
173 RefPtr
<SourceSurface
> source
= gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt
, aSurface
);
175 dt
->CopySurface(source
, IntRect(IntPoint(), GetSize()), IntPoint());
181 GrallocTextureClientOGL::SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle
)
184 mBufferLocked
->SetReleaseFenceHandle(aReleaseFenceHandle
);
186 mReleaseFenceHandle
= aReleaseFenceHandle
;
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.
201 fence
->waitForever("GrallocTextureClientOGL::Lock");
203 mReleaseFenceHandle
= FenceHandle();
209 GrallocTextureClientOGL::Lock(OpenMode aMode
)
211 MOZ_ASSERT(IsValid());
212 if (!IsValid() || !IsAllocated()) {
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
));
231 mMappedBuffer
= nullptr;
232 NS_WARNING("Couldn't lock graphic buffer");
235 return BufferTextureClient::Lock(aMode
);
239 GrallocTextureClientOGL::Unlock()
241 BufferTextureClient::Unlock();
242 mDrawTarget
= nullptr;
244 mMappedBuffer
= nullptr;
245 mGraphicBuffer
->unlock();
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
)
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
;
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 :(");
285 gfx::SurfaceFormat format
= SurfaceFormatForPixelFormat(mGraphicBuffer
->getPixelFormat());
286 long pixelStride
= mGraphicBuffer
->getStride();
287 long byteStride
= pixelStride
* BytesPerPixel(format
);
288 mDrawTarget
= gfxPlatform::GetPlatform()->CreateDrawTargetForData(GetBuffer(),
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
),
308 SurfaceFormatToImageFormat(mFormat
));
309 return surface
.forget();
313 GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize
,
314 TextureAllocationFlags
)
316 MOZ_ASSERT(IsValid());
319 uint32_t usage
= android::GraphicBuffer::USAGE_SW_READ_OFTEN
|
320 android::GraphicBuffer::USAGE_SW_WRITE_OFTEN
|
321 android::GraphicBuffer::USAGE_HW_TEXTURE
;
324 case gfx::SurfaceFormat::R8G8B8A8
:
325 format
= android::PIXEL_FORMAT_RGBA_8888
;
327 case gfx::SurfaceFormat::B8G8R8A8
:
328 format
= android::PIXEL_FORMAT_RGBA_8888
;
329 mFlags
|= TEXTURE_RB_SWAPPED
;
331 case gfx::SurfaceFormat::R8G8B8X8
:
332 format
= android::PIXEL_FORMAT_RGBX_8888
;
334 case gfx::SurfaceFormat::B8G8R8X8
:
335 format
= android::PIXEL_FORMAT_RGBX_8888
;
336 mFlags
|= TEXTURE_RB_SWAPPED
;
338 case gfx::SurfaceFormat::R5G6B5
:
339 format
= android::PIXEL_FORMAT_RGB_565
;
341 case gfx::SurfaceFormat::A8
:
342 NS_WARNING("gralloc does not support gfx::SurfaceFormat::A8");
345 NS_WARNING("Unsupported surface format");
349 return AllocateGralloc(aSize
, format
, usage
);
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
);
362 GrallocTextureClientOGL::AllocateForGLRendering(gfx::IntSize aSize
)
364 MOZ_ASSERT(IsValid());
367 uint32_t usage
= android::GraphicBuffer::USAGE_HW_RENDER
|
368 android::GraphicBuffer::USAGE_HW_TEXTURE
;
371 case gfx::SurfaceFormat::R8G8B8A8
:
372 case gfx::SurfaceFormat::B8G8R8A8
:
373 format
= android::PIXEL_FORMAT_RGBA_8888
;
375 case gfx::SurfaceFormat::R8G8B8X8
:
376 case gfx::SurfaceFormat::B8G8R8X8
:
377 // there is no android BGRX format?
378 format
= android::PIXEL_FORMAT_RGBX_8888
;
380 case gfx::SurfaceFormat::R5G6B5
:
381 format
= android::PIXEL_FORMAT_RGB_565
;
384 NS_WARNING("Unsupported surface format");
388 return AllocateGralloc(aSize
, format
, usage
);
392 GrallocTextureClientOGL::AllocateGralloc(gfx::IntSize aSize
,
393 uint32_t aAndroidFormat
,
396 MOZ_ASSERT(IsValid());
397 ISurfaceAllocator
* allocator
= GetAllocator();
399 MaybeMagicGrallocBufferHandle handle
;
400 PGrallocBufferChild
* actor
=
401 allocator
->AllocGrallocBuffer(aSize
,
408 GrallocBufferActor
* gba
= static_cast<GrallocBufferActor
*>(actor
);
409 gba
->InitFromHandle(handle
.get_MagicGrallocBufferHandle());
411 sp
<GraphicBuffer
> graphicBuffer
= gba
->GetGraphicBuffer();
412 if (!graphicBuffer
.get()) {
416 if (graphicBuffer
->initCheck() != NO_ERROR
) {
421 mGraphicBuffer
= graphicBuffer
;
427 GrallocTextureClientOGL::IsAllocated() const
429 return !!mGraphicBuffer
.get();
433 GrallocTextureClientOGL::Allocate(uint32_t aSize
)
436 MOZ_CRASH("This method should never be called.");
441 GrallocTextureClientOGL::GetBufferSize() const
444 MOZ_CRASH("This method should never be called.");
448 } // namesapace layers
449 } // namesapace mozilla
451 #endif // MOZ_WIDGET_GONK