Skip to content

Commit

Permalink
Introduce ColorMode, StencilMode, DepthMode abstractions
Browse files Browse the repository at this point in the history
  • Loading branch information
Lauren Budorick authored Dec 13, 2017
1 parent cca8ba4 commit 4658095
Show file tree
Hide file tree
Showing 18 changed files with 272 additions and 146 deletions.
38 changes: 38 additions & 0 deletions src/gl/color_mode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// @flow
const Color = require('../style-spec/util/color');

import type {BlendFuncType, ColorMaskType} from './types';

const ZERO = 0x0000;
const ONE = 0x0001;
const ONE_MINUS_SRC_ALPHA = 0x0303;

class ColorMode {
blendFunction: BlendFuncType;
blendColor: Color;
mask: ColorMaskType;

constructor(blendFunction: BlendFuncType, blendColor: Color, mask: ColorMaskType) {
this.blendFunction = blendFunction;
this.blendColor = blendColor;
this.mask = mask;
}

static Replace: BlendFuncType;

static disabled(): ColorMode {
return new ColorMode(ColorMode.Replace, Color.transparent, [false, false, false, false]);
}

static unblended(): ColorMode {
return new ColorMode(ColorMode.Replace, Color.transparent, [true, true, true, true]);
}

static alphaBlended(): ColorMode {
return new ColorMode([ONE, ONE_MINUS_SRC_ALPHA], Color.transparent, [true, true, true, true]);
}
}

ColorMode.Replace = [ONE, ZERO];

module.exports = ColorMode;
44 changes: 44 additions & 0 deletions src/gl/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ const IndexBuffer = require('./index_buffer');
const VertexBuffer = require('./vertex_buffer');
const Framebuffer = require('./framebuffer');
const State = require('./state');
const DepthMode = require('./depth_mode');
const StencilMode = require('./stencil_mode');
const ColorMode = require('./color_mode');
const util = require('../util/util');
const {
ClearColor,
ClearDepth,
Expand Down Expand Up @@ -59,6 +63,7 @@ class Context {
gl: WebGLRenderingContext;
extVertexArrayObject: any;
currentNumAttributes: ?number;
lineWidthRange: [number, number];

clearColor: State<Color>;
clearDepth: State<number>;
Expand Down Expand Up @@ -95,6 +100,7 @@ class Context {
constructor(gl: WebGLRenderingContext) {
this.gl = gl;
this.extVertexArrayObject = this.gl.getExtension('OES_vertex_array_object');
this.lineWidthRange = gl.getParameter(gl.ALIASED_LINE_WIDTH_RANGE);

this.clearColor = new State(new ClearColor(this));
this.clearDepth = new State(new ClearDepth(this));
Expand Down Expand Up @@ -188,6 +194,44 @@ class Context {

gl.clear(mask);
}

setDepthMode(depthMode: DepthMode) {
if (depthMode.func === this.gl.ALWAYS && !depthMode.mask) {
this.depthTest.set(false);
} else {
this.depthTest.set(true);
this.depthFunc.set(depthMode.func);
this.depthMask.set(depthMode.mask);
this.depthRange.set(depthMode.range);
}
}

setStencilMode(stencilMode: StencilMode) {
if (stencilMode.func === this.gl.ALWAYS && !stencilMode.mask) {
this.stencilTest.set(false);
} else {
this.stencilTest.set(true);
this.stencilMask.set(stencilMode.mask);
this.stencilOp.set([stencilMode.fail, stencilMode.depthFail, stencilMode.pass]);
this.stencilFunc.set({
func: stencilMode.test.func,
ref: stencilMode.ref,
mask: stencilMode.test.mask
});
}
}

setColorMode(colorMode: ColorMode) {
if (util.deepEqual(colorMode.blendFunction, ColorMode.Replace)) {
this.blend.set(false);
} else {
this.blend.set(true);
this.blendFunc.set(colorMode.blendFunction);
this.blendColor.set(colorMode.blendColor);
}

this.colorMask.set(colorMode.mask);
}
}

module.exports = Context;
29 changes: 29 additions & 0 deletions src/gl/depth_mode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// @flow
import type { DepthFuncType, DepthMaskType, DepthRangeType } from './types';

const ALWAYS = 0x0207;

class DepthMode {
func: DepthFuncType;
mask: DepthMaskType;
range: DepthRangeType;

// DepthMask enums
static ReadOnly: boolean;
static ReadWrite: boolean;

constructor(depthFunc: DepthFuncType, depthMask: DepthMaskType, depthRange: DepthRangeType) {
this.func = depthFunc;
this.mask = depthMask;
this.range = depthRange;
}

static disabled() {
return new DepthMode(ALWAYS, DepthMode.ReadOnly, [0, 1]);
}
}

DepthMode.ReadOnly = false;
DepthMode.ReadWrite = true;

module.exports = DepthMode;
30 changes: 30 additions & 0 deletions src/gl/stencil_mode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// @flow
import type { StencilOpConstant, StencilTest } from './types';

const ALWAYS = 0x0207;
const KEEP = 0x1E00;

class StencilMode {
test: StencilTest;
ref: number;
mask: number;
fail: StencilOpConstant;
depthFail: StencilOpConstant;
pass: StencilOpConstant;

constructor(test: StencilTest, ref: number, mask: number, fail: StencilOpConstant,
depthFail: StencilOpConstant, pass: StencilOpConstant) {
this.test = test;
this.ref = ref;
this.mask = mask;
this.fail = fail;
this.depthFail = depthFail;
this.pass = pass;
}

static disabled() {
return new StencilMode({ func: ALWAYS, mask: 0 }, 0, 0, KEEP, KEEP, KEEP);
}
}

module.exports = StencilMode;
22 changes: 17 additions & 5 deletions src/gl/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ export type BlendFuncType = [BlendFuncConstant, BlendFuncConstant];

export type ColorMaskType = [boolean, boolean, boolean, boolean];

export type DepthRangeType = [number, number];

export type CompareFuncType =
| $PropertyType<WebGLRenderingContext, 'NEVER'>
| $PropertyType<WebGLRenderingContext, 'LESS'>
Expand All @@ -33,15 +31,19 @@ export type CompareFuncType =
| $PropertyType<WebGLRenderingContext, 'GEQUAL'>
| $PropertyType<WebGLRenderingContext, 'ALWAYS'>;

export type DepthMaskType = boolean;

export type DepthRangeType = [number, number];

export type DepthFuncType = CompareFuncType;

export type StencilFuncType = {
func: CompareFuncType,
ref: number,
mask: number
};

export type DepthFuncType = CompareFuncType;

type StencilOpConstant =
export type StencilOpConstant =
| $PropertyType<WebGLRenderingContext, 'KEEP'>
| $PropertyType<WebGLRenderingContext, 'ZERO'>
| $PropertyType<WebGLRenderingContext, 'REPLACE'>
Expand All @@ -56,3 +58,13 @@ export type StencilOpType = [StencilOpConstant, StencilOpConstant, StencilOpCons
export type TextureUnitType = number;

export type ViewportType = [number, number, number, number];

export type StencilTest =
| { func: $PropertyType<WebGLRenderingContext, 'NEVER'>, mask: 0 }
| { func: $PropertyType<WebGLRenderingContext, 'LESS'>, mask: number }
| { func: $PropertyType<WebGLRenderingContext, 'EQUAL'>, mask: number }
| { func: $PropertyType<WebGLRenderingContext, 'LEQUAL'>, mask: number }
| { func: $PropertyType<WebGLRenderingContext, 'GREATER'>, mask: number }
| { func: $PropertyType<WebGLRenderingContext, 'NOTEQUAL'>, mask: number }
| { func: $PropertyType<WebGLRenderingContext, 'GEQUAL'>, mask: number }
| { func: $PropertyType<WebGLRenderingContext, 'ALWAYS'>, mask: 0 };
8 changes: 5 additions & 3 deletions src/gl/value.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
BlendFuncType,
ColorMaskType,
DepthRangeType,
DepthMaskType,
StencilFuncType,
StencilOpType,
DepthFuncType,
Expand Down Expand Up @@ -66,10 +67,10 @@ class ColorMask extends ContextValue implements Value<ColorMaskType> {
}
}

class DepthMask extends ContextValue implements Value<boolean> {
class DepthMask extends ContextValue implements Value<DepthMaskType> {
static default() { return true; }

set(v: boolean): void {
set(v: DepthMaskType): void {
this.context.gl.depthMask(v);
}
}
Expand Down Expand Up @@ -199,7 +200,8 @@ class LineWidth extends ContextValue implements Value<number> {
static default() { return 1; }

set(v: number): void {
this.context.gl.lineWidth(v);
const range = this.context.lineWidthRange;
this.context.gl.lineWidth(util.clamp(v, range[0], range[1]));
}
}

Expand Down
8 changes: 5 additions & 3 deletions src/render/draw_background.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const pattern = require('./pattern');
const {ProgramConfiguration} = require('../data/program_configuration');
const {PossiblyEvaluated, PossiblyEvaluatedPropertyValue} = require('../style/properties');
const fillLayerPaintProperties = require('../style/style_layer/fill_style_layer_properties').paint;
const StencilMode = require('../gl/stencil_mode');
const DepthMode = require('../gl/depth_mode');

import type Painter from './painter';
import type SourceCache from '../source/source_cache';
Expand All @@ -27,9 +29,9 @@ function drawBackground(painter: Painter, sourceCache: SourceCache, layer: Backg
const pass = (!image && color.a === 1 && opacity === 1) ? 'opaque' : 'translucent';
if (painter.renderPass !== pass) return;

context.stencilTest.set(false);
context.depthMask.set(pass === 'opaque');
painter.setDepthSublayer(0);
context.setStencilMode(StencilMode.disabled());
context.setDepthMode(painter.depthModeForSublayer(0, pass === 'opaque' ? DepthMode.ReadWrite : DepthMode.ReadOnly));
context.setColorMode(painter.colorModeForRenderPass());

const properties = new PossiblyEvaluated(fillLayerPaintProperties);

Expand Down
9 changes: 5 additions & 4 deletions src/render/draw_circle.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// @flow

const pixelsToTileUnits = require('../source/pixels_to_tile_units');
const StencilMode = require('../gl/stencil_mode');
const DepthMode = require('../gl/depth_mode');

import type Painter from './painter';
import type SourceCache from '../source/source_cache';
Expand All @@ -24,12 +26,11 @@ function drawCircles(painter: Painter, sourceCache: SourceCache, layer: CircleSt
const context = painter.context;
const gl = context.gl;

painter.setDepthSublayer(0);
context.depthMask.set(false);

context.setDepthMode(painter.depthModeForSublayer(0, DepthMode.ReadOnly));
// Allow circles to be drawn across boundaries, so that
// large circles are not clipped to tiles
context.stencilTest.set(false);
context.setStencilMode(StencilMode.disabled());
context.setColorMode(painter.colorModeForRenderPass());

for (let i = 0; i < coords.length; i++) {
const coord = coords[i];
Expand Down
10 changes: 9 additions & 1 deletion src/render/draw_collision_debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@ import type StyleLayer from '../style/style_layer';
import type {OverscaledTileID} from '../source/tile_id';
import type SymbolBucket from '../data/bucket/symbol_bucket';
const pixelsToTileUnits = require('../source/pixels_to_tile_units');
const DepthMode = require('../gl/depth_mode');
const StencilMode = require('../gl/stencil_mode');

module.exports = drawCollisionDebug;

function drawCollisionDebugGeometry(painter: Painter, sourceCache: SourceCache, layer: StyleLayer, coords: Array<OverscaledTileID>, drawCircles: boolean) {
const context = painter.context;
const gl = context.gl;
const program = drawCircles ? painter.useProgram('collisionCircle') : painter.useProgram('collisionBox');

context.setDepthMode(DepthMode.disabled());
context.setStencilMode(StencilMode.disabled());
context.setColorMode(painter.colorModeForRenderPass());

for (let i = 0; i < coords.length; i++) {
const coord = coords[i];
const tile = sourceCache.getTile(coord);
Expand All @@ -21,10 +28,11 @@ function drawCollisionDebugGeometry(painter: Painter, sourceCache: SourceCache,
const buffers = drawCircles ? bucket.collisionCircle : bucket.collisionBox;
if (!buffers) continue;


gl.uniformMatrix4fv(program.uniforms.u_matrix, false, coord.posMatrix);

if (!drawCircles) {
painter.lineWidth(1);
context.lineWidth.set(1);
}

gl.uniform1f(program.uniforms.u_camera_to_center_distance, painter.transform.cameraToCenterDistance);
Expand Down
9 changes: 7 additions & 2 deletions src/render/draw_debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ const mat4 = require('@mapbox/gl-matrix').mat4;
const EXTENT = require('../data/extent');
const VertexArrayObject = require('./vertex_array_object');
const PosArray = require('../data/pos_array');
const DepthMode = require('../gl/depth_mode');
const StencilMode = require('../gl/stencil_mode');

import type Painter from './painter';
import type SourceCache from '../source/source_cache';
Expand All @@ -22,12 +24,15 @@ function drawDebugTile(painter, sourceCache, coord) {
const context = painter.context;
const gl = context.gl;

context.stencilTest.set(false);
painter.lineWidth(1 * browser.devicePixelRatio);
context.lineWidth.set(1 * browser.devicePixelRatio);

const posMatrix = coord.posMatrix;
const program = painter.useProgram('debug');

context.setDepthMode(DepthMode.disabled());
context.setStencilMode(StencilMode.disabled());
context.setColorMode(painter.colorModeForRenderPass());

gl.uniformMatrix4fv(program.uniforms.u_matrix, false, posMatrix);
gl.uniform4f(program.uniforms.u_color, 1, 0, 0, 1);
painter.debugVAO.bind(context, program, painter.debugBuffer);
Expand Down
Loading

0 comments on commit 4658095

Please sign in to comment.