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/. */
6 
7 #include "TextureClientSharedSurface.h"
8 
9 #include "GLContext.h"
10 #include "mozilla/gfx/2D.h"
11 #include "mozilla/gfx/Logging.h"  // for gfxDebug
12 #include "mozilla/layers/ISurfaceAllocator.h"
13 #include "mozilla/Unused.h"
14 #include "nsThreadUtils.h"
15 #include "SharedSurface.h"
16 
17 #ifdef MOZ_WIDGET_ANDROID
18 #  include "mozilla/layers/AndroidHardwareBuffer.h"
19 #endif
20 
21 using namespace mozilla::gl;
22 
23 namespace mozilla {
24 namespace layers {
25 
26 /* static */
CreateTextureClient(const layers::SurfaceDescriptor & aDesc,const gfx::SurfaceFormat aFormat,gfx::IntSize aSize,TextureFlags aFlags,LayersIPCChannel * aAllocator)27 already_AddRefed<TextureClient> SharedSurfaceTextureData::CreateTextureClient(
28     const layers::SurfaceDescriptor& aDesc, const gfx::SurfaceFormat aFormat,
29     gfx::IntSize aSize, TextureFlags aFlags, LayersIPCChannel* aAllocator) {
30   auto data = MakeUnique<SharedSurfaceTextureData>(aDesc, aFormat, aSize);
31   return TextureClient::CreateWithData(data.release(), aFlags, aAllocator);
32 }
33 
SharedSurfaceTextureData(const SurfaceDescriptor & desc,const gfx::SurfaceFormat format,const gfx::IntSize size)34 SharedSurfaceTextureData::SharedSurfaceTextureData(
35     const SurfaceDescriptor& desc, const gfx::SurfaceFormat format,
36     const gfx::IntSize size)
37     : mDesc(desc), mFormat(format), mSize(size) {}
38 
39 SharedSurfaceTextureData::~SharedSurfaceTextureData() = default;
40 
Deallocate(LayersIPCChannel *)41 void SharedSurfaceTextureData::Deallocate(LayersIPCChannel*) {}
42 
FillInfo(TextureData::Info & aInfo) const43 void SharedSurfaceTextureData::FillInfo(TextureData::Info& aInfo) const {
44   aInfo.size = mSize;
45   aInfo.format = mFormat;
46   aInfo.hasIntermediateBuffer = false;
47   aInfo.hasSynchronization = false;
48   aInfo.supportsMoz2D = false;
49   aInfo.canExposeMappedData = false;
50 }
51 
Serialize(SurfaceDescriptor & aOutDescriptor)52 bool SharedSurfaceTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
53   if (mDesc.type() !=
54       SurfaceDescriptor::TSurfaceDescriptorAndroidHardwareBuffer) {
55     aOutDescriptor = mDesc;
56     return true;
57   }
58 
59 #ifdef MOZ_WIDGET_ANDROID
60   // File descriptor is created heare for reducing its allocation.
61   const SurfaceDescriptorAndroidHardwareBuffer& desc =
62       mDesc.get_SurfaceDescriptorAndroidHardwareBuffer();
63   RefPtr<AndroidHardwareBuffer> buffer =
64       AndroidHardwareBufferManager::Get()->GetBuffer(desc.bufferId());
65   if (!buffer) {
66     return false;
67   }
68 
69   int fd[2] = {};
70   if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fd) != 0) {
71     return false;
72   }
73 
74   UniqueFileHandle readerFd(fd[0]);
75   UniqueFileHandle writerFd(fd[1]);
76 
77   // Send the AHardwareBuffer to an AF_UNIX socket. It does not acquire or
78   // retain a reference to the buffer object. The caller is therefore
79   // responsible for ensuring that the buffer remains alive through the lifetime
80   // of this file descriptor.
81   int ret = buffer->SendHandleToUnixSocket(writerFd.get());
82   if (ret < 0) {
83     return false;
84   }
85 
86   aOutDescriptor = layers::SurfaceDescriptorAndroidHardwareBuffer(
87       ipc::FileDescriptor(readerFd.release()), buffer->mId, buffer->mSize,
88       buffer->mFormat);
89   return true;
90 #else
91   MOZ_ASSERT_UNREACHABLE("unexpected to be called");
92   return false;
93 #endif
94 }
95 
GetTextureFlags() const96 TextureFlags SharedSurfaceTextureData::GetTextureFlags() const {
97   TextureFlags flags = TextureFlags::NO_FLAGS;
98 
99 #ifdef MOZ_WIDGET_ANDROID
100   if (mDesc.type() ==
101       SurfaceDescriptor::TSurfaceDescriptorAndroidHardwareBuffer) {
102     flags |= TextureFlags::WAIT_HOST_USAGE_END;
103   }
104 #endif
105   return flags;
106 }
107 
GetBufferId() const108 Maybe<uint64_t> SharedSurfaceTextureData::GetBufferId() const {
109 #ifdef MOZ_WIDGET_ANDROID
110   if (mDesc.type() ==
111       SurfaceDescriptor::TSurfaceDescriptorAndroidHardwareBuffer) {
112     const SurfaceDescriptorAndroidHardwareBuffer& desc =
113         mDesc.get_SurfaceDescriptorAndroidHardwareBuffer();
114     return Some(desc.bufferId());
115   }
116 #endif
117   return Nothing();
118 }
119 
GetAcquireFence()120 mozilla::ipc::FileDescriptor SharedSurfaceTextureData::GetAcquireFence() {
121 #ifdef MOZ_WIDGET_ANDROID
122   if (mDesc.type() ==
123       SurfaceDescriptor::TSurfaceDescriptorAndroidHardwareBuffer) {
124     const SurfaceDescriptorAndroidHardwareBuffer& desc =
125         mDesc.get_SurfaceDescriptorAndroidHardwareBuffer();
126     RefPtr<AndroidHardwareBuffer> buffer =
127         AndroidHardwareBufferManager::Get()->GetBuffer(desc.bufferId());
128     if (!buffer) {
129       return ipc::FileDescriptor();
130     }
131 
132     return buffer->GetAcquireFence();
133   }
134 #endif
135   return ipc::FileDescriptor();
136 }
137 
138 }  // namespace layers
139 }  // namespace mozilla
140