Bug 1874684 - Part 28: Return DateDuration from DifferenceISODateTime. r=mgaudet
[gecko.git] / gfx / webrender_bindings / RenderAndroidHardwareBufferTextureHost.cpp
blob779b3762906812afc3288b8a402cf40a8c540eb9
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"
17 namespace mozilla {
18 namespace wr {
20 RenderAndroidHardwareBufferTextureHost::RenderAndroidHardwareBufferTextureHost(
21 layers::AndroidHardwareBuffer* aAndroidHardwareBuffer)
22 : mAndroidHardwareBuffer(aAndroidHardwareBuffer),
23 mEGLImage(EGL_NO_IMAGE),
24 mTextureHandle(0) {
25 MOZ_ASSERT(mAndroidHardwareBuffer);
26 MOZ_COUNT_CTOR_INHERITED(RenderAndroidHardwareBufferTextureHost,
27 RenderTextureHost);
30 RenderAndroidHardwareBufferTextureHost::
31 ~RenderAndroidHardwareBufferTextureHost() {
32 MOZ_COUNT_DTOR_INHERITED(RenderAndroidHardwareBufferTextureHost,
33 RenderTextureHost);
34 DeleteTextureHandle();
35 DestroyEGLImage();
38 gfx::IntSize RenderAndroidHardwareBufferTextureHost::GetSize() const {
39 if (mAndroidHardwareBuffer) {
40 return mAndroidHardwareBuffer->mSize;
42 return gfx::IntSize();
45 bool RenderAndroidHardwareBufferTextureHost::EnsureLockable() {
46 if (!mAndroidHardwareBuffer) {
47 return false;
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};
59 EGLSync sync =
60 egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
61 if (sync) {
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);
67 } else {
68 egl->fClientWaitSync(sync, 0, LOCAL_EGL_FOREVER);
70 egl->fDestroySync(sync);
71 } else {
72 gfxCriticalNote << "Failed to create EGLSync from acquire fence fd";
76 if (mTextureHandle) {
77 return true;
80 if (!mEGLImage) {
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,
88 LOCAL_EGL_TRUE,
89 LOCAL_EGL_NONE,
90 LOCAL_EGL_NONE,
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);
110 return true;
113 wr::WrExternalImage RenderAndroidHardwareBufferTextureHost::Lock(
114 uint8_t aChannelIndex, gl::GLContext* aGL) {
115 MOZ_ASSERT(aChannelIndex == 0);
117 if (mGL.get() != aGL) {
118 if (mGL) {
119 // This should not happen.
120 MOZ_ASSERT_UNREACHABLE("Unexpected GL context");
121 return InvalidToWrExternalImage();
123 mGL = aGL;
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) {
148 return;
150 MOZ_ASSERT(mGL);
151 mGL->fDeleteTextures(1, &mTextureHandle);
152 mTextureHandle = 0;
155 void RenderAndroidHardwareBufferTextureHost::DestroyEGLImage() {
156 if (!mEGLImage) {
157 return;
159 MOZ_ASSERT(mGL);
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;
178 gfxCriticalNoteOnce
179 << "Unexpected color format of RenderAndroidSurfaceTextureHost";
181 return gfx::SurfaceFormat::UNKNOWN;
184 already_AddRefed<gfx::DataSourceSurface>
185 RenderAndroidHardwareBufferTextureHost::ReadTexImage() {
186 if (!mGL) {
187 mGL = RenderThread::Get()->SingletonGL();
188 if (!mGL) {
189 return nullptr;
193 if (!EnsureLockable()) {
194 return nullptr;
197 /* Allocate resulting image surface */
198 int32_t stride = GetSize().width * BytesPerPixel(GetFormat());
199 RefPtr<gfx::DataSourceSurface> surf =
200 gfx::Factory::CreateDataSourceSurfaceWithStride(GetSize(), GetFormat(),
201 stride);
202 if (!surf) {
203 return nullptr;
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);
213 if (!ret) {
214 return nullptr;
217 return surf.forget();
220 bool RenderAndroidHardwareBufferTextureHost::MapPlane(
221 RenderCompositor* aCompositor, uint8_t aChannelIndex,
222 PlaneInfo& aPlaneInfo) {
223 RefPtr<gfx::DataSourceSurface> readback = ReadTexImage();
224 if (!readback) {
225 return false;
228 gfx::DataSourceSurface::MappedSurface map;
229 if (!readback->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
230 return false;
233 mReadback = readback;
234 aPlaneInfo.mSize = GetSize();
235 aPlaneInfo.mStride = map.mStride;
236 aPlaneInfo.mData = map.mData;
237 return true;
240 void RenderAndroidHardwareBufferTextureHost::UnmapPlanes() {
241 if (mReadback) {
242 mReadback->Unmap();
243 mReadback = nullptr;
247 } // namespace wr
248 } // namespace mozilla