1 /* 2 * Copyright 2022 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.hardware.HardwareBuffer 20 import android.opengl.GLES20 21 import androidx.graphics.opengl.FrameBufferRenderer 22 import androidx.graphics.opengl.SyncStrategy 23 import androidx.graphics.opengl.egl.EGLSpec 24 import androidx.hardware.SyncFenceCompat 25 26 /** 27 * [SyncStrategy] implementation that optimizes for front buffered rendering use cases. More 28 * specifically this attempts to avoid unnecessary synchronization overhead wherever possible. 29 * 30 * This will always provide a fence if the corresponding layer transitions from an invisible to a 31 * visible state. If the layer is already visible and front buffer usage flags are support on the 32 * device, then no fence is provided. If this flag is not supported, then a fence is created to 33 * ensure contents are flushed to the single buffer. 34 * 35 * @param usageFlags usage flags that describe the [HardwareBuffer] that is used as the destination 36 * for rendering content within [FrameBufferRenderer]. The usage flags can be obtained via 37 * [HardwareBuffer.getUsage] or by passing in the same flags from [HardwareBuffer.create] 38 */ 39 class FrontBufferSyncStrategy(usageFlags: Long) : SyncStrategy { 40 private val supportsFrontBufferUsage = (usageFlags and HardwareBuffer.USAGE_FRONT_BUFFER) != 0L 41 private var mFrontBufferVisible: Boolean = false 42 43 /** 44 * Tells whether the corresponding front buffer layer is visible in its current state or not. 45 * Utilize this to dictate when a [SyncFenceCompat] will be created when using 46 * [createSyncFence]. 47 */ 48 var isVisible 49 get() = mFrontBufferVisible 50 set(visibility) { 51 mFrontBufferVisible = visibility 52 } 53 54 /** 55 * Creates a [SyncFenceCompat] based on various conditions. If the layer is changing from 56 * invisible to visible, a fence is provided. If the layer is already visible and front buffer 57 * usage flag is supported on the device, then no fence is provided. If front buffer usage is 58 * not supported, then a fence is created and destroyed to flush contents to screen. 59 */ createSyncFencenull60 override fun createSyncFence(eglSpec: EGLSpec): SyncFenceCompat? { 61 return if (!isVisible) { 62 SyncFenceCompat.createNativeSyncFence() 63 } else if (supportsFrontBufferUsage) { 64 GLES20.glFlush() 65 return null 66 } else { 67 val fence = SyncFenceCompat.createNativeSyncFence() 68 fence.close() 69 return null 70 } 71 } 72 } 73