zorldo

Goofing around with Ebiten
git clone git://bsandro.tech/zorldo
Log | Files | Refs | README

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 }