vertex.go (4379B)
1 // Copyright 2019 The Ebiten Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package graphics 16 17 import ( 18 "sync" 19 ) 20 21 const ( 22 ShaderImageNum = 4 23 24 // PreservedUniformVariablesNum represents the number of preserved uniform variables. 25 // Any shaders in Ebiten must have these uniform variables. 26 PreservedUniformVariablesNum = 1 + // the destination texture size 27 1 + // the texture sizes array 28 1 + // the texture destination region's origin 29 1 + // the texture destination region's size 30 1 + // the offsets array of the second and the following images 31 1 + // the texture source region's origin 32 1 // the texture source region's size 33 34 DestinationTextureSizeUniformVariableIndex = 0 35 TextureSizesUniformVariableIndex = 1 36 TextureDestinationRegionOriginUniformVariableIndex = 2 37 TextureDestinationRegionSizeUniformVariableIndex = 3 38 TextureSourceOffsetsUniformVariableIndex = 4 39 TextureSourceRegionOriginUniformVariableIndex = 5 40 TextureSourceRegionSizeUniformVariableIndex = 6 41 ) 42 43 const ( 44 IndicesNum = (1 << 16) / 3 * 3 // Adjust num for triangles. 45 VertexFloatNum = 8 46 ) 47 48 var ( 49 quadIndices = []uint16{0, 1, 2, 1, 2, 3} 50 ) 51 52 func QuadIndices() []uint16 { 53 return quadIndices 54 } 55 56 var ( 57 theVerticesBackend = &verticesBackend{} 58 ) 59 60 // TODO: The logic is very similar to atlas.temporaryPixels. Unify them. 61 62 type verticesBackend struct { 63 backend []float32 64 pos int 65 notFullyUsedTime int 66 67 m sync.Mutex 68 } 69 70 func verticesBackendFloat32Size(size int) int { 71 l := 128 * VertexFloatNum 72 for l < size { 73 l *= 2 74 } 75 return l 76 } 77 78 func (v *verticesBackend) slice(n int) []float32 { 79 v.m.Lock() 80 defer v.m.Unlock() 81 82 need := n * VertexFloatNum 83 if len(v.backend) < v.pos+need { 84 v.backend = make([]float32, verticesBackendFloat32Size(v.pos+need)) 85 v.pos = 0 86 } 87 s := v.backend[v.pos : v.pos+need] 88 v.pos += need 89 return s 90 } 91 92 func (v *verticesBackend) lockAndReset(f func() error) error { 93 v.m.Lock() 94 defer v.m.Unlock() 95 96 if err := f(); err != nil { 97 return err 98 } 99 100 const maxNotFullyUsedTime = 60 101 if verticesBackendFloat32Size(v.pos) < len(v.backend) { 102 if v.notFullyUsedTime < maxNotFullyUsedTime { 103 v.notFullyUsedTime++ 104 } 105 } else { 106 v.notFullyUsedTime = 0 107 } 108 109 if v.notFullyUsedTime == maxNotFullyUsedTime && len(v.backend) > 0 { 110 v.backend = nil 111 } 112 113 v.pos = 0 114 return nil 115 } 116 117 // Vertices returns a float32 slice for n vertices. 118 // Vertices returns a slice that never overlaps with other slices returned this function, 119 // and users can do optimization based on this fact. 120 func Vertices(n int) []float32 { 121 return theVerticesBackend.slice(n) 122 } 123 124 func LockAndResetVertices(f func() error) error { 125 return theVerticesBackend.lockAndReset(f) 126 } 127 128 // QuadVertices returns a float32 slice for a quadrangle. 129 // QuadVertices returns a slice that never overlaps with other slices returned this function, 130 // and users can do optimization based on this fact. 131 func QuadVertices(sx0, sy0, sx1, sy1 float32, a, b, c, d, tx, ty float32, cr, cg, cb, ca float32) []float32 { 132 x := sx1 - sx0 133 y := sy1 - sy0 134 ax, by, cx, dy := a*x, b*y, c*x, d*y 135 u0, v0, u1, v1 := float32(sx0), float32(sy0), float32(sx1), float32(sy1) 136 137 // Use the vertex backend instead of calling make to reduce GCs (#1521). 138 vs := theVerticesBackend.slice(4) 139 140 // This function is very performance-sensitive and implement in a very dumb way. 141 _ = vs[:4*VertexFloatNum] 142 143 vs[0] = tx 144 vs[1] = ty 145 vs[2] = u0 146 vs[3] = v0 147 vs[4] = cr 148 vs[5] = cg 149 vs[6] = cb 150 vs[7] = ca 151 152 vs[8] = ax + tx 153 vs[9] = cx + ty 154 vs[10] = u1 155 vs[11] = v0 156 vs[12] = cr 157 vs[13] = cg 158 vs[14] = cb 159 vs[15] = ca 160 161 vs[16] = by + tx 162 vs[17] = dy + ty 163 vs[18] = u0 164 vs[19] = v1 165 vs[20] = cr 166 vs[21] = cg 167 vs[22] = cb 168 vs[23] = ca 169 170 vs[24] = ax + by + tx 171 vs[25] = cx + dy + ty 172 vs[26] = u1 173 vs[27] = v1 174 vs[28] = cr 175 vs[29] = cg 176 vs[30] = cb 177 vs[31] = ca 178 179 return vs 180 }