1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "RenderAndroidHardwareBufferTextureHost.h"
9 #include "mozilla/layers/AndroidHardwareBuffer.h"
10 #include "mozilla/layers/TextureHostOGL.h"
11 #include "mozilla/webrender/RenderThread.h"
12 #include "mozilla/gfx/2D.h"
13 #include "GLContextEGL.h"
14 #include "GLLibraryEGL.h"
15 #include "GLReadTexImageHelper.h"
16 #include "OGLShaderConfig.h"
21 RenderAndroidHardwareBufferTextureHost::RenderAndroidHardwareBufferTextureHost(
22 layers::AndroidHardwareBuffer
* aAndroidHardwareBuffer
)
23 : mAndroidHardwareBuffer(aAndroidHardwareBuffer
),
24 mEGLImage(EGL_NO_IMAGE
),
26 MOZ_ASSERT(mAndroidHardwareBuffer
);
27 MOZ_COUNT_CTOR_INHERITED(RenderAndroidHardwareBufferTextureHost
,
31 RenderAndroidHardwareBufferTextureHost::
32 ~RenderAndroidHardwareBufferTextureHost() {
33 MOZ_COUNT_DTOR_INHERITED(RenderAndroidHardwareBufferTextureHost
,
35 DeleteTextureHandle();
39 gfx::IntSize
RenderAndroidHardwareBufferTextureHost::GetSize() const {
40 if (mAndroidHardwareBuffer
) {
41 return mAndroidHardwareBuffer
->mSize
;
43 return gfx::IntSize();
46 bool RenderAndroidHardwareBufferTextureHost::EnsureLockable() {
47 if (!mAndroidHardwareBuffer
) {
51 auto fenceFd
= mAndroidHardwareBuffer
->GetAndResetAcquireFence();
52 if (fenceFd
.IsValid()) {
53 const auto& gle
= gl::GLContextEGL::Cast(mGL
);
54 const auto& egl
= gle
->mEgl
;
56 auto rawFD
= fenceFd
.TakePlatformHandle();
57 const EGLint attribs
[] = {LOCAL_EGL_SYNC_NATIVE_FENCE_FD_ANDROID
,
58 rawFD
.get(), LOCAL_EGL_NONE
};
61 egl
->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID
, attribs
);
63 // Release fd here, since it is owned by EGLSync
64 Unused
<< rawFD
.release();
66 if (egl
->IsExtensionSupported(gl::EGLExtension::KHR_wait_sync
)) {
67 egl
->fWaitSync(sync
, 0);
69 egl
->fClientWaitSync(sync
, 0, LOCAL_EGL_FOREVER
);
71 egl
->fDestroySync(sync
);
73 gfxCriticalNote
<< "Failed to create EGLSync from acquire fence fd";
82 // XXX add crop handling for video
83 // Should only happen the first time.
84 const auto& gle
= gl::GLContextEGL::Cast(mGL
);
85 const auto& egl
= gle
->mEgl
;
87 const EGLint attrs
[] = {
88 LOCAL_EGL_IMAGE_PRESERVED
,
94 EGLClientBuffer clientBuffer
= egl
->mLib
->fGetNativeClientBufferANDROID(
95 mAndroidHardwareBuffer
->GetNativeBuffer());
96 mEGLImage
= egl
->fCreateImage(
97 EGL_NO_CONTEXT
, LOCAL_EGL_NATIVE_BUFFER_ANDROID
, clientBuffer
, attrs
);
99 MOZ_ASSERT(mEGLImage
);
101 mGL
->fGenTextures(1, &mTextureHandle
);
102 mGL
->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL
, mTextureHandle
);
103 mGL
->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL
, LOCAL_GL_TEXTURE_WRAP_T
,
104 LOCAL_GL_CLAMP_TO_EDGE
);
105 mGL
->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL
, LOCAL_GL_TEXTURE_WRAP_S
,
106 LOCAL_GL_CLAMP_TO_EDGE
);
107 mGL
->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_EXTERNAL
, mEGLImage
);
109 ActivateBindAndTexParameteri(mGL
, LOCAL_GL_TEXTURE0
,
110 LOCAL_GL_TEXTURE_EXTERNAL_OES
, mTextureHandle
);
114 wr::WrExternalImage
RenderAndroidHardwareBufferTextureHost::Lock(
115 uint8_t aChannelIndex
, gl::GLContext
* aGL
) {
116 MOZ_ASSERT(aChannelIndex
== 0);
118 if (mGL
.get() != aGL
) {
120 // This should not happen.
121 MOZ_ASSERT_UNREACHABLE("Unexpected GL context");
122 return InvalidToWrExternalImage();
127 if (!mGL
|| !mGL
->MakeCurrent()) {
128 return InvalidToWrExternalImage();
131 if (!EnsureLockable()) {
132 return InvalidToWrExternalImage();
135 const gfx::IntSize size
= GetSize();
136 return NativeTextureToWrExternalImage(mTextureHandle
, 0.0, 0.0,
137 static_cast<float>(size
.width
),
138 static_cast<float>(size
.height
));
141 void RenderAndroidHardwareBufferTextureHost::Unlock() {}
143 size_t RenderAndroidHardwareBufferTextureHost::Bytes() {
144 return GetSize().width
* GetSize().height
*
145 BytesPerPixel(mAndroidHardwareBuffer
->mFormat
);
148 void RenderAndroidHardwareBufferTextureHost::DeleteTextureHandle() {
149 if (!mTextureHandle
) {
153 mGL
->fDeleteTextures(1, &mTextureHandle
);
157 void RenderAndroidHardwareBufferTextureHost::DestroyEGLImage() {
162 const auto& gle
= gl::GLContextEGL::Cast(mGL
);
163 const auto& egl
= gle
->mEgl
;
164 egl
->fDestroyImage(mEGLImage
);
165 mEGLImage
= EGL_NO_IMAGE
;
168 gfx::SurfaceFormat
RenderAndroidHardwareBufferTextureHost::GetFormat() const {
169 MOZ_ASSERT(mAndroidHardwareBuffer
->mFormat
== gfx::SurfaceFormat::R8G8B8A8
||
170 mAndroidHardwareBuffer
->mFormat
== gfx::SurfaceFormat::R8G8B8X8
);
172 if (mAndroidHardwareBuffer
->mFormat
== gfx::SurfaceFormat::R8G8B8A8
) {
173 return gfx::SurfaceFormat::B8G8R8A8
;
176 if (mAndroidHardwareBuffer
->mFormat
== gfx::SurfaceFormat::R8G8B8X8
) {
177 return gfx::SurfaceFormat::B8G8R8X8
;
181 << "Unexpected color format of RenderAndroidSurfaceTextureHost";
183 return gfx::SurfaceFormat::UNKNOWN
;
186 already_AddRefed
<gfx::DataSourceSurface
>
187 RenderAndroidHardwareBufferTextureHost::ReadTexImage() {
189 mGL
= RenderThread::Get()->SingletonGL();
195 if (!EnsureLockable()) {
199 /* Allocate resulting image surface */
200 int32_t stride
= GetSize().width
* BytesPerPixel(GetFormat());
201 RefPtr
<gfx::DataSourceSurface
> surf
=
202 gfx::Factory::CreateDataSourceSurfaceWithStride(GetSize(), GetFormat(),
208 layers::ShaderConfigOGL config
= layers::ShaderConfigFromTargetAndFormat(
209 LOCAL_GL_TEXTURE_EXTERNAL
, mAndroidHardwareBuffer
->mFormat
);
210 int shaderConfig
= config
.mFeatures
;
212 bool ret
= mGL
->ReadTexImageHelper()->ReadTexImage(
213 surf
, mTextureHandle
, LOCAL_GL_TEXTURE_EXTERNAL
, GetSize(),
214 gfx::Matrix4x4(), shaderConfig
, /* aYInvert */ false);
219 return surf
.forget();
222 bool RenderAndroidHardwareBufferTextureHost::MapPlane(
223 RenderCompositor
* aCompositor
, uint8_t aChannelIndex
,
224 PlaneInfo
& aPlaneInfo
) {
225 RefPtr
<gfx::DataSourceSurface
> readback
= ReadTexImage();
230 gfx::DataSourceSurface::MappedSurface map
;
231 if (!readback
->Map(gfx::DataSourceSurface::MapType::READ
, &map
)) {
235 mReadback
= readback
;
236 aPlaneInfo
.mSize
= GetSize();
237 aPlaneInfo
.mStride
= map
.mStride
;
238 aPlaneInfo
.mData
= map
.mData
;
242 void RenderAndroidHardwareBufferTextureHost::UnmapPlanes() {
249 RefPtr
<layers::TextureSource
>
250 RenderAndroidHardwareBufferTextureHost::CreateTextureSource(
251 layers::TextureSourceProvider
* aProvider
) {
252 return new layers::AndroidHardwareBufferTextureSource(
253 aProvider
, mAndroidHardwareBuffer
, mAndroidHardwareBuffer
->mFormat
,
254 LOCAL_GL_TEXTURE_EXTERNAL
, LOCAL_GL_CLAMP_TO_EDGE
, GetSize());
258 } // namespace mozilla