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.opengl.GLES20
20 import android.opengl.Matrix
21 import android.os.Build
22 import androidx.annotation.RequiresApi
23 import androidx.graphics.surface.SurfaceControlCompat
24 
25 /**
26  * Class responsible for computing the corresponding transformations necessary to support
27  * pre-rotation. Consumers are expected to use the corresponding [bufferWidth] and [bufferHeight]
28  * parameters to configure with [GLES20.glViewport] as well as [transform] that should be consumed
29  * in any vertex shader computations
30  */
31 @RequiresApi(Build.VERSION_CODES.Q)
32 internal class BufferTransformer {
33 
34     private val mViewTransform = FloatArray(16)
35 
36     val transform: FloatArray
37         get() = mViewTransform
38 
39     var logicalWidth = 0
40         private set
41 
42     var logicalHeight = 0
43         private set
44 
45     var bufferWidth = 0
46         private set
47 
48     var bufferHeight = 0
49         private set
50 
51     var computedTransform: Int = BufferTransformHintResolver.UNKNOWN_TRANSFORM
52         private set
53 
invertBufferTransformnull54     fun invertBufferTransform(transform: Int): Int =
55         when (transform) {
56             SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_90 ->
57                 SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_270
58             SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_180 ->
59                 SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_180
60             SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_270 ->
61                 SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_90
62             SurfaceControlCompat.BUFFER_TRANSFORM_IDENTITY ->
63                 SurfaceControlCompat.BUFFER_TRANSFORM_IDENTITY
64             else -> BufferTransformHintResolver.UNKNOWN_TRANSFORM // Return unknown transform
65         }
66 
67     /**
68      * Compute the corresponding transform to apply to take into account buffer transformation hints
69      */
computeTransformnull70     fun computeTransform(width: Int, height: Int, transformHint: Int) {
71         val fWidth = width.toFloat()
72         val fHeight = height.toFloat()
73         logicalWidth = width
74         logicalHeight = height
75         bufferWidth = width
76         bufferHeight = height
77         computedTransform = transformHint
78         when (transformHint) {
79             SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_90 -> {
80                 Matrix.setRotateM(mViewTransform, 0, -90f, 0f, 0f, 1f)
81                 Matrix.translateM(mViewTransform, 0, -fWidth, 0f, 0f)
82                 bufferWidth = height
83                 bufferHeight = width
84             }
85             SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_180 -> {
86                 Matrix.setRotateM(mViewTransform, 0, 180f, 0f, 0f, 1f)
87                 Matrix.translateM(mViewTransform, 0, -fWidth, -fHeight, 0f)
88             }
89             SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_270 -> {
90                 Matrix.setRotateM(mViewTransform, 0, 90f, 0f, 0f, 1f)
91                 Matrix.translateM(mViewTransform, 0, 0f, -fHeight, 0f)
92                 bufferWidth = height
93                 bufferHeight = width
94             }
95             SurfaceControlCompat.BUFFER_TRANSFORM_IDENTITY -> {
96                 Matrix.setIdentityM(mViewTransform, 0)
97             }
98             // Identity or unknown case, just set the identity matrix
99             else -> {
100                 computedTransform = BufferTransformHintResolver.UNKNOWN_TRANSFORM
101                 Matrix.setIdentityM(mViewTransform, 0)
102             }
103         }
104     }
105 }
106