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 package androidx.graphics.lowlatency 17 18 import android.graphics.Color 19 import android.opengl.GLES20 20 import java.nio.ByteBuffer 21 import java.nio.ByteOrder 22 import java.nio.FloatBuffer 23 import java.nio.ShortBuffer 24 25 class Rectangle { 26 27 private val mVertexBuffer: FloatBuffer 28 private val mDrawListBuffer: ShortBuffer 29 private val mProgram: Int 30 private var mPositionHandle = 0 31 private var mColorHandle = 0 32 private var mMVPMatrixHandle = 0 33 private var mColor = floatArrayOf(1f, 0f, 0f, 1f) 34 private var mSquareCoords = FloatArray(12) 35 36 /** Sets up the drawing object data for use in an OpenGL ES context. */ 37 init { 38 // initialize vertex byte buffer for shape coordinates 39 val bb = 40 ByteBuffer.allocateDirect( // (# of coordinate values * 4 bytes per float) 41 mSquareCoords.size * 4 42 ) 43 bb.order(ByteOrder.nativeOrder()) 44 mVertexBuffer = bb.asFloatBuffer() 45 mVertexBuffer.put(mSquareCoords) 46 mVertexBuffer.position(0) 47 // initialize byte buffer for the draw list 48 val dlb = 49 ByteBuffer.allocateDirect( // (# of coordinate values * 2 bytes per short) 50 DRAW_ORDER.size * 2 51 ) 52 dlb.order(ByteOrder.nativeOrder()) 53 mDrawListBuffer = dlb.asShortBuffer() 54 mDrawListBuffer.put(DRAW_ORDER) 55 mDrawListBuffer.position(0) 56 // prepare shaders and OpenGL program 57 val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode) 58 val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode) 59 mProgram = GLES20.glCreateProgram() // create empty OpenGL Program 60 GLES20.glAttachShader(mProgram, vertexShader) // add the vertex shader to program 61 GLES20.glAttachShader(mProgram, fragmentShader) // add the fragment shader to program 62 GLES20.glLinkProgram(mProgram) // create OpenGL program executables 63 } 64 drawnull65 fun draw( 66 mvpMatrix: FloatArray?, 67 color: Int, 68 left: Float, 69 top: Float, 70 right: Float, 71 bottom: Float 72 ) { 73 74 mColor[0] = Color.red(color) / 255f 75 mColor[1] = Color.green(color) / 255f 76 mColor[2] = Color.blue(color) / 255f 77 mColor[3] = Color.alpha(color) / 255f 78 79 // top left 80 mSquareCoords[0] = left 81 mSquareCoords[1] = top 82 mSquareCoords[2] = 0f 83 // bottom left 84 mSquareCoords[3] = left 85 mSquareCoords[4] = bottom 86 mSquareCoords[5] = 0f 87 // bottom right 88 mSquareCoords[6] = right 89 mSquareCoords[7] = bottom 90 mSquareCoords[8] = 0f 91 // top right 92 mSquareCoords[9] = right 93 mSquareCoords[10] = top 94 mSquareCoords[11] = 0f 95 96 mVertexBuffer.clear() 97 mVertexBuffer.put(mSquareCoords) 98 mVertexBuffer.position(0) 99 100 GLES20.glUseProgram(mProgram) 101 // get handle to vertex shader's vPosition member 102 mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition") 103 // Enable a handle to the triangle vertices 104 GLES20.glEnableVertexAttribArray(mPositionHandle) 105 // Prepare the triangle coordinate data 106 // 4 bytes per vertex 107 val vertexStride = COORDS_PER_VERTEX * 4 108 GLES20.glVertexAttribPointer( 109 mPositionHandle, 110 COORDS_PER_VERTEX, 111 GLES20.GL_FLOAT, 112 false, 113 vertexStride, 114 mVertexBuffer 115 ) 116 // get handle to fragment shader's vColor member 117 mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor") 118 // Set color for drawing the triangle 119 GLES20.glUniform4fv(mColorHandle, 1, mColor, 0) 120 // get handle to shape's transformation matrix 121 mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix") 122 // Apply the projection and view transformation 123 GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0) 124 // Draw the square 125 GLES20.glDrawElements( 126 GLES20.GL_TRIANGLES, 127 DRAW_ORDER.size, 128 GLES20.GL_UNSIGNED_SHORT, 129 mDrawListBuffer 130 ) 131 // Disable vertex array 132 GLES20.glDisableVertexAttribArray(mPositionHandle) 133 } 134 135 companion object { 136 private val vertexShaderCode = 137 """ 138 uniform mat4 uMVPMatrix; 139 attribute vec4 vPosition; 140 void main() { 141 gl_Position = uMVPMatrix * vPosition; 142 } 143 """ 144 private val fragmentShaderCode = 145 """ 146 precision mediump float; 147 uniform vec4 vColor; 148 void main() { 149 gl_FragColor = vColor; 150 } 151 """ 152 153 // number of coordinates per vertex in this array 154 val COORDS_PER_VERTEX = 3 155 val DRAW_ORDER = shortArrayOf(0, 1, 2, 0, 2, 3) // order to draw vertices 156 } 157 } 158