twitchapon-anim

Basic Twitchapon Receiver/Visuals
git clone git://bsandro.tech/twitchapon-anim
Log | Files | Refs | README | LICENSE

context_mobile.go (12743B)


      1 // Copyright 2014 Hajime Hoshi
      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 // +build android ios
     16 
     17 package opengl
     18 
     19 import (
     20 	"errors"
     21 	"fmt"
     22 
     23 	mgl "golang.org/x/mobile/gl"
     24 
     25 	"github.com/hajimehoshi/ebiten/v2/internal/driver"
     26 	"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
     27 )
     28 
     29 type (
     30 	textureNative     mgl.Texture
     31 	framebufferNative mgl.Framebuffer
     32 	shader            mgl.Shader
     33 	program           mgl.Program
     34 	buffer            mgl.Buffer
     35 )
     36 
     37 func (t textureNative) equal(rhs textureNative) bool {
     38 	return t == rhs
     39 }
     40 
     41 func (f framebufferNative) equal(rhs framebufferNative) bool {
     42 	return f == rhs
     43 }
     44 
     45 func (s shader) equal(rhs shader) bool {
     46 	return s == rhs
     47 }
     48 
     49 func (b buffer) equal(rhs buffer) bool {
     50 	return b == rhs
     51 }
     52 
     53 func (p program) equal(rhs program) bool {
     54 	return p == rhs
     55 }
     56 
     57 var InvalidTexture textureNative
     58 
     59 type (
     60 	uniformLocation mgl.Uniform
     61 	attribLocation  mgl.Attrib
     62 )
     63 
     64 func (u uniformLocation) equal(rhs uniformLocation) bool {
     65 	return u == rhs
     66 }
     67 
     68 type programID uint32
     69 
     70 var (
     71 	invalidTexture     = textureNative(mgl.Texture{})
     72 	invalidFramebuffer = framebufferNative(mgl.Framebuffer{Value: (1 << 32) - 1})
     73 	invalidUniform     = uniformLocation(mgl.Uniform{Value: -1})
     74 )
     75 
     76 func getProgramID(p program) programID {
     77 	return programID(p.Value)
     78 }
     79 
     80 const (
     81 	vertexShader       = shaderType(mgl.VERTEX_SHADER)
     82 	fragmentShader     = shaderType(mgl.FRAGMENT_SHADER)
     83 	arrayBuffer        = bufferType(mgl.ARRAY_BUFFER)
     84 	elementArrayBuffer = bufferType(mgl.ELEMENT_ARRAY_BUFFER)
     85 	dynamicDraw        = bufferUsage(mgl.DYNAMIC_DRAW)
     86 	short              = dataType(mgl.SHORT)
     87 	float              = dataType(mgl.FLOAT)
     88 
     89 	zero             = operation(mgl.ZERO)
     90 	one              = operation(mgl.ONE)
     91 	srcAlpha         = operation(mgl.SRC_ALPHA)
     92 	dstAlpha         = operation(mgl.DST_ALPHA)
     93 	oneMinusSrcAlpha = operation(mgl.ONE_MINUS_SRC_ALPHA)
     94 	oneMinusDstAlpha = operation(mgl.ONE_MINUS_DST_ALPHA)
     95 	dstColor         = operation(mgl.DST_COLOR)
     96 )
     97 
     98 type contextImpl struct {
     99 	gl mgl.Context
    100 }
    101 
    102 func (c *context) reset() error {
    103 	c.locationCache = newLocationCache()
    104 	c.lastTexture = invalidTexture
    105 	c.lastFramebuffer = invalidFramebuffer
    106 	c.lastViewportWidth = 0
    107 	c.lastViewportHeight = 0
    108 	c.lastCompositeMode = driver.CompositeModeUnknown
    109 	c.gl.Enable(mgl.BLEND)
    110 	c.blendFunc(driver.CompositeModeSourceOver)
    111 	f := c.gl.GetInteger(mgl.FRAMEBUFFER_BINDING)
    112 	c.screenFramebuffer = framebufferNative(mgl.Framebuffer{uint32(f)})
    113 	// TODO: Need to update screenFramebufferWidth/Height?
    114 	return nil
    115 }
    116 
    117 func (c *context) blendFunc(mode driver.CompositeMode) {
    118 	gl := c.gl
    119 	if c.lastCompositeMode == mode {
    120 		return
    121 	}
    122 	c.lastCompositeMode = mode
    123 	s, d := mode.Operations()
    124 	s2, d2 := convertOperation(s), convertOperation(d)
    125 	gl.BlendFunc(mgl.Enum(s2), mgl.Enum(d2))
    126 }
    127 
    128 func (c *context) newTexture(width, height int) (textureNative, error) {
    129 	gl := c.gl
    130 	t := gl.CreateTexture()
    131 	if t.Value <= 0 {
    132 		return textureNative{}, errors.New("opengl: creating texture failed")
    133 	}
    134 	gl.PixelStorei(mgl.UNPACK_ALIGNMENT, 4)
    135 	c.bindTexture(textureNative(t))
    136 
    137 	gl.TexParameteri(mgl.TEXTURE_2D, mgl.TEXTURE_MAG_FILTER, mgl.NEAREST)
    138 	gl.TexParameteri(mgl.TEXTURE_2D, mgl.TEXTURE_MIN_FILTER, mgl.NEAREST)
    139 	gl.TexParameteri(mgl.TEXTURE_2D, mgl.TEXTURE_WRAP_S, mgl.CLAMP_TO_EDGE)
    140 	gl.TexParameteri(mgl.TEXTURE_2D, mgl.TEXTURE_WRAP_T, mgl.CLAMP_TO_EDGE)
    141 	gl.TexImage2D(mgl.TEXTURE_2D, 0, mgl.RGBA, width, height, mgl.RGBA, mgl.UNSIGNED_BYTE, nil)
    142 
    143 	return textureNative(t), nil
    144 }
    145 
    146 func (c *context) bindFramebufferImpl(f framebufferNative) {
    147 	gl := c.gl
    148 	gl.BindFramebuffer(mgl.FRAMEBUFFER, mgl.Framebuffer(f))
    149 }
    150 
    151 func (c *context) framebufferPixels(f *framebuffer, width, height int) ([]byte, error) {
    152 	gl := c.gl
    153 	gl.Flush()
    154 
    155 	c.bindFramebuffer(f.native)
    156 
    157 	pixels := make([]byte, 4*width*height)
    158 	gl.ReadPixels(pixels, 0, 0, width, height, mgl.RGBA, mgl.UNSIGNED_BYTE)
    159 	return pixels, nil
    160 }
    161 
    162 func (c *context) activeTexture(idx int) {
    163 	gl := c.gl
    164 	gl.ActiveTexture(mgl.Enum(mgl.TEXTURE0 + idx))
    165 }
    166 
    167 func (c *context) bindTextureImpl(t textureNative) {
    168 	gl := c.gl
    169 	gl.BindTexture(mgl.TEXTURE_2D, mgl.Texture(t))
    170 }
    171 
    172 func (c *context) deleteTexture(t textureNative) {
    173 	gl := c.gl
    174 	if !gl.IsTexture(mgl.Texture(t)) {
    175 		return
    176 	}
    177 	if c.lastTexture == t {
    178 		c.lastTexture = invalidTexture
    179 	}
    180 	gl.DeleteTexture(mgl.Texture(t))
    181 }
    182 
    183 func (c *context) isTexture(t textureNative) bool {
    184 	gl := c.gl
    185 	return gl.IsTexture(mgl.Texture(t))
    186 }
    187 
    188 func (c *context) newFramebuffer(texture textureNative) (framebufferNative, error) {
    189 	gl := c.gl
    190 	f := gl.CreateFramebuffer()
    191 	if f.Value <= 0 {
    192 		return framebufferNative{}, errors.New("opengl: creating framebuffer failed: gl.IsFramebuffer returns false")
    193 	}
    194 	c.bindFramebuffer(framebufferNative(f))
    195 
    196 	gl.FramebufferTexture2D(mgl.FRAMEBUFFER, mgl.COLOR_ATTACHMENT0, mgl.TEXTURE_2D, mgl.Texture(texture), 0)
    197 	s := gl.CheckFramebufferStatus(mgl.FRAMEBUFFER)
    198 	if s != mgl.FRAMEBUFFER_COMPLETE {
    199 		if s != 0 {
    200 			return framebufferNative{}, fmt.Errorf("opengl: creating framebuffer failed: %v", s)
    201 		}
    202 		if e := gl.GetError(); e != mgl.NO_ERROR {
    203 			return framebufferNative{}, fmt.Errorf("opengl: creating framebuffer failed: (glGetError) %d", e)
    204 		}
    205 		return framebufferNative{}, fmt.Errorf("opengl: creating framebuffer failed: unknown error")
    206 	}
    207 	return framebufferNative(f), nil
    208 }
    209 
    210 func (c *context) setViewportImpl(width, height int) {
    211 	gl := c.gl
    212 	gl.Viewport(0, 0, width, height)
    213 }
    214 
    215 func (c *context) deleteFramebuffer(f framebufferNative) {
    216 	gl := c.gl
    217 	if !gl.IsFramebuffer(mgl.Framebuffer(f)) {
    218 		return
    219 	}
    220 	// If a framebuffer to be deleted is bound, a newly bound framebuffer
    221 	// will be a default framebuffer.
    222 	// https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDeleteFramebuffers.xml
    223 	if c.lastFramebuffer == f {
    224 		c.lastFramebuffer = invalidFramebuffer
    225 		c.lastViewportWidth = 0
    226 		c.lastViewportHeight = 0
    227 	}
    228 	gl.DeleteFramebuffer(mgl.Framebuffer(f))
    229 }
    230 
    231 func (c *context) newShader(shaderType shaderType, source string) (shader, error) {
    232 	gl := c.gl
    233 	s := gl.CreateShader(mgl.Enum(shaderType))
    234 	if s.Value == 0 {
    235 		return shader{}, fmt.Errorf("opengl: glCreateShader failed: shader type: %d", shaderType)
    236 	}
    237 	gl.ShaderSource(s, source)
    238 	gl.CompileShader(s)
    239 
    240 	v := gl.GetShaderi(s, mgl.COMPILE_STATUS)
    241 	if v == mgl.FALSE {
    242 		log := gl.GetShaderInfoLog(s)
    243 		return shader{}, fmt.Errorf("opengl: shader compile failed: %s", log)
    244 	}
    245 	return shader(s), nil
    246 }
    247 
    248 func (c *context) deleteShader(s shader) {
    249 	gl := c.gl
    250 	gl.DeleteShader(mgl.Shader(s))
    251 }
    252 
    253 func (c *context) newProgram(shaders []shader, attributes []string) (program, error) {
    254 	gl := c.gl
    255 	p := gl.CreateProgram()
    256 	if p.Value == 0 {
    257 		return program{}, errors.New("opengl: glCreateProgram failed")
    258 	}
    259 
    260 	for _, shader := range shaders {
    261 		gl.AttachShader(p, mgl.Shader(shader))
    262 	}
    263 
    264 	for i, name := range attributes {
    265 		gl.BindAttribLocation(p, mgl.Attrib{Value: uint(i)}, name)
    266 	}
    267 
    268 	gl.LinkProgram(p)
    269 	v := gl.GetProgrami(p, mgl.LINK_STATUS)
    270 	if v == mgl.FALSE {
    271 		info := gl.GetProgramInfoLog(p)
    272 		return program{}, fmt.Errorf("opengl: program error: %s", info)
    273 	}
    274 	return program(p), nil
    275 }
    276 
    277 func (c *context) useProgram(p program) {
    278 	gl := c.gl
    279 	gl.UseProgram(mgl.Program(p))
    280 }
    281 
    282 func (c *context) deleteProgram(p program) {
    283 	gl := c.gl
    284 	if !gl.IsProgram(mgl.Program(p)) {
    285 		return
    286 	}
    287 	gl.DeleteProgram(mgl.Program(p))
    288 }
    289 
    290 func (c *context) getUniformLocationImpl(p program, location string) uniformLocation {
    291 	gl := c.gl
    292 	u := uniformLocation(gl.GetUniformLocation(mgl.Program(p), location))
    293 	return u
    294 }
    295 
    296 func (c *context) uniformInt(p program, location string, v int) bool {
    297 	gl := c.gl
    298 	l := c.locationCache.GetUniformLocation(c, p, location)
    299 	if l == invalidUniform {
    300 		return false
    301 	}
    302 	gl.Uniform1i(mgl.Uniform(l), v)
    303 	return true
    304 }
    305 
    306 func (c *context) uniformFloat(p program, location string, v float32) bool {
    307 	gl := c.gl
    308 	l := c.locationCache.GetUniformLocation(c, p, location)
    309 	if l == invalidUniform {
    310 		return false
    311 	}
    312 	gl.Uniform1f(mgl.Uniform(l), v)
    313 	return true
    314 }
    315 
    316 func (c *context) uniformFloats(p program, location string, v []float32, typ shaderir.Type) bool {
    317 	gl := c.gl
    318 	l := c.locationCache.GetUniformLocation(c, p, location)
    319 	if l == invalidUniform {
    320 		return false
    321 	}
    322 
    323 	base := typ.Main
    324 	if base == shaderir.Array {
    325 		base = typ.Sub[0].Main
    326 	}
    327 
    328 	switch base {
    329 	case shaderir.Float:
    330 		gl.Uniform1fv(mgl.Uniform(l), v)
    331 	case shaderir.Vec2:
    332 		gl.Uniform2fv(mgl.Uniform(l), v)
    333 	case shaderir.Vec3:
    334 		gl.Uniform3fv(mgl.Uniform(l), v)
    335 	case shaderir.Vec4:
    336 		gl.Uniform4fv(mgl.Uniform(l), v)
    337 	case shaderir.Mat2:
    338 		gl.UniformMatrix2fv(mgl.Uniform(l), v)
    339 	case shaderir.Mat3:
    340 		gl.UniformMatrix3fv(mgl.Uniform(l), v)
    341 	case shaderir.Mat4:
    342 		gl.UniformMatrix4fv(mgl.Uniform(l), v)
    343 	default:
    344 		panic(fmt.Sprintf("opengl: unexpected type: %s", typ.String()))
    345 	}
    346 	return true
    347 }
    348 
    349 func (c *context) vertexAttribPointer(p program, index int, size int, dataType dataType, stride int, offset int) {
    350 	gl := c.gl
    351 	gl.VertexAttribPointer(mgl.Attrib{Value: uint(index)}, size, mgl.Enum(dataType), false, stride, offset)
    352 }
    353 
    354 func (c *context) enableVertexAttribArray(p program, index int) {
    355 	gl := c.gl
    356 	gl.EnableVertexAttribArray(mgl.Attrib{Value: uint(index)})
    357 }
    358 
    359 func (c *context) disableVertexAttribArray(p program, index int) {
    360 	gl := c.gl
    361 	gl.DisableVertexAttribArray(mgl.Attrib{Value: uint(index)})
    362 }
    363 
    364 func (c *context) newArrayBuffer(size int) buffer {
    365 	gl := c.gl
    366 	b := gl.CreateBuffer()
    367 	gl.BindBuffer(mgl.Enum(arrayBuffer), b)
    368 	gl.BufferInit(mgl.Enum(arrayBuffer), size, mgl.Enum(dynamicDraw))
    369 	return buffer(b)
    370 }
    371 
    372 func (c *context) newElementArrayBuffer(size int) buffer {
    373 	gl := c.gl
    374 	b := gl.CreateBuffer()
    375 	gl.BindBuffer(mgl.Enum(elementArrayBuffer), b)
    376 	gl.BufferInit(mgl.Enum(elementArrayBuffer), size, mgl.Enum(dynamicDraw))
    377 	return buffer(b)
    378 }
    379 
    380 func (c *context) bindBuffer(bufferType bufferType, b buffer) {
    381 	gl := c.gl
    382 	gl.BindBuffer(mgl.Enum(bufferType), mgl.Buffer(b))
    383 }
    384 
    385 func (c *context) arrayBufferSubData(data []float32) {
    386 	gl := c.gl
    387 	gl.BufferSubData(mgl.Enum(arrayBuffer), 0, float32sToBytes(data))
    388 }
    389 
    390 func (c *context) elementArrayBufferSubData(data []uint16) {
    391 	gl := c.gl
    392 	gl.BufferSubData(mgl.Enum(elementArrayBuffer), 0, uint16sToBytes(data))
    393 }
    394 
    395 func (c *context) deleteBuffer(b buffer) {
    396 	gl := c.gl
    397 	gl.DeleteBuffer(mgl.Buffer(b))
    398 }
    399 
    400 func (c *context) drawElements(len int, offsetInBytes int) {
    401 	gl := c.gl
    402 	gl.DrawElements(mgl.TRIANGLES, len, mgl.UNSIGNED_SHORT, offsetInBytes)
    403 }
    404 
    405 func (c *context) maxTextureSizeImpl() int {
    406 	gl := c.gl
    407 	return gl.GetInteger(mgl.MAX_TEXTURE_SIZE)
    408 }
    409 
    410 func (c *context) getShaderPrecisionFormatPrecision() int {
    411 	gl := c.gl
    412 	_, _, p := gl.GetShaderPrecisionFormat(mgl.FRAGMENT_SHADER, mgl.HIGH_FLOAT)
    413 	return p
    414 }
    415 
    416 func (c *context) flush() {
    417 	gl := c.gl
    418 	gl.Flush()
    419 }
    420 
    421 func (c *context) needsRestoring() bool {
    422 	return true
    423 }
    424 
    425 func (c *context) canUsePBO() bool {
    426 	// On Android, using PBO might slow the applications, especially when coming back from the context lost.
    427 	// Let's not use PBO until we find a good solution.
    428 	return false
    429 }
    430 
    431 func (c *context) texSubImage2D(t textureNative, width, height int, args []*driver.ReplacePixelsArgs) {
    432 	c.bindTexture(t)
    433 	gl := c.gl
    434 	for _, a := range args {
    435 		gl.TexSubImage2D(mgl.TEXTURE_2D, 0, a.X, a.Y, a.Width, a.Height, mgl.RGBA, mgl.UNSIGNED_BYTE, a.Pixels)
    436 	}
    437 }
    438 
    439 func (c *context) newPixelBufferObject(width, height int) buffer {
    440 	gl := c.gl
    441 	b := gl.CreateBuffer()
    442 	gl.BindBuffer(mgl.PIXEL_UNPACK_BUFFER, b)
    443 	gl.BufferInit(mgl.PIXEL_UNPACK_BUFFER, 4*width*height, mgl.STREAM_DRAW)
    444 	gl.BindBuffer(mgl.PIXEL_UNPACK_BUFFER, mgl.Buffer{0})
    445 	return buffer(b)
    446 }
    447 
    448 func (c *context) replacePixelsWithPBO(buffer buffer, t textureNative, width, height int, args []*driver.ReplacePixelsArgs) {
    449 	// This implementation is not used yet so far. See the comment at canUsePBO.
    450 
    451 	c.bindTexture(t)
    452 	gl := c.gl
    453 	gl.BindBuffer(mgl.PIXEL_UNPACK_BUFFER, mgl.Buffer(buffer))
    454 
    455 	stride := 4 * width
    456 	for _, a := range args {
    457 		offset := 4 * (a.Y*width + a.X)
    458 		for j := 0; j < a.Height; j++ {
    459 			gl.BufferSubData(mgl.PIXEL_UNPACK_BUFFER, offset+stride*j, a.Pixels[4*a.Width*j:4*a.Width*(j+1)])
    460 		}
    461 	}
    462 
    463 	gl.TexSubImage2D(mgl.TEXTURE_2D, 0, 0, 0, width, height, mgl.RGBA, mgl.UNSIGNED_BYTE, nil)
    464 	gl.BindBuffer(mgl.PIXEL_UNPACK_BUFFER, mgl.Buffer{0})
    465 }