1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/gl/android/android_surface_control_compat.h"
6
7 #include <dlfcn.h>
8 #include <android/data_space.h>
9
10 #include "base/android/build_info.h"
11 #include "base/atomic_sequence_num.h"
12 #include "base/bind.h"
13 #include "base/debug/crash_logging.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/no_destructor.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/system/sys_info.h"
18 #include "base/trace_event/trace_event.h"
19 #include "ui/gfx/color_space.h"
20
21 extern "C" {
22 typedef struct ASurfaceTransactionStats ASurfaceTransactionStats;
23 typedef void (*ASurfaceTransaction_OnComplete)(void* context,
24 ASurfaceTransactionStats* stats);
25
26 // ASurface
27 using pASurfaceControl_createFromWindow =
28 ASurfaceControl* (*)(ANativeWindow* parent, const char* name);
29 using pASurfaceControl_create = ASurfaceControl* (*)(ASurfaceControl* parent,
30 const char* name);
31 using pASurfaceControl_release = void (*)(ASurfaceControl*);
32
33 // ASurfaceTransaction enums
34 enum {
35 ASURFACE_TRANSACTION_TRANSPARENCY_TRANSPARENT = 0,
36 ASURFACE_TRANSACTION_TRANSPARENCY_TRANSLUCENT = 1,
37 ASURFACE_TRANSACTION_TRANSPARENCY_OPAQUE = 2,
38 };
39
40 // ASurfaceTransaction
41 using pASurfaceTransaction_create = ASurfaceTransaction* (*)(void);
42 using pASurfaceTransaction_delete = void (*)(ASurfaceTransaction*);
43 using pASurfaceTransaction_apply = int64_t (*)(ASurfaceTransaction*);
44 using pASurfaceTransaction_setOnComplete =
45 void (*)(ASurfaceTransaction*, void* ctx, ASurfaceTransaction_OnComplete);
46 using pASurfaceTransaction_reparent = void (*)(ASurfaceTransaction*,
47 ASurfaceControl* surface_control,
48 ASurfaceControl* new_parent);
49 using pASurfaceTransaction_setVisibility = void (*)(ASurfaceTransaction*,
50 ASurfaceControl*,
51 int8_t visibility);
52 using pASurfaceTransaction_setZOrder =
53 void (*)(ASurfaceTransaction* transaction, ASurfaceControl*, int32_t z);
54 using pASurfaceTransaction_setBuffer =
55 void (*)(ASurfaceTransaction* transaction,
56 ASurfaceControl*,
57 AHardwareBuffer*,
58 int32_t fence_fd);
59 using pASurfaceTransaction_setGeometry =
60 void (*)(ASurfaceTransaction* transaction,
61 ASurfaceControl* surface,
62 const ARect& src,
63 const ARect& dst,
64 int32_t transform);
65 using pASurfaceTransaction_setBufferTransparency =
66 void (*)(ASurfaceTransaction* transaction,
67 ASurfaceControl* surface,
68 int8_t transparency);
69 using pASurfaceTransaction_setDamageRegion =
70 void (*)(ASurfaceTransaction* transaction,
71 ASurfaceControl* surface,
72 const ARect rects[],
73 uint32_t count);
74 using pASurfaceTransaction_setBufferDataSpace =
75 void (*)(ASurfaceTransaction* transaction,
76 ASurfaceControl* surface,
77 uint64_t data_space);
78
79 // ASurfaceTransactionStats
80 using pASurfaceTransactionStats_getPresentFenceFd =
81 int (*)(ASurfaceTransactionStats* stats);
82 using pASurfaceTransactionStats_getLatchTime =
83 int64_t (*)(ASurfaceTransactionStats* stats);
84 using pASurfaceTransactionStats_getASurfaceControls =
85 void (*)(ASurfaceTransactionStats* stats,
86 ASurfaceControl*** surface_controls,
87 size_t* size);
88 using pASurfaceTransactionStats_releaseASurfaceControls =
89 void (*)(ASurfaceControl** surface_controls);
90 using pASurfaceTransactionStats_getPreviousReleaseFenceFd =
91 int (*)(ASurfaceTransactionStats* stats, ASurfaceControl* surface_control);
92 }
93
94 namespace gl {
95 namespace {
96
97 base::AtomicSequenceNumber g_next_transaction_id;
98
99 uint64_t g_agb_required_usage_bits = AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY;
100
101 #define LOAD_FUNCTION(lib, func) \
102 do { \
103 func##Fn = reinterpret_cast<p##func>(dlsym(lib, #func)); \
104 if (!func##Fn) { \
105 supported = false; \
106 LOG(ERROR) << "Unable to load function " << #func; \
107 } \
108 } while (0)
109
110 struct SurfaceControlMethods {
111 public:
Getgl::__anone42c85bf0211::SurfaceControlMethods112 static const SurfaceControlMethods& Get() {
113 static const base::NoDestructor<SurfaceControlMethods> instance;
114 return *instance;
115 }
116
SurfaceControlMethodsgl::__anone42c85bf0211::SurfaceControlMethods117 SurfaceControlMethods() {
118 void* main_dl_handle = dlopen("libandroid.so", RTLD_NOW);
119 if (!main_dl_handle) {
120 LOG(ERROR) << "Couldnt load android so";
121 supported = false;
122 return;
123 }
124
125 LOAD_FUNCTION(main_dl_handle, ASurfaceControl_createFromWindow);
126 LOAD_FUNCTION(main_dl_handle, ASurfaceControl_create);
127 LOAD_FUNCTION(main_dl_handle, ASurfaceControl_release);
128
129 LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_create);
130 LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_delete);
131 LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_apply);
132 LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setOnComplete);
133 LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_reparent);
134 LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setVisibility);
135 LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setZOrder);
136 LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setBuffer);
137 LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setGeometry);
138 LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setBufferTransparency);
139 LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setDamageRegion);
140 LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setBufferDataSpace);
141
142 LOAD_FUNCTION(main_dl_handle, ASurfaceTransactionStats_getPresentFenceFd);
143 LOAD_FUNCTION(main_dl_handle, ASurfaceTransactionStats_getLatchTime);
144 LOAD_FUNCTION(main_dl_handle, ASurfaceTransactionStats_getASurfaceControls);
145 LOAD_FUNCTION(main_dl_handle,
146 ASurfaceTransactionStats_releaseASurfaceControls);
147 LOAD_FUNCTION(main_dl_handle,
148 ASurfaceTransactionStats_getPreviousReleaseFenceFd);
149 }
150
151 ~SurfaceControlMethods() = default;
152
153 bool supported = true;
154 // Surface methods.
155 pASurfaceControl_createFromWindow ASurfaceControl_createFromWindowFn;
156 pASurfaceControl_create ASurfaceControl_createFn;
157 pASurfaceControl_release ASurfaceControl_releaseFn;
158
159 // Transaction methods.
160 pASurfaceTransaction_create ASurfaceTransaction_createFn;
161 pASurfaceTransaction_delete ASurfaceTransaction_deleteFn;
162 pASurfaceTransaction_apply ASurfaceTransaction_applyFn;
163 pASurfaceTransaction_setOnComplete ASurfaceTransaction_setOnCompleteFn;
164 pASurfaceTransaction_reparent ASurfaceTransaction_reparentFn;
165 pASurfaceTransaction_setVisibility ASurfaceTransaction_setVisibilityFn;
166 pASurfaceTransaction_setZOrder ASurfaceTransaction_setZOrderFn;
167 pASurfaceTransaction_setBuffer ASurfaceTransaction_setBufferFn;
168 pASurfaceTransaction_setGeometry ASurfaceTransaction_setGeometryFn;
169 pASurfaceTransaction_setBufferTransparency
170 ASurfaceTransaction_setBufferTransparencyFn;
171 pASurfaceTransaction_setDamageRegion ASurfaceTransaction_setDamageRegionFn;
172 pASurfaceTransaction_setBufferDataSpace
173 ASurfaceTransaction_setBufferDataSpaceFn;
174
175 // TransactionStats methods.
176 pASurfaceTransactionStats_getPresentFenceFd
177 ASurfaceTransactionStats_getPresentFenceFdFn;
178 pASurfaceTransactionStats_getLatchTime
179 ASurfaceTransactionStats_getLatchTimeFn;
180 pASurfaceTransactionStats_getASurfaceControls
181 ASurfaceTransactionStats_getASurfaceControlsFn;
182 pASurfaceTransactionStats_releaseASurfaceControls
183 ASurfaceTransactionStats_releaseASurfaceControlsFn;
184 pASurfaceTransactionStats_getPreviousReleaseFenceFd
185 ASurfaceTransactionStats_getPreviousReleaseFenceFdFn;
186 };
187
RectToARect(const gfx::Rect & rect)188 ARect RectToARect(const gfx::Rect& rect) {
189 return ARect{rect.x(), rect.y(), rect.right(), rect.bottom()};
190 }
191
OverlayTransformToWindowTransform(gfx::OverlayTransform transform)192 int32_t OverlayTransformToWindowTransform(gfx::OverlayTransform transform) {
193 // Note that the gfx::OverlayTransform expresses rotations in anticlockwise
194 // direction while the ANativeWindow rotations are in clockwise direction.
195 switch (transform) {
196 case gfx::OVERLAY_TRANSFORM_INVALID:
197 DCHECK(false) << "Invalid Transform";
198 return ANATIVEWINDOW_TRANSFORM_IDENTITY;
199 case gfx::OVERLAY_TRANSFORM_NONE:
200 return ANATIVEWINDOW_TRANSFORM_IDENTITY;
201 case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
202 return ANATIVEWINDOW_TRANSFORM_MIRROR_HORIZONTAL;
203 case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
204 return ANATIVEWINDOW_TRANSFORM_MIRROR_VERTICAL;
205 case gfx::OVERLAY_TRANSFORM_ROTATE_90:
206 return ANATIVEWINDOW_TRANSFORM_ROTATE_270;
207 case gfx::OVERLAY_TRANSFORM_ROTATE_180:
208 return ANATIVEWINDOW_TRANSFORM_ROTATE_180;
209 case gfx::OVERLAY_TRANSFORM_ROTATE_270:
210 return ANATIVEWINDOW_TRANSFORM_ROTATE_90;
211 };
212 NOTREACHED();
213 return ANATIVEWINDOW_TRANSFORM_IDENTITY;
214 }
215
ColorSpaceToADataSpace(const gfx::ColorSpace & color_space)216 uint64_t ColorSpaceToADataSpace(const gfx::ColorSpace& color_space) {
217 if (!color_space.IsValid() || color_space == gfx::ColorSpace::CreateSRGB())
218 return ADATASPACE_SRGB;
219
220 if (color_space == gfx::ColorSpace::CreateSCRGBLinear())
221 return ADATASPACE_SCRGB_LINEAR;
222
223 if (color_space == gfx::ColorSpace::CreateDisplayP3D65())
224 return ADATASPACE_DISPLAY_P3;
225
226 // TODO(khushalsagar): Check if we can support BT2020 using
227 // ADATASPACE_BT2020_PQ.
228 return ADATASPACE_UNKNOWN;
229 }
230
ToTransactionStats(ASurfaceTransactionStats * stats)231 SurfaceControl::TransactionStats ToTransactionStats(
232 ASurfaceTransactionStats* stats) {
233 SurfaceControl::TransactionStats transaction_stats;
234 transaction_stats.present_fence = base::ScopedFD(
235 SurfaceControlMethods::Get().ASurfaceTransactionStats_getPresentFenceFdFn(
236 stats));
237 transaction_stats.latch_time =
238 base::TimeTicks() +
239 base::TimeDelta::FromNanoseconds(
240 SurfaceControlMethods::Get().ASurfaceTransactionStats_getLatchTimeFn(
241 stats));
242 if (transaction_stats.latch_time == base::TimeTicks())
243 transaction_stats.latch_time = base::TimeTicks::Now();
244
245 ASurfaceControl** surface_controls = nullptr;
246 size_t size = 0u;
247 SurfaceControlMethods::Get().ASurfaceTransactionStats_getASurfaceControlsFn(
248 stats, &surface_controls, &size);
249 transaction_stats.surface_stats.resize(size);
250 for (size_t i = 0u; i < size; ++i) {
251 transaction_stats.surface_stats[i].surface = surface_controls[i];
252 int fence_fd = SurfaceControlMethods::Get()
253 .ASurfaceTransactionStats_getPreviousReleaseFenceFdFn(
254 stats, surface_controls[i]);
255 if (fence_fd != -1) {
256 transaction_stats.surface_stats[i].fence = base::ScopedFD(fence_fd);
257 }
258 }
259 SurfaceControlMethods::Get()
260 .ASurfaceTransactionStats_releaseASurfaceControlsFn(surface_controls);
261
262 return transaction_stats;
263 }
264
265 struct TransactionAckCtx {
266 int id = 0;
267 scoped_refptr<base::SingleThreadTaskRunner> task_runner;
268 SurfaceControl::Transaction::OnCompleteCb callback;
269 };
270
271 // Note that the framework API states that this callback can be dispatched on
272 // any thread (in practice it should be the binder thread).
OnTransactionCompletedOnAnyThread(void * context,ASurfaceTransactionStats * stats)273 void OnTransactionCompletedOnAnyThread(void* context,
274 ASurfaceTransactionStats* stats) {
275 auto* ack_ctx = static_cast<TransactionAckCtx*>(context);
276 auto transaction_stats = ToTransactionStats(stats);
277 TRACE_EVENT_ASYNC_END0("gpu,benchmark", "SurfaceControlTransaction",
278 ack_ctx->id);
279
280 if (ack_ctx->task_runner) {
281 ack_ctx->task_runner->PostTask(
282 FROM_HERE, base::BindOnce(std::move(ack_ctx->callback),
283 std::move(transaction_stats)));
284 } else {
285 std::move(ack_ctx->callback).Run(std::move(transaction_stats));
286 }
287
288 delete ack_ctx;
289 }
290 } // namespace
291
292 // static
IsSupported()293 bool SurfaceControl::IsSupported() {
294 if (!base::android::BuildInfo::GetInstance()->is_at_least_q())
295 return false;
296
297 CHECK(SurfaceControlMethods::Get().supported);
298 return true;
299 }
300
SupportsColorSpace(const gfx::ColorSpace & color_space)301 bool SurfaceControl::SupportsColorSpace(const gfx::ColorSpace& color_space) {
302 return ColorSpaceToADataSpace(color_space) != ADATASPACE_UNKNOWN;
303 }
304
RequiredUsage()305 uint64_t SurfaceControl::RequiredUsage() {
306 if (!IsSupported())
307 return 0u;
308 return g_agb_required_usage_bits;
309 }
310
EnableQualcommUBWC()311 void SurfaceControl::EnableQualcommUBWC() {
312 g_agb_required_usage_bits |= AHARDWAREBUFFER_USAGE_VENDOR_0;
313 }
314
315 SurfaceControl::Surface::Surface() = default;
316
Surface(const Surface & parent,const char * name)317 SurfaceControl::Surface::Surface(const Surface& parent, const char* name) {
318 surface_ = SurfaceControlMethods::Get().ASurfaceControl_createFn(
319 parent.surface(), name);
320 if (!surface_)
321 LOG(ERROR) << "Failed to create ASurfaceControl : " << name;
322 }
323
Surface(ANativeWindow * parent,const char * name)324 SurfaceControl::Surface::Surface(ANativeWindow* parent, const char* name) {
325 surface_ = SurfaceControlMethods::Get().ASurfaceControl_createFromWindowFn(
326 parent, name);
327 if (!surface_)
328 LOG(ERROR) << "Failed to create ASurfaceControl : " << name;
329 }
330
~Surface()331 SurfaceControl::Surface::~Surface() {
332 if (surface_) {
333 // It is important to detach the surface from the tree before deleting it.
334 Transaction transaction;
335 transaction.SetParent(*this, nullptr);
336 transaction.Apply();
337
338 SurfaceControlMethods::Get().ASurfaceControl_releaseFn(surface_);
339 }
340 }
341
342 SurfaceControl::SurfaceStats::SurfaceStats() = default;
343 SurfaceControl::SurfaceStats::~SurfaceStats() = default;
344
345 SurfaceControl::SurfaceStats::SurfaceStats(SurfaceStats&& other) = default;
346 SurfaceControl::SurfaceStats& SurfaceControl::SurfaceStats::operator=(
347 SurfaceStats&& other) = default;
348
349 SurfaceControl::TransactionStats::TransactionStats() = default;
350 SurfaceControl::TransactionStats::~TransactionStats() = default;
351
352 SurfaceControl::TransactionStats::TransactionStats(TransactionStats&& other) =
353 default;
354 SurfaceControl::TransactionStats& SurfaceControl::TransactionStats::operator=(
355 TransactionStats&& other) = default;
356
Transaction()357 SurfaceControl::Transaction::Transaction()
358 : id_(g_next_transaction_id.GetNext()) {
359 transaction_ = SurfaceControlMethods::Get().ASurfaceTransaction_createFn();
360 DCHECK(transaction_);
361 }
362
~Transaction()363 SurfaceControl::Transaction::~Transaction() {
364 if (transaction_)
365 SurfaceControlMethods::Get().ASurfaceTransaction_deleteFn(transaction_);
366 }
367
Transaction(Transaction && other)368 SurfaceControl::Transaction::Transaction(Transaction&& other)
369 : id_(other.id_), transaction_(other.transaction_) {
370 other.transaction_ = nullptr;
371 other.id_ = 0;
372 }
373
operator =(Transaction && other)374 SurfaceControl::Transaction& SurfaceControl::Transaction::operator=(
375 Transaction&& other) {
376 if (transaction_)
377 SurfaceControlMethods::Get().ASurfaceTransaction_deleteFn(transaction_);
378
379 transaction_ = other.transaction_;
380 id_ = other.id_;
381
382 other.transaction_ = nullptr;
383 other.id_ = 0;
384 return *this;
385 }
386
SetVisibility(const Surface & surface,bool show)387 void SurfaceControl::Transaction::SetVisibility(const Surface& surface,
388 bool show) {
389 SurfaceControlMethods::Get().ASurfaceTransaction_setVisibilityFn(
390 transaction_, surface.surface(), show);
391 }
392
SetZOrder(const Surface & surface,int32_t z)393 void SurfaceControl::Transaction::SetZOrder(const Surface& surface, int32_t z) {
394 SurfaceControlMethods::Get().ASurfaceTransaction_setZOrderFn(
395 transaction_, surface.surface(), z);
396 }
397
SetBuffer(const Surface & surface,AHardwareBuffer * buffer,base::ScopedFD fence_fd)398 void SurfaceControl::Transaction::SetBuffer(const Surface& surface,
399 AHardwareBuffer* buffer,
400 base::ScopedFD fence_fd) {
401 SurfaceControlMethods::Get().ASurfaceTransaction_setBufferFn(
402 transaction_, surface.surface(), buffer,
403 fence_fd.is_valid() ? fence_fd.release() : -1);
404 }
405
SetGeometry(const Surface & surface,const gfx::Rect & src,const gfx::Rect & dst,gfx::OverlayTransform transform)406 void SurfaceControl::Transaction::SetGeometry(const Surface& surface,
407 const gfx::Rect& src,
408 const gfx::Rect& dst,
409 gfx::OverlayTransform transform) {
410 SurfaceControlMethods::Get().ASurfaceTransaction_setGeometryFn(
411 transaction_, surface.surface(), RectToARect(src), RectToARect(dst),
412 OverlayTransformToWindowTransform(transform));
413 }
414
SetOpaque(const Surface & surface,bool opaque)415 void SurfaceControl::Transaction::SetOpaque(const Surface& surface,
416 bool opaque) {
417 int8_t transparency = opaque ? ASURFACE_TRANSACTION_TRANSPARENCY_OPAQUE
418 : ASURFACE_TRANSACTION_TRANSPARENCY_TRANSLUCENT;
419 SurfaceControlMethods::Get().ASurfaceTransaction_setBufferTransparencyFn(
420 transaction_, surface.surface(), transparency);
421 }
422
SetDamageRect(const Surface & surface,const gfx::Rect & rect)423 void SurfaceControl::Transaction::SetDamageRect(const Surface& surface,
424 const gfx::Rect& rect) {
425 auto a_rect = RectToARect(rect);
426 SurfaceControlMethods::Get().ASurfaceTransaction_setDamageRegionFn(
427 transaction_, surface.surface(), &a_rect, 1u);
428 }
429
SetColorSpace(const Surface & surface,const gfx::ColorSpace & color_space)430 void SurfaceControl::Transaction::SetColorSpace(
431 const Surface& surface,
432 const gfx::ColorSpace& color_space) {
433 auto data_space = ColorSpaceToADataSpace(color_space);
434
435 // Log the data space in crash keys for debugging crbug.com/997592.
436 static auto* kCrashKey = base::debug::AllocateCrashKeyString(
437 "data_space_for_buffer", base::debug::CrashKeySize::Size256);
438 auto crash_key_value = base::NumberToString(data_space);
439 base::debug::ScopedCrashKeyString scoped_crash_key(kCrashKey,
440 crash_key_value);
441
442 SurfaceControlMethods::Get().ASurfaceTransaction_setBufferDataSpaceFn(
443 transaction_, surface.surface(), data_space);
444 }
445
SetOnCompleteCb(OnCompleteCb cb,scoped_refptr<base::SingleThreadTaskRunner> task_runner)446 void SurfaceControl::Transaction::SetOnCompleteCb(
447 OnCompleteCb cb,
448 scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
449 TransactionAckCtx* ack_ctx = new TransactionAckCtx;
450 ack_ctx->callback = std::move(cb);
451 ack_ctx->task_runner = std::move(task_runner);
452 ack_ctx->id = id_;
453
454 SurfaceControlMethods::Get().ASurfaceTransaction_setOnCompleteFn(
455 transaction_, ack_ctx, &OnTransactionCompletedOnAnyThread);
456 }
457
SetParent(const Surface & surface,const Surface * new_parent)458 void SurfaceControl::Transaction::SetParent(const Surface& surface,
459 const Surface* new_parent) {
460 SurfaceControlMethods::Get().ASurfaceTransaction_reparentFn(
461 transaction_, surface.surface(),
462 new_parent ? new_parent->surface() : nullptr);
463 }
464
Apply()465 void SurfaceControl::Transaction::Apply() {
466 TRACE_EVENT_ASYNC_BEGIN0("gpu,benchmark", "SurfaceControlTransaction", id_);
467 SurfaceControlMethods::Get().ASurfaceTransaction_applyFn(transaction_);
468 }
469
470 } // namespace gl
471