1 /* 2 * Copyright 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.graphics.lowlatency 18 19 import android.annotation.SuppressLint 20 import android.hardware.HardwareBuffer 21 import android.os.Build 22 import androidx.annotation.RequiresApi 23 import androidx.graphics.surface.SurfaceControlCompat 24 import androidx.hardware.USAGE_COMPOSER_OVERLAY 25 26 internal class FrontBufferUtils private constructor() { 27 28 companion object { 29 30 internal const val TAG = "FrontBufferUtils" 31 32 /** Flags that are expected to be supported on all [HardwareBuffer] instances */ 33 @SuppressLint("WrongConstant") 34 internal const val BaseFlags = 35 HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE or 36 HardwareBuffer.USAGE_GPU_COLOR_OUTPUT or 37 USAGE_COMPOSER_OVERLAY 38 obtainHardwareBufferUsageFlagsnull39 internal fun obtainHardwareBufferUsageFlags(): Long = 40 if (!UseCompatSurfaceControl && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { 41 UsageFlagsVerificationHelper.obtainUsageFlagsV33() 42 } else { 43 BaseFlags 44 } 45 46 internal const val UseCompatSurfaceControl = false 47 configureFrontBufferLayerFrameRatenull48 fun configureFrontBufferLayerFrameRate( 49 frontBufferSurfaceControl: SurfaceControlCompat, 50 frameRate: Float = 1000f, 51 transaction: SurfaceControlCompat.Transaction? = null 52 ): SurfaceControlCompat.Transaction? { 53 var targetTransaction: SurfaceControlCompat.Transaction? = transaction 54 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { 55 if (targetTransaction == null) { 56 targetTransaction = SurfaceControlCompat.Transaction() 57 } 58 targetTransaction.setFrameRate( 59 frontBufferSurfaceControl, 60 frameRate, 61 SurfaceControlCompat.FRAME_RATE_COMPATIBILITY_DEFAULT, 62 SurfaceControlCompat.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS 63 ) 64 } 65 return targetTransaction 66 } 67 } 68 } 69 70 /** Helper class to avoid class verification failures */ 71 @RequiresApi(Build.VERSION_CODES.Q) 72 internal class UsageFlagsVerificationHelper private constructor() { 73 companion object { 74 75 /** 76 * Helper method to determine if a particular HardwareBuffer usage flag is supported. Even 77 * though the FRONT_BUFFER_USAGE and COMPOSER_OVERLAY flags are introduced in Android T, not 78 * all devices may support this flag. So we conduct a capability query with a sample 1x1 79 * HardwareBuffer with the provided flag to see if it is compatible 80 */ 81 // Suppressing WrongConstant warnings as we are leveraging a constant with the same value 82 // as HardwareBuffer.USAGE_COMPOSER_OVERLAY to avoid SDK checks as the constant has been 83 // supported in the NDK for several platform releases. 84 // See: 85 // developer.android.com/ndk/reference/group/a-hardware-buffer#ahardwarebuffer_usageflags 86 @SuppressLint("WrongConstant") 87 @RequiresApi(Build.VERSION_CODES.Q) isSupportednull88 internal fun isSupported(flag: Long): Boolean = 89 HardwareBuffer.isSupported( 90 1, // width 91 1, // height 92 HardwareBuffer.RGBA_8888, // format 93 1, // layers 94 FrontBufferUtils.BaseFlags or flag 95 ) 96 97 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 98 fun obtainUsageFlagsV33(): Long { 99 // First verify if the front buffer usage flag is supported along with the 100 // "usage composer overlay" flag that was introduced in API level 33 101 return if (isSupported(HardwareBuffer.USAGE_FRONT_BUFFER)) { 102 FrontBufferUtils.BaseFlags or HardwareBuffer.USAGE_FRONT_BUFFER 103 } else { 104 // If the front buffer usage flag is not supported, configure the CPU write flag 105 // in order to prevent arm frame buffer compression from causing visual artifacts 106 // on certain devices like the Samsung Galaxy Tab S6 lite. See b/365131024 107 FrontBufferUtils.BaseFlags or HardwareBuffer.USAGE_CPU_WRITE_OFTEN 108 } 109 } 110 } 111 } 112