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 #include "base/process.h"
9 #include <ui/GraphicBuffer.h>
10 #include "GrallocImages.h" // for GrallocImage
11 #include "mozilla/layers/GrallocTextureHost.h"
12 #include "mozilla/layers/CompositorOGL.h"
13 #include "mozilla/layers/SharedBufferManagerParent.h"
14 #include "EGLImageHelpers.h"
15 #include "GLReadTexImageHelper.h"
20 using namespace android
;
22 static gfx::SurfaceFormat
23 SurfaceFormatForAndroidPixelFormat(android::PixelFormat aFormat
,
26 bool swapRB
= bool(aFlags
& TextureFlags::RB_SWAPPED
);
28 case android::PIXEL_FORMAT_BGRA_8888
:
29 return swapRB
? gfx::SurfaceFormat::R8G8B8A8
: gfx::SurfaceFormat::B8G8R8A8
;
30 case android::PIXEL_FORMAT_RGBA_8888
:
31 return swapRB
? gfx::SurfaceFormat::B8G8R8A8
: gfx::SurfaceFormat::R8G8B8A8
;
32 case android::PIXEL_FORMAT_RGBX_8888
:
33 return swapRB
? gfx::SurfaceFormat::B8G8R8X8
: gfx::SurfaceFormat::R8G8B8X8
;
34 case android::PIXEL_FORMAT_RGB_565
:
35 return gfx::SurfaceFormat::R5G6B5
;
36 case HAL_PIXEL_FORMAT_YCbCr_422_SP
:
37 case HAL_PIXEL_FORMAT_YCrCb_420_SP
:
38 case HAL_PIXEL_FORMAT_YCbCr_422_I
:
39 case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED
:
40 case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS
:
41 case HAL_PIXEL_FORMAT_YV12
:
42 return gfx::SurfaceFormat::R8G8B8A8
; // yup, use SurfaceFormat::R8G8B8A8 even though it's a YUV texture. This is an external texture.
44 if (aFormat
>= 0x100 && aFormat
<= 0x1FF) {
45 // Reserved range for HAL specific formats.
46 return gfx::SurfaceFormat::R8G8B8A8
;
48 // This is not super-unreachable, there's a bunch of hypothetical pixel
49 // formats we don't deal with.
50 // We only want to abort in debug builds here, since if we crash here
51 // we'll take down the compositor process and thus the phone. This seems
52 // like undesirable behaviour. We'd rather have a subtle artifact.
53 printf_stderr(" xxxxx unknow android format %i\n", (int)aFormat
);
54 MOZ_ASSERT(false, "Unknown Android pixel format.");
55 return gfx::SurfaceFormat::UNKNOWN
;
61 TextureTargetForAndroidPixelFormat(android::PixelFormat aFormat
)
64 case HAL_PIXEL_FORMAT_YCbCr_422_SP
:
65 case HAL_PIXEL_FORMAT_YCrCb_420_SP
:
66 case HAL_PIXEL_FORMAT_YCbCr_422_I
:
67 case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED
:
68 case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS
:
69 case HAL_PIXEL_FORMAT_YV12
:
70 return LOCAL_GL_TEXTURE_EXTERNAL
;
71 case android::PIXEL_FORMAT_BGRA_8888
:
72 case android::PIXEL_FORMAT_RGBA_8888
:
73 case android::PIXEL_FORMAT_RGBX_8888
:
74 case android::PIXEL_FORMAT_RGB_565
:
75 return LOCAL_GL_TEXTURE_2D
;
77 if (aFormat
>= 0x100 && aFormat
<= 0x1FF) {
78 // Reserved range for HAL specific formats.
79 return LOCAL_GL_TEXTURE_EXTERNAL
;
81 // This is not super-unreachable, there's a bunch of hypothetical pixel
82 // formats we don't deal with.
83 // We only want to abort in debug builds here, since if we crash here
84 // we'll take down the compositor process and thus the phone. This seems
85 // like undesirable behaviour. We'd rather have a subtle artifact.
86 MOZ_ASSERT(false, "Unknown Android pixel format.");
87 return LOCAL_GL_TEXTURE_EXTERNAL
;
92 GrallocTextureSourceOGL::GrallocTextureSourceOGL(CompositorOGL
* aCompositor
,
93 GrallocTextureHostOGL
* aTextureHost
,
94 android::GraphicBuffer
* aGraphicBuffer
,
95 gfx::SurfaceFormat aFormat
)
96 : mCompositor(aCompositor
)
97 , mTextureHost(aTextureHost
)
98 , mGraphicBuffer(aGraphicBuffer
)
103 MOZ_ASSERT(mGraphicBuffer
.get());
106 GrallocTextureSourceOGL::~GrallocTextureSourceOGL()
108 DeallocateDeviceData();
109 mCompositor
= nullptr;
113 GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit
, gfx::Filter aFilter
)
116 * The job of this function is to ensure that the texture is tied to the
117 * android::GraphicBuffer, so that texturing will source the GraphicBuffer.
119 * To this effect we create an EGLImage wrapping this GraphicBuffer,
120 * using EGLImageCreateFromNativeBuffer, and then we tie this EGLImage to our
121 * texture using fEGLImageTargetTexture2D.
129 GLuint tex
= GetGLTexture();
130 GLuint textureTarget
= GetTextureTarget();
132 gl()->fActiveTexture(aTextureUnit
);
133 gl()->fBindTexture(textureTarget
, tex
);
135 if (mCompositableBackendData
) {
136 // There are two paths for locking/unlocking - if mCompositableBackendData is
137 // set, we use the texture on there, otherwise we use
138 // CompositorBackendSpecificData from the compositor and bind the EGLImage
141 mEGLImage
= EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer
->getNativeBuffer());
146 ApplyFilterToBoundTexture(gl(), aFilter
, textureTarget
);
148 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
150 // Wait until it's ready.
151 mTextureHost
->WaitAcquireFenceSyncComplete();
156 void GrallocTextureSourceOGL::Lock()
158 if (mCompositableBackendData
) return;
160 MOZ_ASSERT(IsValid());
162 mTexture
= mCompositor
->GetTemporaryTexture(GetTextureTarget(), LOCAL_GL_TEXTURE0
);
164 GLuint textureTarget
= GetTextureTarget();
167 gl()->fActiveTexture(LOCAL_GL_TEXTURE0
);
168 gl()->fBindTexture(textureTarget
, mTexture
);
170 mEGLImage
= EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer
->getNativeBuffer());
172 gl()->fEGLImageTargetTexture2D(textureTarget
, mEGLImage
);
176 GrallocTextureSourceOGL::IsValid() const
178 return !!gl() && !!mGraphicBuffer
.get() && (!!mCompositor
|| !!mCompositableBackendData
);
182 GrallocTextureSourceOGL::gl() const
184 return mCompositor
? mCompositor
->gl() : nullptr;
188 GrallocTextureSourceOGL::SetCompositor(Compositor
* aCompositor
)
190 if (mCompositor
&& !aCompositor
) {
191 DeallocateDeviceData();
193 mCompositor
= static_cast<CompositorOGL
*>(aCompositor
);
198 GrallocTextureSourceOGL::GetTextureTarget() const
201 MOZ_ASSERT(mGraphicBuffer
.get());
203 if (!gl() || !mGraphicBuffer
.get()) {
204 return LOCAL_GL_TEXTURE_EXTERNAL
;
207 // SGX has a quirk that only TEXTURE_EXTERNAL works and any other value will
208 // result in black pixels when trying to draw from bound textures.
209 // Unfortunately, using TEXTURE_EXTERNAL on Adreno has a terrible effect on
212 if (gl()->Renderer() == gl::GLRenderer::SGX530
||
213 gl()->Renderer() == gl::GLRenderer::SGX540
) {
214 return LOCAL_GL_TEXTURE_EXTERNAL
;
217 return TextureTargetForAndroidPixelFormat(mGraphicBuffer
->getPixelFormat());
221 GrallocTextureSourceOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData
* aBackendData
)
224 DeallocateDeviceData();
225 // Update mCompositableBackendData after calling DeallocateDeviceData().
226 mCompositableBackendData
= nullptr;
230 if (mCompositableBackendData
!= aBackendData
) {
235 // Update binding to the EGLImage
237 GLuint tex
= GetGLTexture();
238 GLuint textureTarget
= GetTextureTarget();
239 gl()->fActiveTexture(LOCAL_GL_TEXTURE0
);
240 gl()->fBindTexture(textureTarget
, tex
);
246 mCompositableBackendData
= aBackendData
;
250 // delete old EGLImage
251 DeallocateDeviceData();
253 // Update mCompositableBackendData after calling DeallocateDeviceData().
254 mCompositableBackendData
= aBackendData
;
257 GLuint tex
= GetGLTexture();
258 GLuint textureTarget
= GetTextureTarget();
260 gl()->fActiveTexture(LOCAL_GL_TEXTURE0
);
261 gl()->fBindTexture(textureTarget
, tex
);
262 // create new EGLImage
263 mEGLImage
= EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer
->getNativeBuffer());
269 GrallocTextureSourceOGL::GetSize() const
272 NS_WARNING("Trying to access the size of an invalid GrallocTextureSourceOGL");
273 return gfx::IntSize(0, 0);
275 return gfx::IntSize(mGraphicBuffer
->getWidth(), mGraphicBuffer
->getHeight());
279 GrallocTextureSourceOGL::DeallocateDeviceData()
284 if (mCompositableBackendData
) {
285 CompositableDataGonkOGL
* backend
= static_cast<CompositableDataGonkOGL
*>(mCompositableBackendData
.get());
286 backend
->ClearBoundEGLImage(mEGLImage
);
288 EGLImageDestroy(gl(), mEGLImage
);
289 mEGLImage
= EGL_NO_IMAGE
;
293 GrallocTextureHostOGL::GrallocTextureHostOGL(TextureFlags aFlags
,
294 const NewSurfaceDescriptorGralloc
& aDescriptor
)
295 : TextureHost(aFlags
)
297 gfx::SurfaceFormat format
= gfx::SurfaceFormat::UNKNOWN
;
298 mGrallocHandle
= aDescriptor
;
300 android::GraphicBuffer
* graphicBuffer
= GetGraphicBufferFromDesc(mGrallocHandle
).get();
301 MOZ_ASSERT(graphicBuffer
);
303 mSize
= aDescriptor
.size();
306 SurfaceFormatForAndroidPixelFormat(graphicBuffer
->getPixelFormat(),
307 aFlags
& TextureFlags::RB_SWAPPED
);
309 NS_WARNING("gralloc buffer is nullptr");
311 mTextureSource
= new GrallocTextureSourceOGL(nullptr,
317 GrallocTextureHostOGL::~GrallocTextureHostOGL()
319 mTextureSource
= nullptr;
323 GrallocTextureHostOGL::SetCompositor(Compositor
* aCompositor
)
325 mTextureSource
->SetCompositor(static_cast<CompositorOGL
*>(aCompositor
));
329 GrallocTextureHostOGL::Lock()
332 mTextureSource
->Lock();
339 GrallocTextureHostOGL::Unlock()
341 // Unlock is done internally by binding the texture to another gralloc buffer
345 GrallocTextureHostOGL::IsValid() const
347 return mTextureSource
->IsValid();
351 GrallocTextureHostOGL::GetFormat() const
353 return mTextureSource
->GetFormat();
357 GrallocTextureHostOGL::DeallocateSharedData()
359 if (mTextureSource
) {
360 mTextureSource
->ForgetBuffer();
362 if (mGrallocHandle
.buffer().type() != SurfaceDescriptor::Tnull_t
) {
363 MaybeMagicGrallocBufferHandle handle
= mGrallocHandle
.buffer();
364 base::ProcessId owner
;
365 if (handle
.type() == MaybeMagicGrallocBufferHandle::TGrallocBufferRef
) {
366 owner
= handle
.get_GrallocBufferRef().mOwner
;
369 owner
= handle
.get_MagicGrallocBufferHandle().mRef
.mOwner
;
372 SharedBufferManagerParent::GetInstance(owner
)->DropGrallocBuffer(mGrallocHandle
);
377 GrallocTextureHostOGL::ForgetSharedData()
379 if (mTextureSource
) {
380 mTextureSource
->ForgetBuffer();
385 GrallocTextureHostOGL::DeallocateDeviceData()
387 mTextureSource
->DeallocateDeviceData();
391 GrallocTextureHostOGL::GetRenderState()
394 LayerRenderStateFlags flags
= LayerRenderStateFlags::LAYER_RENDER_STATE_DEFAULT
;
395 if (mFlags
& TextureFlags::NEEDS_Y_FLIP
) {
396 flags
|= LayerRenderStateFlags::Y_FLIPPED
;
398 if (mFlags
& TextureFlags::RB_SWAPPED
) {
399 flags
|= LayerRenderStateFlags::FORMAT_RB_SWAP
;
401 return LayerRenderState(mTextureSource
->mGraphicBuffer
.get(),
402 gfx::ThebesIntSize(mSize
),
407 return LayerRenderState();
410 TemporaryRef
<gfx::DataSourceSurface
>
411 GrallocTextureHostOGL::GetAsSurface() {
412 return mTextureSource
? mTextureSource
->GetAsSurface()
416 TemporaryRef
<gfx::DataSourceSurface
>
417 GrallocTextureSourceOGL::GetAsSurface() {
423 GLuint tex
= GetGLTexture();
424 gl()->fActiveTexture(LOCAL_GL_TEXTURE0
);
425 gl()->fBindTexture(GetTextureTarget(), tex
);
427 mEGLImage
= EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer
->getNativeBuffer());
431 RefPtr
<gfx::DataSourceSurface
> surf
=
432 IsValid() ? ReadBackSurface(gl(), tex
, false, GetFormat())
435 gl()->fActiveTexture(LOCAL_GL_TEXTURE0
);
436 return surf
.forget();
440 GrallocTextureSourceOGL::GetGLTexture()
442 if (mCompositableBackendData
) {
443 mCompositableBackendData
->SetCompositor(mCompositor
);
444 return static_cast<CompositableDataGonkOGL
*>(mCompositableBackendData
.get())->GetTexture();
451 GrallocTextureSourceOGL::BindEGLImage()
453 if (mCompositableBackendData
) {
454 CompositableDataGonkOGL
* backend
= static_cast<CompositableDataGonkOGL
*>(mCompositableBackendData
.get());
455 backend
->BindEGLImage(GetTextureTarget(), mEGLImage
);
457 gl()->fEGLImageTargetTexture2D(GetTextureTarget(), mEGLImage
);
462 GrallocTextureHostOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData
* aBackendData
)
464 mCompositableBackendData
= aBackendData
;
465 if (mTextureSource
) {
466 mTextureSource
->SetCompositableBackendSpecificData(aBackendData
);
470 } // namepsace layers
471 } // namepsace mozilla