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