UNPKG

11.4 kBPlain TextView Raw
1import IndexBuffer from './index_buffer';
2
3import VertexBuffer from './vertex_buffer';
4import Framebuffer from './framebuffer';
5import DepthMode from './depth_mode';
6import StencilMode from './stencil_mode';
7import ColorMode from './color_mode';
8import CullFaceMode from './cull_face_mode';
9import {deepEqual} from '../util/util';
10import {ClearColor, ClearDepth, ClearStencil, ColorMask, DepthMask, StencilMask, StencilFunc, StencilOp, StencilTest, DepthRange, DepthTest, DepthFunc, Blend, BlendFunc, BlendColor, BlendEquation, CullFace, CullFaceSide, FrontFace, ProgramValue, ActiveTextureUnit, Viewport, BindFramebuffer, BindRenderbuffer, BindTexture, BindVertexBuffer, BindElementBuffer, BindVertexArrayOES, PixelStoreUnpack, PixelStoreUnpackPremultiplyAlpha, PixelStoreUnpackFlipY} from './value';
11
12import type {TriangleIndexArray, LineIndexArray, LineStripIndexArray} from '../data/index_array_type';
13import type {
14 StructArray,
15 StructArrayMember
16} from '../util/struct_array';
17import type Color from '../style-spec/util/color';
18
19type ClearArgs = {
20 color?: Color;
21 depth?: number;
22 stencil?: number;
23};
24
25class Context {
26 gl: WebGLRenderingContext;
27 extVertexArrayObject: any;
28 currentNumAttributes: number;
29 maxTextureSize: number;
30
31 clearColor: ClearColor;
32 clearDepth: ClearDepth;
33 clearStencil: ClearStencil;
34 colorMask: ColorMask;
35 depthMask: DepthMask;
36 stencilMask: StencilMask;
37 stencilFunc: StencilFunc;
38 stencilOp: StencilOp;
39 stencilTest: StencilTest;
40 depthRange: DepthRange;
41 depthTest: DepthTest;
42 depthFunc: DepthFunc;
43 blend: Blend;
44 blendFunc: BlendFunc;
45 blendColor: BlendColor;
46 blendEquation: BlendEquation;
47 cullFace: CullFace;
48 cullFaceSide: CullFaceSide;
49 frontFace: FrontFace;
50 program: ProgramValue;
51 activeTexture: ActiveTextureUnit;
52 viewport: Viewport;
53 bindFramebuffer: BindFramebuffer;
54 bindRenderbuffer: BindRenderbuffer;
55 bindTexture: BindTexture;
56 bindVertexBuffer: BindVertexBuffer;
57 bindElementBuffer: BindElementBuffer;
58 bindVertexArrayOES: BindVertexArrayOES;
59 pixelStoreUnpack: PixelStoreUnpack;
60 pixelStoreUnpackPremultiplyAlpha: PixelStoreUnpackPremultiplyAlpha;
61 pixelStoreUnpackFlipY: PixelStoreUnpackFlipY;
62
63 extTextureFilterAnisotropic: any;
64 extTextureFilterAnisotropicMax: any;
65 extTextureHalfFloat: any;
66 extRenderToTextureHalfFloat: any;
67 extTimerQuery: any;
68
69 constructor(gl: WebGLRenderingContext) {
70 this.gl = gl;
71 this.extVertexArrayObject = this.gl.getExtension('OES_vertex_array_object');
72
73 this.clearColor = new ClearColor(this);
74 this.clearDepth = new ClearDepth(this);
75 this.clearStencil = new ClearStencil(this);
76 this.colorMask = new ColorMask(this);
77 this.depthMask = new DepthMask(this);
78 this.stencilMask = new StencilMask(this);
79 this.stencilFunc = new StencilFunc(this);
80 this.stencilOp = new StencilOp(this);
81 this.stencilTest = new StencilTest(this);
82 this.depthRange = new DepthRange(this);
83 this.depthTest = new DepthTest(this);
84 this.depthFunc = new DepthFunc(this);
85 this.blend = new Blend(this);
86 this.blendFunc = new BlendFunc(this);
87 this.blendColor = new BlendColor(this);
88 this.blendEquation = new BlendEquation(this);
89 this.cullFace = new CullFace(this);
90 this.cullFaceSide = new CullFaceSide(this);
91 this.frontFace = new FrontFace(this);
92 this.program = new ProgramValue(this);
93 this.activeTexture = new ActiveTextureUnit(this);
94 this.viewport = new Viewport(this);
95 this.bindFramebuffer = new BindFramebuffer(this);
96 this.bindRenderbuffer = new BindRenderbuffer(this);
97 this.bindTexture = new BindTexture(this);
98 this.bindVertexBuffer = new BindVertexBuffer(this);
99 this.bindElementBuffer = new BindElementBuffer(this);
100 this.bindVertexArrayOES = this.extVertexArrayObject && new BindVertexArrayOES(this);
101 this.pixelStoreUnpack = new PixelStoreUnpack(this);
102 this.pixelStoreUnpackPremultiplyAlpha = new PixelStoreUnpackPremultiplyAlpha(this);
103 this.pixelStoreUnpackFlipY = new PixelStoreUnpackFlipY(this);
104
105 this.extTextureFilterAnisotropic = (
106 gl.getExtension('EXT_texture_filter_anisotropic') ||
107 gl.getExtension('MOZ_EXT_texture_filter_anisotropic') ||
108 gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic')
109 );
110 if (this.extTextureFilterAnisotropic) {
111 this.extTextureFilterAnisotropicMax = gl.getParameter(this.extTextureFilterAnisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT);
112 }
113
114 this.extTextureHalfFloat = gl.getExtension('OES_texture_half_float');
115 if (this.extTextureHalfFloat) {
116 gl.getExtension('OES_texture_half_float_linear');
117 this.extRenderToTextureHalfFloat = gl.getExtension('EXT_color_buffer_half_float');
118 }
119
120 this.extTimerQuery = gl.getExtension('EXT_disjoint_timer_query');
121 this.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
122 }
123
124 setDefault() {
125 this.unbindVAO();
126
127 this.clearColor.setDefault();
128 this.clearDepth.setDefault();
129 this.clearStencil.setDefault();
130 this.colorMask.setDefault();
131 this.depthMask.setDefault();
132 this.stencilMask.setDefault();
133 this.stencilFunc.setDefault();
134 this.stencilOp.setDefault();
135 this.stencilTest.setDefault();
136 this.depthRange.setDefault();
137 this.depthTest.setDefault();
138 this.depthFunc.setDefault();
139 this.blend.setDefault();
140 this.blendFunc.setDefault();
141 this.blendColor.setDefault();
142 this.blendEquation.setDefault();
143 this.cullFace.setDefault();
144 this.cullFaceSide.setDefault();
145 this.frontFace.setDefault();
146 this.program.setDefault();
147 this.activeTexture.setDefault();
148 this.bindFramebuffer.setDefault();
149 this.pixelStoreUnpack.setDefault();
150 this.pixelStoreUnpackPremultiplyAlpha.setDefault();
151 this.pixelStoreUnpackFlipY.setDefault();
152 }
153
154 setDirty() {
155 this.clearColor.dirty = true;
156 this.clearDepth.dirty = true;
157 this.clearStencil.dirty = true;
158 this.colorMask.dirty = true;
159 this.depthMask.dirty = true;
160 this.stencilMask.dirty = true;
161 this.stencilFunc.dirty = true;
162 this.stencilOp.dirty = true;
163 this.stencilTest.dirty = true;
164 this.depthRange.dirty = true;
165 this.depthTest.dirty = true;
166 this.depthFunc.dirty = true;
167 this.blend.dirty = true;
168 this.blendFunc.dirty = true;
169 this.blendColor.dirty = true;
170 this.blendEquation.dirty = true;
171 this.cullFace.dirty = true;
172 this.cullFaceSide.dirty = true;
173 this.frontFace.dirty = true;
174 this.program.dirty = true;
175 this.activeTexture.dirty = true;
176 this.viewport.dirty = true;
177 this.bindFramebuffer.dirty = true;
178 this.bindRenderbuffer.dirty = true;
179 this.bindTexture.dirty = true;
180 this.bindVertexBuffer.dirty = true;
181 this.bindElementBuffer.dirty = true;
182 if (this.extVertexArrayObject) {
183 this.bindVertexArrayOES.dirty = true;
184 }
185 this.pixelStoreUnpack.dirty = true;
186 this.pixelStoreUnpackPremultiplyAlpha.dirty = true;
187 this.pixelStoreUnpackFlipY.dirty = true;
188 }
189
190 createIndexBuffer(array: TriangleIndexArray | LineIndexArray | LineStripIndexArray, dynamicDraw?: boolean) {
191 return new IndexBuffer(this, array, dynamicDraw);
192 }
193
194 createVertexBuffer(array: StructArray, attributes: ReadonlyArray<StructArrayMember>, dynamicDraw?: boolean) {
195 return new VertexBuffer(this, array, attributes, dynamicDraw);
196 }
197
198 createRenderbuffer(storageFormat: number, width: number, height: number) {
199 const gl = this.gl;
200
201 const rbo = gl.createRenderbuffer();
202 this.bindRenderbuffer.set(rbo);
203 gl.renderbufferStorage(gl.RENDERBUFFER, storageFormat, width, height);
204 this.bindRenderbuffer.set(null);
205
206 return rbo;
207 }
208
209 createFramebuffer(width: number, height: number, hasDepth: boolean) {
210 return new Framebuffer(this, width, height, hasDepth);
211 }
212
213 clear({
214 color,
215 depth
216 }: ClearArgs) {
217 const gl = this.gl;
218 let mask = 0;
219
220 if (color) {
221 mask |= gl.COLOR_BUFFER_BIT;
222 this.clearColor.set(color);
223 this.colorMask.set([true, true, true, true]);
224 }
225
226 if (typeof depth !== 'undefined') {
227 mask |= gl.DEPTH_BUFFER_BIT;
228
229 // Workaround for platforms where clearDepth doesn't seem to work
230 // without reseting the depthRange. See https://github.com/mapbox/mapbox-gl-js/issues/3437
231 this.depthRange.set([0, 1]);
232
233 this.clearDepth.set(depth);
234 this.depthMask.set(true);
235 }
236
237 // See note in Painter#clearStencil: implement this the easy way once GPU bug/workaround is fixed upstream
238 // if (typeof stencil !== 'undefined') {
239 // mask |= gl.STENCIL_BUFFER_BIT;
240 // this.clearStencil.set(stencil);
241 // this.stencilMask.set(0xFF);
242 // }
243
244 gl.clear(mask);
245 }
246
247 setCullFace(cullFaceMode: Readonly<CullFaceMode>) {
248 if (cullFaceMode.enable === false) {
249 this.cullFace.set(false);
250 } else {
251 this.cullFace.set(true);
252 this.cullFaceSide.set(cullFaceMode.mode);
253 this.frontFace.set(cullFaceMode.frontFace);
254 }
255 }
256
257 setDepthMode(depthMode: Readonly<DepthMode>) {
258 if (depthMode.func === this.gl.ALWAYS && !depthMode.mask) {
259 this.depthTest.set(false);
260 } else {
261 this.depthTest.set(true);
262 this.depthFunc.set(depthMode.func);
263 this.depthMask.set(depthMode.mask);
264 this.depthRange.set(depthMode.range);
265 }
266 }
267
268 setStencilMode(stencilMode: Readonly<StencilMode>) {
269 if (stencilMode.test.func === this.gl.ALWAYS && !stencilMode.mask) {
270 this.stencilTest.set(false);
271 } else {
272 this.stencilTest.set(true);
273 this.stencilMask.set(stencilMode.mask);
274 this.stencilOp.set([stencilMode.fail, stencilMode.depthFail, stencilMode.pass]);
275 this.stencilFunc.set({
276 func: stencilMode.test.func,
277 ref: stencilMode.ref,
278 mask: stencilMode.test.mask
279 });
280 }
281 }
282
283 setColorMode(colorMode: Readonly<ColorMode>) {
284 if (deepEqual(colorMode.blendFunction, ColorMode.Replace)) {
285 this.blend.set(false);
286 } else {
287 this.blend.set(true);
288 this.blendFunc.set(colorMode.blendFunction);
289 this.blendColor.set(colorMode.blendColor);
290 }
291
292 this.colorMask.set(colorMode.mask);
293 }
294
295 unbindVAO() {
296 // Unbinding the VAO prevents other things (custom layers, new buffer creation) from
297 // unintentionally changing the state of the last VAO used.
298 if (this.extVertexArrayObject) {
299 this.bindVertexArrayOES.set(null);
300 }
301 }
302}
303
304export default Context;