context.go (3367B)
1 // Copyright 2016 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 package opengl 16 17 import ( 18 "fmt" 19 "sync" 20 21 "github.com/hajimehoshi/ebiten/v2/internal/driver" 22 ) 23 24 type operation int 25 26 func convertOperation(op driver.Operation) operation { 27 switch op { 28 case driver.Zero: 29 return zero 30 case driver.One: 31 return one 32 case driver.SrcAlpha: 33 return srcAlpha 34 case driver.DstAlpha: 35 return dstAlpha 36 case driver.OneMinusSrcAlpha: 37 return oneMinusSrcAlpha 38 case driver.OneMinusDstAlpha: 39 return oneMinusDstAlpha 40 case driver.DstColor: 41 return dstColor 42 default: 43 panic(fmt.Sprintf("opengl: invalid operation %d at convertOperation", op)) 44 } 45 } 46 47 type context struct { 48 locationCache *locationCache 49 screenFramebuffer framebufferNative // This might not be the default frame buffer '0' (e.g. iOS). 50 lastFramebuffer framebufferNative 51 lastTexture textureNative 52 lastRenderbuffer renderbufferNative 53 lastViewportWidth int 54 lastViewportHeight int 55 lastCompositeMode driver.CompositeMode 56 maxTextureSize int 57 maxTextureSizeOnce sync.Once 58 highp bool 59 highpOnce sync.Once 60 61 contextImpl 62 } 63 64 func (c *context) bindTexture(t textureNative) { 65 if c.lastTexture.equal(t) { 66 return 67 } 68 c.bindTextureImpl(t) 69 c.lastTexture = t 70 } 71 72 func (c *context) bindRenderbuffer(r renderbufferNative) { 73 if c.lastRenderbuffer.equal(r) { 74 return 75 } 76 c.bindRenderbufferImpl(r) 77 c.lastRenderbuffer = r 78 } 79 80 func (c *context) bindFramebuffer(f framebufferNative) { 81 if c.lastFramebuffer.equal(f) { 82 return 83 } 84 c.bindFramebufferImpl(f) 85 c.lastFramebuffer = f 86 } 87 88 func (c *context) setViewport(f *framebuffer) { 89 c.bindFramebuffer(f.native) 90 if c.lastViewportWidth != f.width || c.lastViewportHeight != f.height { 91 // On some environments, viewport size must be within the framebuffer size. 92 // e.g. Edge (#71), Chrome on GPD Pocket (#420), macOS Mojave (#691). 93 // Use the same size of the framebuffer here. 94 c.setViewportImpl(f.width, f.height) 95 96 // glViewport must be called at least at every frame on iOS. 97 // As the screen framebuffer is the last render target, next SetViewport should be 98 // the first call at a frame. 99 if f.native.equal(c.screenFramebuffer) { 100 c.lastViewportWidth = 0 101 c.lastViewportHeight = 0 102 } else { 103 c.lastViewportWidth = f.width 104 c.lastViewportHeight = f.height 105 } 106 } 107 } 108 109 func (c *context) getScreenFramebuffer() framebufferNative { 110 return c.screenFramebuffer 111 } 112 113 func (c *context) getMaxTextureSize() int { 114 c.maxTextureSizeOnce.Do(func() { 115 c.maxTextureSize = c.maxTextureSizeImpl() 116 }) 117 return c.maxTextureSize 118 } 119 120 // highpPrecision represents an enough mantissa of float values in a shader. 121 const highpPrecision = 23 122 123 func (c *context) hasHighPrecisionFloat() bool { 124 c.highpOnce.Do(func() { 125 c.highp = c.getShaderPrecisionFormatPrecision() >= highpPrecision 126 }) 127 return c.highp 128 }