1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
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 "SharedSurfaceAndroidHardwareBuffer.h"
8 #include "GLBlitHelper.h"
9 #include "GLContextEGL.h"
10 #include "GLContextProvider.h"
11 #include "GLLibraryEGL.h"
12 #include "GLReadTexImageHelper.h"
13 #include "MozFramebuffer.h"
14 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
15 #include "mozilla/layers/AndroidHardwareBuffer.h"
16 #include "ScopedGLHelpers.h"
17 #include "SharedSurface.h"
23 UniquePtr
<SharedSurface_AndroidHardwareBuffer
>
24 SharedSurface_AndroidHardwareBuffer::Create(const SharedSurfaceDesc
& desc
) {
25 const auto& gle
= GLContextEGL::Cast(desc
.gl
);
26 const auto& egl
= gle
->mEgl
;
28 RefPtr
<layers::AndroidHardwareBuffer
> buffer
=
29 layers::AndroidHardwareBuffer::Create(desc
.size
,
30 gfx::SurfaceFormat::R8G8B8A8
);
35 const EGLint attrs
[] = {
36 LOCAL_EGL_IMAGE_PRESERVED
,
42 EGLClientBuffer clientBuffer
=
43 egl
->mLib
->fGetNativeClientBufferANDROID(buffer
->GetNativeBuffer());
44 const auto image
= egl
->fCreateImage(
45 EGL_NO_CONTEXT
, LOCAL_EGL_NATIVE_BUFFER_ANDROID
, clientBuffer
, attrs
);
50 auto tex
= MakeUnique
<Texture
>(*desc
.gl
);
52 ScopedBindTexture
texture(gle
, tex
->name
, LOCAL_GL_TEXTURE_2D
);
53 gle
->fTexParameteri(LOCAL_GL_TEXTURE_2D
, LOCAL_GL_TEXTURE_MIN_FILTER
,
55 gle
->fTexParameteri(LOCAL_GL_TEXTURE_2D
, LOCAL_GL_TEXTURE_MAG_FILTER
,
57 gle
->fTexParameteri(LOCAL_GL_TEXTURE_2D
, LOCAL_GL_TEXTURE_WRAP_S
,
58 LOCAL_GL_CLAMP_TO_EDGE
);
59 gle
->fTexParameteri(LOCAL_GL_TEXTURE_2D
, LOCAL_GL_TEXTURE_WRAP_T
,
60 LOCAL_GL_CLAMP_TO_EDGE
);
61 gle
->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D
, image
);
62 egl
->fDestroyImage(image
);
65 const GLenum target
= LOCAL_GL_TEXTURE_2D
;
66 auto fb
= MozFramebuffer::CreateForBacking(desc
.gl
, desc
.size
, 0, false,
72 return AsUnique(new SharedSurface_AndroidHardwareBuffer(
73 desc
, std::move(fb
), std::move(tex
), buffer
));
76 SharedSurface_AndroidHardwareBuffer::SharedSurface_AndroidHardwareBuffer(
77 const SharedSurfaceDesc
& desc
, UniquePtr
<MozFramebuffer
> fb
,
78 UniquePtr
<Texture
> tex
, RefPtr
<layers::AndroidHardwareBuffer
> buffer
)
79 : SharedSurface(desc
, std::move(fb
)),
81 mAndroidHardwareBuffer(buffer
) {}
83 SharedSurface_AndroidHardwareBuffer::~SharedSurface_AndroidHardwareBuffer() {
84 const auto& gl
= mDesc
.gl
;
85 if (!gl
|| !gl
->MakeCurrent()) {
88 const auto& gle
= GLContextEGL::Cast(gl
);
89 const auto& egl
= gle
->mEgl
;
92 egl
->fDestroySync(mSync
);
97 void SharedSurface_AndroidHardwareBuffer::ProducerReleaseImpl() {
98 const auto& gl
= mDesc
.gl
;
99 if (!gl
|| !gl
->MakeCurrent()) {
102 const auto& gle
= GLContextEGL::Cast(gl
);
103 const auto& egl
= gle
->mEgl
;
106 MOZ_ALWAYS_TRUE(egl
->fDestroySync(mSync
));
110 mSync
= egl
->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID
, nullptr);
112 int rawFd
= egl
->fDupNativeFenceFDANDROID(mSync
);
114 auto fenceFd
= ipc::FileDescriptor(UniqueFileHandle(rawFd
));
115 mAndroidHardwareBuffer
->SetAcquireFence(std::move(fenceFd
));
121 Maybe
<layers::SurfaceDescriptor
>
122 SharedSurface_AndroidHardwareBuffer::ToSurfaceDescriptor() {
123 return Some(layers::SurfaceDescriptorAndroidHardwareBuffer(
124 mAndroidHardwareBuffer
->mId
, mAndroidHardwareBuffer
->mSize
,
125 mAndroidHardwareBuffer
->mFormat
));
128 void SharedSurface_AndroidHardwareBuffer::WaitForBufferOwnership() {
129 ipc::FileDescriptor fenceFd
=
130 mAndroidHardwareBuffer
->GetAndResetReleaseFence();
131 if (!fenceFd
.IsValid()) {
135 const auto& gle
= GLContextEGL::Cast(mDesc
.gl
);
136 const auto& egl
= gle
->mEgl
;
138 auto rawFD
= fenceFd
.TakePlatformHandle();
139 const EGLint attribs
[] = {LOCAL_EGL_SYNC_NATIVE_FENCE_FD_ANDROID
, rawFD
.get(),
142 EGLSync sync
= egl
->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID
, attribs
);
144 gfxCriticalNote
<< "Failed to create EGLSync from fd";
147 // Release fd here, since it is owned by EGLSync
148 Unused
<< rawFD
.release();
150 egl
->fClientWaitSync(sync
, 0, LOCAL_EGL_FOREVER
);
151 egl
->fDestroySync(sync
);
155 UniquePtr
<SurfaceFactory_AndroidHardwareBuffer
>
156 SurfaceFactory_AndroidHardwareBuffer::Create(GLContext
& gl
) {
157 const auto partialDesc
= PartialSharedSurfaceDesc
{
159 SharedSurfaceType::AndroidHardwareBuffer
,
160 layers::TextureType::AndroidHardwareBuffer
,
163 return AsUnique(new SurfaceFactory_AndroidHardwareBuffer(partialDesc
));
168 } /* namespace mozilla */