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