Bug 1874684 - Part 28: Return DateDuration from DifferenceISODateTime. r=mgaudet
[gecko.git] / gfx / gl / SharedSurfaceAndroidHardwareBuffer.cpp
blob00f925ce7536912bf8d6e179e0b55e86d15b2001
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"
19 namespace mozilla {
20 namespace gl {
22 /*static*/
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);
31 if (!buffer) {
32 return nullptr;
35 const EGLint attrs[] = {
36 LOCAL_EGL_IMAGE_PRESERVED,
37 LOCAL_EGL_TRUE,
38 LOCAL_EGL_NONE,
39 LOCAL_EGL_NONE,
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);
46 if (!image) {
47 return nullptr;
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,
54 LOCAL_GL_LINEAR);
55 gle->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER,
56 LOCAL_GL_LINEAR);
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,
67 target, tex->name);
68 if (!fb) {
69 return nullptr;
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)),
80 mTex(std::move(tex)),
81 mAndroidHardwareBuffer(buffer) {}
83 SharedSurface_AndroidHardwareBuffer::~SharedSurface_AndroidHardwareBuffer() {
84 const auto& gl = mDesc.gl;
85 if (!gl || !gl->MakeCurrent()) {
86 return;
88 const auto& gle = GLContextEGL::Cast(gl);
89 const auto& egl = gle->mEgl;
91 if (mSync) {
92 egl->fDestroySync(mSync);
93 mSync = 0;
97 void SharedSurface_AndroidHardwareBuffer::ProducerReleaseImpl() {
98 const auto& gl = mDesc.gl;
99 if (!gl || !gl->MakeCurrent()) {
100 return;
102 const auto& gle = GLContextEGL::Cast(gl);
103 const auto& egl = gle->mEgl;
105 if (mSync) {
106 MOZ_ALWAYS_TRUE(egl->fDestroySync(mSync));
107 mSync = 0;
110 mSync = egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
111 MOZ_ASSERT(mSync);
112 int rawFd = egl->fDupNativeFenceFDANDROID(mSync);
113 if (rawFd >= 0) {
114 auto fenceFd = ipc::FileDescriptor(UniqueFileHandle(rawFd));
115 mAndroidHardwareBuffer->SetAcquireFence(std::move(fenceFd));
118 gl->fFlush();
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()) {
132 return;
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(),
140 LOCAL_EGL_NONE};
142 EGLSync sync = egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
143 if (!sync) {
144 gfxCriticalNote << "Failed to create EGLSync from fd";
145 return;
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);
154 /*static*/
155 UniquePtr<SurfaceFactory_AndroidHardwareBuffer>
156 SurfaceFactory_AndroidHardwareBuffer::Create(GLContext& gl) {
157 const auto partialDesc = PartialSharedSurfaceDesc{
158 &gl,
159 SharedSurfaceType::AndroidHardwareBuffer,
160 layers::TextureType::AndroidHardwareBuffer,
161 true,
163 return AsUnique(new SurfaceFactory_AndroidHardwareBuffer(partialDesc));
166 } // namespace gl
168 } /* namespace mozilla */