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/webrender/RenderThread.h"
11 #include "mozilla/gfx/2D.h"
12 #include "GLContextEGL.h"
13 #include "GLLibraryEGL.h"
14 #include "GLReadTexImageHelper.h"
15 #include "OGLShaderConfig.h"
20 RenderAndroidHardwareBufferTextureHost::RenderAndroidHardwareBufferTextureHost(
21 layers::AndroidHardwareBuffer
* aAndroidHardwareBuffer
)
22 : mAndroidHardwareBuffer(aAndroidHardwareBuffer
),
23 mEGLImage(EGL_NO_IMAGE
),
25 MOZ_ASSERT(mAndroidHardwareBuffer
);
26 MOZ_COUNT_CTOR_INHERITED(RenderAndroidHardwareBufferTextureHost
,
30 RenderAndroidHardwareBufferTextureHost::
31 ~RenderAndroidHardwareBufferTextureHost() {
32 MOZ_COUNT_DTOR_INHERITED(RenderAndroidHardwareBufferTextureHost
,
34 DeleteTextureHandle();
38 gfx::IntSize
RenderAndroidHardwareBufferTextureHost::GetSize() const {
39 if (mAndroidHardwareBuffer
) {
40 return mAndroidHardwareBuffer
->mSize
;
42 return gfx::IntSize();
45 bool RenderAndroidHardwareBufferTextureHost::EnsureLockable() {
46 if (!mAndroidHardwareBuffer
) {
50 auto fenceFd
= mAndroidHardwareBuffer
->GetAndResetAcquireFence();
51 if (fenceFd
.IsValid()) {
52 const auto& gle
= gl::GLContextEGL::Cast(mGL
);
53 const auto& egl
= gle
->mEgl
;
55 auto rawFD
= fenceFd
.TakePlatformHandle();
56 const EGLint attribs
[] = {LOCAL_EGL_SYNC_NATIVE_FENCE_FD_ANDROID
,
57 rawFD
.get(), LOCAL_EGL_NONE
};
60 egl
->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID
, attribs
);
62 // Release fd here, since it is owned by EGLSync
63 Unused
<< rawFD
.release();
65 if (egl
->IsExtensionSupported(gl::EGLExtension::KHR_wait_sync
)) {
66 egl
->fWaitSync(sync
, 0);
68 egl
->fClientWaitSync(sync
, 0, LOCAL_EGL_FOREVER
);
70 egl
->fDestroySync(sync
);
72 gfxCriticalNote
<< "Failed to create EGLSync from acquire fence fd";
81 // XXX add crop handling for video
82 // Should only happen the first time.
83 const auto& gle
= gl::GLContextEGL::Cast(mGL
);
84 const auto& egl
= gle
->mEgl
;
86 const EGLint attrs
[] = {
87 LOCAL_EGL_IMAGE_PRESERVED
,
93 EGLClientBuffer clientBuffer
= egl
->mLib
->fGetNativeClientBufferANDROID(
94 mAndroidHardwareBuffer
->GetNativeBuffer());
95 mEGLImage
= egl
->fCreateImage(
96 EGL_NO_CONTEXT
, LOCAL_EGL_NATIVE_BUFFER_ANDROID
, clientBuffer
, attrs
);
98 MOZ_ASSERT(mEGLImage
);
100 mGL
->fGenTextures(1, &mTextureHandle
);
101 mGL
->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL
, mTextureHandle
);
102 mGL
->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL
, LOCAL_GL_TEXTURE_WRAP_T
,
103 LOCAL_GL_CLAMP_TO_EDGE
);
104 mGL
->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL
, LOCAL_GL_TEXTURE_WRAP_S
,
105 LOCAL_GL_CLAMP_TO_EDGE
);
106 mGL
->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_EXTERNAL
, mEGLImage
);
108 ActivateBindAndTexParameteri(mGL
, LOCAL_GL_TEXTURE0
,
109 LOCAL_GL_TEXTURE_EXTERNAL_OES
, mTextureHandle
);
113 wr::WrExternalImage
RenderAndroidHardwareBufferTextureHost::Lock(
114 uint8_t aChannelIndex
, gl::GLContext
* aGL
) {
115 MOZ_ASSERT(aChannelIndex
== 0);
117 if (mGL
.get() != aGL
) {
119 // This should not happen.
120 MOZ_ASSERT_UNREACHABLE("Unexpected GL context");
121 return InvalidToWrExternalImage();
126 if (!mGL
|| !mGL
->MakeCurrent()) {
127 return InvalidToWrExternalImage();
130 if (!EnsureLockable()) {
131 return InvalidToWrExternalImage();
134 const auto uvs
= GetUvCoords(GetSize());
135 return NativeTextureToWrExternalImage(
136 mTextureHandle
, uvs
.first
.x
, uvs
.first
.y
, uvs
.second
.x
, uvs
.second
.y
);
139 void RenderAndroidHardwareBufferTextureHost::Unlock() {}
141 size_t RenderAndroidHardwareBufferTextureHost::Bytes() {
142 return GetSize().width
* GetSize().height
*
143 BytesPerPixel(mAndroidHardwareBuffer
->mFormat
);
146 void RenderAndroidHardwareBufferTextureHost::DeleteTextureHandle() {
147 if (!mTextureHandle
) {
151 mGL
->fDeleteTextures(1, &mTextureHandle
);
155 void RenderAndroidHardwareBufferTextureHost::DestroyEGLImage() {
160 const auto& gle
= gl::GLContextEGL::Cast(mGL
);
161 const auto& egl
= gle
->mEgl
;
162 egl
->fDestroyImage(mEGLImage
);
163 mEGLImage
= EGL_NO_IMAGE
;
166 gfx::SurfaceFormat
RenderAndroidHardwareBufferTextureHost::GetFormat() const {
167 MOZ_ASSERT(mAndroidHardwareBuffer
->mFormat
== gfx::SurfaceFormat::R8G8B8A8
||
168 mAndroidHardwareBuffer
->mFormat
== gfx::SurfaceFormat::R8G8B8X8
);
170 if (mAndroidHardwareBuffer
->mFormat
== gfx::SurfaceFormat::R8G8B8A8
) {
171 return gfx::SurfaceFormat::B8G8R8A8
;
174 if (mAndroidHardwareBuffer
->mFormat
== gfx::SurfaceFormat::R8G8B8X8
) {
175 return gfx::SurfaceFormat::B8G8R8X8
;
179 << "Unexpected color format of RenderAndroidSurfaceTextureHost";
181 return gfx::SurfaceFormat::UNKNOWN
;
184 already_AddRefed
<gfx::DataSourceSurface
>
185 RenderAndroidHardwareBufferTextureHost::ReadTexImage() {
187 mGL
= RenderThread::Get()->SingletonGL();
193 if (!EnsureLockable()) {
197 /* Allocate resulting image surface */
198 int32_t stride
= GetSize().width
* BytesPerPixel(GetFormat());
199 RefPtr
<gfx::DataSourceSurface
> surf
=
200 gfx::Factory::CreateDataSourceSurfaceWithStride(GetSize(), GetFormat(),
206 layers::ShaderConfigOGL config
= layers::ShaderConfigFromTargetAndFormat(
207 LOCAL_GL_TEXTURE_EXTERNAL
, mAndroidHardwareBuffer
->mFormat
);
208 int shaderConfig
= config
.mFeatures
;
210 bool ret
= mGL
->ReadTexImageHelper()->ReadTexImage(
211 surf
, mTextureHandle
, LOCAL_GL_TEXTURE_EXTERNAL
, GetSize(), shaderConfig
,
212 /* aYInvert */ false);
217 return surf
.forget();
220 bool RenderAndroidHardwareBufferTextureHost::MapPlane(
221 RenderCompositor
* aCompositor
, uint8_t aChannelIndex
,
222 PlaneInfo
& aPlaneInfo
) {
223 RefPtr
<gfx::DataSourceSurface
> readback
= ReadTexImage();
228 gfx::DataSourceSurface::MappedSurface map
;
229 if (!readback
->Map(gfx::DataSourceSurface::MapType::READ
, &map
)) {
233 mReadback
= readback
;
234 aPlaneInfo
.mSize
= GetSize();
235 aPlaneInfo
.mStride
= map
.mStride
;
236 aPlaneInfo
.mData
= map
.mData
;
240 void RenderAndroidHardwareBufferTextureHost::UnmapPlanes() {
248 } // namespace mozilla