SharedSurfaceAndroidHardwareBuffer.cpp (5188B)
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/. */ 5 6 #include "SharedSurfaceAndroidHardwareBuffer.h" 7 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" 18 19 namespace mozilla { 20 namespace gl { 21 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; 27 28 RefPtr<layers::AndroidHardwareBuffer> buffer = 29 layers::AndroidHardwareBuffer::Create(desc.size, 30 gfx::SurfaceFormat::R8G8B8A8); 31 if (!buffer) { 32 return nullptr; 33 } 34 35 const EGLint attrs[] = { 36 LOCAL_EGL_IMAGE_PRESERVED, 37 LOCAL_EGL_TRUE, 38 LOCAL_EGL_NONE, 39 LOCAL_EGL_NONE, 40 }; 41 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; 48 } 49 50 auto tex = MakeUnique<Texture>(*desc.gl); 51 { 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); 63 } 64 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; 70 } 71 72 return AsUnique(new SharedSurface_AndroidHardwareBuffer( 73 desc, std::move(fb), std::move(tex), buffer)); 74 } 75 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) {} 82 83 SharedSurface_AndroidHardwareBuffer::~SharedSurface_AndroidHardwareBuffer() { 84 const auto& gl = mDesc.gl; 85 if (!gl || !gl->MakeCurrent()) { 86 return; 87 } 88 const auto& gle = GLContextEGL::Cast(gl); 89 const auto& egl = gle->mEgl; 90 91 if (mSync) { 92 egl->fDestroySync(mSync); 93 mSync = 0; 94 } 95 } 96 97 void SharedSurface_AndroidHardwareBuffer::ProducerReleaseImpl() { 98 const auto& gl = mDesc.gl; 99 if (!gl || !gl->MakeCurrent()) { 100 return; 101 } 102 const auto& gle = GLContextEGL::Cast(gl); 103 const auto& egl = gle->mEgl; 104 105 if (mSync) { 106 MOZ_ALWAYS_TRUE(egl->fDestroySync(mSync)); 107 mSync = 0; 108 } 109 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 mAndroidHardwareBuffer->SetAcquireFence(UniqueFileHandle(rawFd)); 115 } 116 117 gl->fFlush(); 118 } 119 120 Maybe<layers::SurfaceDescriptor> 121 SharedSurface_AndroidHardwareBuffer::ToSurfaceDescriptor() { 122 return Some(layers::SurfaceDescriptorAndroidHardwareBuffer( 123 mAndroidHardwareBuffer->mId, mAndroidHardwareBuffer->mSize, 124 mAndroidHardwareBuffer->mFormat)); 125 } 126 127 void SharedSurface_AndroidHardwareBuffer::WaitForBufferOwnership() { 128 UniqueFileHandle fenceFd = mAndroidHardwareBuffer->GetAndResetReleaseFence(); 129 if (!fenceFd) { 130 return; 131 } 132 133 const auto& gle = GLContextEGL::Cast(mDesc.gl); 134 const auto& egl = gle->mEgl; 135 136 const EGLint attribs[] = {LOCAL_EGL_SYNC_NATIVE_FENCE_FD_ANDROID, 137 fenceFd.get(), LOCAL_EGL_NONE}; 138 139 EGLSync sync = egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); 140 if (!sync) { 141 gfxCriticalNote << "Failed to create EGLSync from fd"; 142 return; 143 } 144 // Release fd here, since it is owned by EGLSync 145 (void)fenceFd.release(); 146 147 egl->fClientWaitSync(sync, 0, LOCAL_EGL_FOREVER); 148 egl->fDestroySync(sync); 149 } 150 151 /*static*/ 152 UniquePtr<SurfaceFactory_AndroidHardwareBuffer> 153 SurfaceFactory_AndroidHardwareBuffer::Create(GLContext& gl) { 154 const auto partialDesc = PartialSharedSurfaceDesc{ 155 &gl, 156 SharedSurfaceType::AndroidHardwareBuffer, 157 layers::TextureType::AndroidHardwareBuffer, 158 true, 159 }; 160 return AsUnique(new SurfaceFactory_AndroidHardwareBuffer(partialDesc)); 161 } 162 163 } // namespace gl 164 165 } /* namespace mozilla */