Bug 1918529 - fix some subpixel misalignment issues with gfx.webrender.svg-filter...
[gecko.git] / gfx / webrender_bindings / RenderAndroidHardwareBufferTextureHost.cpp
blob144c8817da5ab76691f529b524bec1e173e12f75
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/layers/TextureHostOGL.h"
11 #include "mozilla/webrender/RenderThread.h"
12 #include "mozilla/gfx/2D.h"
13 #include "GLContextEGL.h"
14 #include "GLLibraryEGL.h"
15 #include "GLReadTexImageHelper.h"
16 #include "OGLShaderConfig.h"
18 namespace mozilla {
19 namespace wr {
21 RenderAndroidHardwareBufferTextureHost::RenderAndroidHardwareBufferTextureHost(
22 layers::AndroidHardwareBuffer* aAndroidHardwareBuffer)
23 : mAndroidHardwareBuffer(aAndroidHardwareBuffer),
24 mEGLImage(EGL_NO_IMAGE),
25 mTextureHandle(0) {
26 MOZ_ASSERT(mAndroidHardwareBuffer);
27 MOZ_COUNT_CTOR_INHERITED(RenderAndroidHardwareBufferTextureHost,
28 RenderTextureHost);
31 RenderAndroidHardwareBufferTextureHost::
32 ~RenderAndroidHardwareBufferTextureHost() {
33 MOZ_COUNT_DTOR_INHERITED(RenderAndroidHardwareBufferTextureHost,
34 RenderTextureHost);
35 DeleteTextureHandle();
36 DestroyEGLImage();
39 gfx::IntSize RenderAndroidHardwareBufferTextureHost::GetSize() const {
40 if (mAndroidHardwareBuffer) {
41 return mAndroidHardwareBuffer->mSize;
43 return gfx::IntSize();
46 bool RenderAndroidHardwareBufferTextureHost::EnsureLockable() {
47 if (!mAndroidHardwareBuffer) {
48 return false;
51 auto fenceFd = mAndroidHardwareBuffer->GetAndResetAcquireFence();
52 if (fenceFd.IsValid()) {
53 const auto& gle = gl::GLContextEGL::Cast(mGL);
54 const auto& egl = gle->mEgl;
56 auto rawFD = fenceFd.TakePlatformHandle();
57 const EGLint attribs[] = {LOCAL_EGL_SYNC_NATIVE_FENCE_FD_ANDROID,
58 rawFD.get(), LOCAL_EGL_NONE};
60 EGLSync sync =
61 egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
62 if (sync) {
63 // Release fd here, since it is owned by EGLSync
64 Unused << rawFD.release();
66 if (egl->IsExtensionSupported(gl::EGLExtension::KHR_wait_sync)) {
67 egl->fWaitSync(sync, 0);
68 } else {
69 egl->fClientWaitSync(sync, 0, LOCAL_EGL_FOREVER);
71 egl->fDestroySync(sync);
72 } else {
73 gfxCriticalNote << "Failed to create EGLSync from acquire fence fd";
77 if (mTextureHandle) {
78 return true;
81 if (!mEGLImage) {
82 // XXX add crop handling for video
83 // Should only happen the first time.
84 const auto& gle = gl::GLContextEGL::Cast(mGL);
85 const auto& egl = gle->mEgl;
87 const EGLint attrs[] = {
88 LOCAL_EGL_IMAGE_PRESERVED,
89 LOCAL_EGL_TRUE,
90 LOCAL_EGL_NONE,
91 LOCAL_EGL_NONE,
94 EGLClientBuffer clientBuffer = egl->mLib->fGetNativeClientBufferANDROID(
95 mAndroidHardwareBuffer->GetNativeBuffer());
96 mEGLImage = egl->fCreateImage(
97 EGL_NO_CONTEXT, LOCAL_EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attrs);
99 MOZ_ASSERT(mEGLImage);
101 mGL->fGenTextures(1, &mTextureHandle);
102 mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL, mTextureHandle);
103 mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL, LOCAL_GL_TEXTURE_WRAP_T,
104 LOCAL_GL_CLAMP_TO_EDGE);
105 mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL, LOCAL_GL_TEXTURE_WRAP_S,
106 LOCAL_GL_CLAMP_TO_EDGE);
107 mGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_EXTERNAL, mEGLImage);
109 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0,
110 LOCAL_GL_TEXTURE_EXTERNAL_OES, mTextureHandle);
111 return true;
114 wr::WrExternalImage RenderAndroidHardwareBufferTextureHost::Lock(
115 uint8_t aChannelIndex, gl::GLContext* aGL) {
116 MOZ_ASSERT(aChannelIndex == 0);
118 if (mGL.get() != aGL) {
119 if (mGL) {
120 // This should not happen.
121 MOZ_ASSERT_UNREACHABLE("Unexpected GL context");
122 return InvalidToWrExternalImage();
124 mGL = aGL;
127 if (!mGL || !mGL->MakeCurrent()) {
128 return InvalidToWrExternalImage();
131 if (!EnsureLockable()) {
132 return InvalidToWrExternalImage();
135 const gfx::IntSize size = GetSize();
136 return NativeTextureToWrExternalImage(mTextureHandle, 0.0, 0.0,
137 static_cast<float>(size.width),
138 static_cast<float>(size.height));
141 void RenderAndroidHardwareBufferTextureHost::Unlock() {}
143 size_t RenderAndroidHardwareBufferTextureHost::Bytes() {
144 return GetSize().width * GetSize().height *
145 BytesPerPixel(mAndroidHardwareBuffer->mFormat);
148 void RenderAndroidHardwareBufferTextureHost::DeleteTextureHandle() {
149 if (!mTextureHandle) {
150 return;
152 MOZ_ASSERT(mGL);
153 mGL->fDeleteTextures(1, &mTextureHandle);
154 mTextureHandle = 0;
157 void RenderAndroidHardwareBufferTextureHost::DestroyEGLImage() {
158 if (!mEGLImage) {
159 return;
161 MOZ_ASSERT(mGL);
162 const auto& gle = gl::GLContextEGL::Cast(mGL);
163 const auto& egl = gle->mEgl;
164 egl->fDestroyImage(mEGLImage);
165 mEGLImage = EGL_NO_IMAGE;
168 gfx::SurfaceFormat RenderAndroidHardwareBufferTextureHost::GetFormat() const {
169 MOZ_ASSERT(mAndroidHardwareBuffer->mFormat == gfx::SurfaceFormat::R8G8B8A8 ||
170 mAndroidHardwareBuffer->mFormat == gfx::SurfaceFormat::R8G8B8X8);
172 if (mAndroidHardwareBuffer->mFormat == gfx::SurfaceFormat::R8G8B8A8) {
173 return gfx::SurfaceFormat::B8G8R8A8;
176 if (mAndroidHardwareBuffer->mFormat == gfx::SurfaceFormat::R8G8B8X8) {
177 return gfx::SurfaceFormat::B8G8R8X8;
180 gfxCriticalNoteOnce
181 << "Unexpected color format of RenderAndroidSurfaceTextureHost";
183 return gfx::SurfaceFormat::UNKNOWN;
186 already_AddRefed<gfx::DataSourceSurface>
187 RenderAndroidHardwareBufferTextureHost::ReadTexImage() {
188 if (!mGL) {
189 mGL = RenderThread::Get()->SingletonGL();
190 if (!mGL) {
191 return nullptr;
195 if (!EnsureLockable()) {
196 return nullptr;
199 /* Allocate resulting image surface */
200 int32_t stride = GetSize().width * BytesPerPixel(GetFormat());
201 RefPtr<gfx::DataSourceSurface> surf =
202 gfx::Factory::CreateDataSourceSurfaceWithStride(GetSize(), GetFormat(),
203 stride);
204 if (!surf) {
205 return nullptr;
208 layers::ShaderConfigOGL config = layers::ShaderConfigFromTargetAndFormat(
209 LOCAL_GL_TEXTURE_EXTERNAL, mAndroidHardwareBuffer->mFormat);
210 int shaderConfig = config.mFeatures;
212 bool ret = mGL->ReadTexImageHelper()->ReadTexImage(
213 surf, mTextureHandle, LOCAL_GL_TEXTURE_EXTERNAL, GetSize(),
214 gfx::Matrix4x4(), shaderConfig, /* aYInvert */ false);
215 if (!ret) {
216 return nullptr;
219 return surf.forget();
222 bool RenderAndroidHardwareBufferTextureHost::MapPlane(
223 RenderCompositor* aCompositor, uint8_t aChannelIndex,
224 PlaneInfo& aPlaneInfo) {
225 RefPtr<gfx::DataSourceSurface> readback = ReadTexImage();
226 if (!readback) {
227 return false;
230 gfx::DataSourceSurface::MappedSurface map;
231 if (!readback->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
232 return false;
235 mReadback = readback;
236 aPlaneInfo.mSize = GetSize();
237 aPlaneInfo.mStride = map.mStride;
238 aPlaneInfo.mData = map.mData;
239 return true;
242 void RenderAndroidHardwareBufferTextureHost::UnmapPlanes() {
243 if (mReadback) {
244 mReadback->Unmap();
245 mReadback = nullptr;
249 RefPtr<layers::TextureSource>
250 RenderAndroidHardwareBufferTextureHost::CreateTextureSource(
251 layers::TextureSourceProvider* aProvider) {
252 return new layers::AndroidHardwareBufferTextureSource(
253 aProvider, mAndroidHardwareBuffer, mAndroidHardwareBuffer->mFormat,
254 LOCAL_GL_TEXTURE_EXTERNAL, LOCAL_GL_CLAMP_TO_EDGE, GetSize());
257 } // namespace wr
258 } // namespace mozilla