Bug 1890689 accumulate input in LargerReceiverBlockSizeThanDesiredBuffering GTest...
[gecko.git] / gfx / gl / SharedSurfaceDMABUF.cpp
blob56315bb31703a0126ec0e541ef12cb769a7849bb
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 "SharedSurfaceDMABUF.h"
8 #include "gfxPlatform.h"
9 #include "GLContextEGL.h"
10 #include "MozFramebuffer.h"
11 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
12 #include "mozilla/gfx/gfxVars.h"
13 #include "mozilla/widget/DMABufLibWrapper.h"
15 namespace mozilla::gl {
17 static bool HasDmaBufExtensions(const GLContextEGL* gl) {
18 const auto& egl = *(gl->mEgl);
19 return egl.IsExtensionSupported(EGLExtension::EXT_image_dma_buf_import) &&
20 egl.IsExtensionSupported(
21 EGLExtension::EXT_image_dma_buf_import_modifiers) &&
22 egl.IsExtensionSupported(EGLExtension::MESA_image_dma_buf_export);
25 /*static*/
26 UniquePtr<SharedSurface_DMABUF> SharedSurface_DMABUF::Create(
27 const SharedSurfaceDesc& desc) {
28 const auto& gle = GLContextEGL::Cast(desc.gl);
29 const auto& context = gle->mContext;
30 const auto& egl = *(gle->mEgl);
32 RefPtr<DMABufSurface> surface;
33 UniquePtr<MozFramebuffer> fb;
35 if (!HasDmaBufExtensions(gle) || !gfx::gfxVars::UseDMABufSurfaceExport()) {
36 // Using MESA_image_dma_buf_export is not supported or it's broken.
37 // Create dmabuf surface directly via GBM and create
38 // EGLImage/framebuffer over it.
39 const auto flags = static_cast<DMABufSurfaceFlags>(
40 DMABUF_TEXTURE | DMABUF_USE_MODIFIERS | DMABUF_ALPHA);
41 surface = DMABufSurfaceRGBA::CreateDMABufSurface(desc.size.width,
42 desc.size.height, flags);
43 if (!surface || !surface->CreateTexture(desc.gl)) {
44 return nullptr;
46 const auto tex = surface->GetTexture();
47 fb = MozFramebuffer::CreateForBacking(desc.gl, desc.size, 0, false,
48 LOCAL_GL_TEXTURE_2D, tex);
49 if (!fb) return nullptr;
50 } else {
51 // Use MESA_image_dma_buf_export to create EGLImage/framebuffer directly
52 // and derive dmabuf from it.
53 fb = MozFramebuffer::Create(desc.gl, desc.size, 0, false);
54 if (!fb) return nullptr;
56 const auto buffer = reinterpret_cast<EGLClientBuffer>(fb->ColorTex());
57 const auto image =
58 egl.fCreateImage(context, LOCAL_EGL_GL_TEXTURE_2D, buffer, nullptr);
59 if (!image) return nullptr;
61 surface = DMABufSurfaceRGBA::CreateDMABufSurface(
62 desc.gl, image, desc.size.width, desc.size.height);
63 if (!surface) return nullptr;
65 return AsUnique(new SharedSurface_DMABUF(desc, std::move(fb), surface));
68 SharedSurface_DMABUF::SharedSurface_DMABUF(const SharedSurfaceDesc& desc,
69 UniquePtr<MozFramebuffer> fb,
70 const RefPtr<DMABufSurface> surface)
71 : SharedSurface(desc, std::move(fb)), mSurface(surface) {}
73 SharedSurface_DMABUF::~SharedSurface_DMABUF() {
74 const auto& gl = mDesc.gl;
75 if (!gl || !gl->MakeCurrent()) {
76 return;
78 mSurface->ReleaseTextures();
81 void SharedSurface_DMABUF::ProducerReleaseImpl() { mSurface->FenceSet(); }
83 void SharedSurface_DMABUF::WaitForBufferOwnership() { mSurface->FenceWait(); }
85 Maybe<layers::SurfaceDescriptor> SharedSurface_DMABUF::ToSurfaceDescriptor() {
86 layers::SurfaceDescriptor desc;
87 if (!mSurface->Serialize(desc)) return {};
88 return Some(desc);
91 /*static*/
92 UniquePtr<SurfaceFactory_DMABUF> SurfaceFactory_DMABUF::Create(GLContext& gl) {
93 if (!widget::DMABufDevice::IsDMABufWebGLEnabled()) {
94 return nullptr;
97 auto dmabufFactory = MakeUnique<SurfaceFactory_DMABUF>(gl);
98 if (dmabufFactory->CanCreateSurface(gl)) {
99 return dmabufFactory;
102 LOGDMABUF(
103 ("SurfaceFactory_DMABUF::Create() failed, fallback to SW buffers.\n"));
104 widget::DMABufDevice::DisableDMABufWebGL();
105 return nullptr;
108 bool SurfaceFactory_DMABUF::CanCreateSurface(GLContext& gl) {
109 UniquePtr<SharedSurface> test =
110 CreateShared(gfx::IntSize(1, 1), gfx::ColorSpace2::SRGB);
111 if (!test) {
112 LOGDMABUF((
113 "SurfaceFactory_DMABUF::CanCreateSurface() failed to create surface."));
114 return false;
116 auto desc = test->ToSurfaceDescriptor();
117 if (!desc) {
118 LOGDMABUF(
119 ("SurfaceFactory_DMABUF::CanCreateSurface() failed to serialize "
120 "surface."));
121 return false;
123 RefPtr<DMABufSurface> importedSurface =
124 DMABufSurface::CreateDMABufSurface(*desc);
125 if (!importedSurface) {
126 LOGDMABUF((
127 "SurfaceFactory_DMABUF::CanCreateSurface() failed to import surface."));
128 return false;
130 if (!importedSurface->CreateTexture(&gl)) {
131 LOGDMABUF(
132 ("SurfaceFactory_DMABUF::CanCreateSurface() failed to create texture "
133 "over surface."));
134 return false;
136 return true;
139 SurfaceFactory_DMABUF::SurfaceFactory_DMABUF(GLContext& gl)
140 : SurfaceFactory({&gl, SharedSurfaceType::EGLSurfaceDMABUF,
141 layers::TextureType::DMABUF, true}) {}
142 } // namespace mozilla::gl