Skip to content

Commit

Permalink
Refactor all offscreen passes, move painter extensions into context, …
Browse files Browse the repository at this point in the history
…have framebuffers destroy their own attachments
  • Loading branch information
Lauren Budorick committed Dec 5, 2017
1 parent dd6d831 commit 470e764
Show file tree
Hide file tree
Showing 13 changed files with 221 additions and 198 deletions.
23 changes: 21 additions & 2 deletions src/gl/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ class Context {
pixelStoreUnpack: State<number>;
pixelStoreUnpackPremultiplyAlpha: State<boolean>;

extTextureFilterAnisotropic: any;
extTextureFilterAnisotropicMax: any;
extTextureHalfFloat: any;

constructor(gl: WebGLRenderingContext) {
this.gl = gl;
this.extVertexArrayObject = this.gl.getExtension('OES_vertex_array_object');
Expand Down Expand Up @@ -119,6 +123,21 @@ class Context {
this.bindVertexArrayOES = this.extVertexArrayObject && new State(new BindVertexArrayOES(this));
this.pixelStoreUnpack = new State(new PixelStoreUnpack(this));
this.pixelStoreUnpackPremultiplyAlpha = new State(new PixelStoreUnpackPremultiplyAlpha(this));

this.extTextureFilterAnisotropic = (
gl.getExtension('EXT_texture_filter_anisotropic') ||
gl.getExtension('MOZ_EXT_texture_filter_anisotropic') ||
gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic')
);
if (this.extTextureFilterAnisotropic) {
this.extTextureFilterAnisotropicMax = gl.getParameter(this.extTextureFilterAnisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT);
}

this.extTextureHalfFloat = gl.getExtension('OES_texture_half_float');
if (this.extTextureHalfFloat) {
gl.getExtension('OES_texture_half_float_linear');
}

}

createIndexBuffer(array: TriangleIndexArray | LineIndexArray, dynamicDraw?: boolean) {
Expand All @@ -140,8 +159,8 @@ class Context {
return rbo;
}

createFramebuffer() {
return new Framebuffer(this);
createFramebuffer(width: number, height: number) {
return new Framebuffer(this, width, height);
}

clear({color, depth}: ClearArgs) {
Expand Down
21 changes: 20 additions & 1 deletion src/gl/framebuffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,37 @@ import type Context from './context';

class Framebuffer {
context: Context;
width: number;
height: number;
framebuffer: WebGLFramebuffer;
colorAttachment: State<?WebGLTexture>;
depthAttachment: State<?WebGLRenderbuffer>;

constructor(context: Context) {
constructor(context: Context, width: number, height: number) {
this.context = context;
this.width = width;
this.height = height;
const gl = context.gl;
const fbo = this.framebuffer = gl.createFramebuffer();

this.colorAttachment = new State(new ColorAttachment(context, fbo));
this.depthAttachment = new State(new DepthAttachment(context, fbo));
}

destroy() {
const gl = this.context.gl;

const texture = this.colorAttachment.get();
if (texture) gl.deleteTexture(texture);

const renderbuffer = this.depthAttachment.get();
if (renderbuffer) gl.deleteRenderbuffer(renderbuffer);

gl.deleteFramebuffer(this.framebuffer);

// TODO we could actually preserve framebuffer on resize since it
// has no inherent size-dependent storage, and just destroy attachments...
}
}

module.exports = Framebuffer;
25 changes: 12 additions & 13 deletions src/gl/value.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// @flow
const assert = require('assert');

const Color = require('../style-spec/util/color');
const util = require('../util/util');
const window = require('../util/window');

import type Context from './context';
import type {
Expand All @@ -26,13 +24,9 @@ export interface Value<T> {

class ContextValue {
context: Context;
parent: ?any;

constructor(context: Context, parent: ?any) {
constructor(context: Context) {
this.context = context;
if (parent) {
this.parent = parent;
}
}

static equal(a, b): boolean {
Expand Down Expand Up @@ -332,13 +326,20 @@ class PixelStoreUnpackPremultiplyAlpha extends ContextValue implements Value<boo
/**
* Framebuffer values
*/
class FramebufferValue extends ContextValue {
context: Context;
parent: WebGLFramebuffer;

class ColorAttachment extends ContextValue implements Value<?WebGLTexture> {
constructor(context: Context, parent: WebGLFramebuffer) {
super(context);
this.parent = parent;
}
}

class ColorAttachment extends FramebufferValue implements Value<?WebGLTexture> {
static default() { return null; }

set(v: ?WebGLTexture): void {
assert(this.parent && this.parent instanceof window.WebGLFramebuffer);

const gl = this.context.gl;
this.context.bindFramebuffer.set(this.parent);
// note: it's possible to attach a renderbuffer to the color
Expand All @@ -351,12 +352,10 @@ class ColorAttachment extends ContextValue implements Value<?WebGLTexture> {
}
}

class DepthAttachment extends ContextValue implements Value<?WebGLRenderbuffer> {
class DepthAttachment extends FramebufferValue implements Value<?WebGLRenderbuffer> {
static default() { return null; }

set(v: ?WebGLRenderbuffer): void {
assert(this.parent && this.parent instanceof window.WebGLFramebuffer);

const gl = this.context.gl;
this.context.bindFramebuffer.set(this.parent);
// note: it's possible to attach a texture to the depth attachment
Expand Down
33 changes: 32 additions & 1 deletion src/render/draw_fill_extrusion.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const glMatrix = require('@mapbox/gl-matrix');
const pattern = require('./pattern');
const Texture = require('./texture');
const Color = require('../style-spec/util/color');
const mat3 = glMatrix.mat3;
const mat4 = glMatrix.mat4;
Expand All @@ -20,9 +21,11 @@ function draw(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLa
return;
}

if (painter.renderPass === '3d') {
if (painter.renderPass === 'offscreen') {
const context = painter.context;

setupFramebuffer(painter, layer);

context.stencilTest.set(false);
context.depthTest.set(true);

Expand All @@ -37,6 +40,34 @@ function draw(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLa
}
}

function setupFramebuffer(painter, layer) {
const context = painter.context;
const gl = context.gl;

let renderTarget = layer.viewportFrame;

if (painter.depthRboNeedsClear) {
painter.setupOffscreenDepthRenderbuffer();
}

if (!renderTarget) {
const texture = new Texture(context, {width: painter.width, height: painter.height, data: null}, gl.RGBA);
texture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);

renderTarget = layer.viewportFrame = context.createFramebuffer(painter.width, painter.height);
renderTarget.colorAttachment.set(texture.texture);
}

context.bindFramebuffer.set(renderTarget.framebuffer);
renderTarget.depthAttachment.set(painter.depthRbo);

if (painter.depthRboNeedsClear) {
context.clear({ depth: 1 });
painter.depthRboNeedsClear = false;
}

}

function drawExtrusionTexture(painter, layer) {
const renderedTexture = layer.viewportFrame;
if (!renderedTexture) return;
Expand Down
Loading

0 comments on commit 470e764

Please sign in to comment.