Compare commits

...

10 Commits

Author SHA1 Message Date
Alexander Rose
26cc7e94c2 2.3.9 2021-11-20 16:58:28 -08:00
Alexander Rose
c6fe6ddcba switch off VAO support for now 2021-11-20 16:54:38 -08:00
Alexander Rose
154984e74d 2.3.8 2021-11-20 16:30:22 -08:00
Alexander Rose
72fcaf8321 changelog 2021-11-20 16:24:54 -08:00
Alexander Rose
0c14ca5888 workaround for VAO issue in Chrome 96 2021-11-20 16:14:30 -08:00
Alexander Rose
a85ede5058 fix unused vertex attribute handling 2021-11-20 16:13:18 -08:00
Alexander Rose
db49a16184 fix double canvas context creation 2021-11-20 12:52:47 -08:00
dsehnal
0704db2343 replace webpack-version-file-plugin 2021-11-20 13:45:28 +01:00
dsehnal
425dca4665 fix sass division 2021-11-20 12:55:46 +01:00
dsehnal
8d65ccabd2 update packages
- use sass instead of node sass
2021-11-20 12:49:26 +01:00
16 changed files with 895 additions and 2112 deletions

View File

@@ -6,6 +6,18 @@ Note that since we don't clearly distinguish between a public and private interf
## [Unreleased]
## [v2.3.9] - 2021-11-20
- Workaround: switch off VAO support for now
## [v2.3.8] - 2021-11-20
- Fix double canvas context creation (in plugin context)
- Fix unused vertex attribute handling (track which are used, disable the rest)
- Workaround for VAO issue in Chrome 96 (can cause WebGL to crash on geometry updates)
## [v2.3.7] - 2021-11-15
- Added ``ViewerOptions.collapseRightPanel``
- Added ``Viewer.loadTrajectory`` to support loading "composed" trajectories (e.g. from gro + xtc)
- Fix: handle parent in Structure.remapModel

2843
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "molstar",
"version": "2.3.7",
"version": "2.3.9",
"description": "A comprehensive macromolecular library.",
"homepage": "https://github.com/molstar/molstar#readme",
"repository": {
@@ -113,18 +113,17 @@
"http-server": "^13.0.2",
"jest": "^27.2.4",
"mini-css-extract-plugin": "^2.3.0",
"node-sass": "^6.0.1",
"path-browserify": "^1.0.1",
"raw-loader": "^4.0.2",
"sass-loader": "^12.1.0",
"sass": "^1.43.4",
"sass-loader": "^12.3.0",
"simple-git": "^2.46.0",
"stream-browserify": "^3.0.0",
"style-loader": "^3.3.0",
"ts-jest": "^27.0.5",
"typescript": "^4.4.3",
"webpack": "^5.56.0",
"webpack-cli": "^4.8.0",
"webpack-version-file-plugin": "^0.4.0"
"typescript": "^4.5.2",
"webpack": "^5.64.1",
"webpack-cli": "^4.9.1"
},
"dependencies": {
"@types/argparse": "^2.0.10",

View File

@@ -53,7 +53,7 @@ describe('renderer', () => {
scene.commit();
expect(ctx.stats.resourceCounts.attribute).toBe(ctx.isWebGL2 ? 4 : 5);
expect(ctx.stats.resourceCounts.texture).toBe(7);
expect(ctx.stats.resourceCounts.vertexArray).toBe(8);
expect(ctx.stats.resourceCounts.vertexArray).toBe(ctx.extensions.vertexArrayObject ? 8 : 0);
expect(ctx.stats.resourceCounts.program).toBe(8);
expect(ctx.stats.resourceCounts.shader).toBe(16);

View File

@@ -91,7 +91,7 @@ export function printImageData(imageData: ImageData, options: Partial<PrintImage
}
canvas.toBlob(imgBlob => {
const objectURL = URL.createObjectURL(imgBlob);
const objectURL = URL.createObjectURL(imgBlob!);
const existingImg = document.getElementById(o.id) as HTMLImageElement;
const img = existingImg || document.createElement('img');
img.id = o.id;

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -11,6 +11,7 @@ import { idFactory } from '../../mol-util/id-factory';
import { ValueOf } from '../../mol-util/type-helpers';
import { GLRenderingContext } from './compat';
import { WebGLExtensions } from './extensions';
import { WebGLState } from './state';
const getNextBufferId = idFactory();
@@ -192,7 +193,7 @@ export interface AttributeBuffer extends Buffer {
bind: (location: number) => void
}
export function createAttributeBuffer<T extends ArrayType, S extends AttributeItemSize>(gl: GLRenderingContext, extensions: WebGLExtensions, array: T, itemSize: S, divisor: number, usageHint: UsageHint = 'dynamic'): AttributeBuffer {
export function createAttributeBuffer<T extends ArrayType, S extends AttributeItemSize>(gl: GLRenderingContext, state: WebGLState, extensions: WebGLExtensions, array: T, itemSize: S, divisor: number, usageHint: UsageHint = 'dynamic'): AttributeBuffer {
const { instancedArrays } = extensions;
const buffer = createBuffer(gl, array, usageHint, 'attribute');
@@ -204,12 +205,12 @@ export function createAttributeBuffer<T extends ArrayType, S extends AttributeIt
gl.bindBuffer(_bufferType, buffer.getBuffer());
if (itemSize === 16) {
for (let i = 0; i < 4; ++i) {
gl.enableVertexAttribArray(location + i);
state.enableVertexAttrib(location + i);
gl.vertexAttribPointer(location + i, 4, _dataType, false, 4 * 4 * _bpe, i * 4 * _bpe);
instancedArrays.vertexAttribDivisor(location + i, divisor);
}
} else {
gl.enableVertexAttribArray(location);
state.enableVertexAttrib(location);
gl.vertexAttribPointer(location, itemSize, _dataType, false, 0, 0);
instancedArrays.vertexAttribDivisor(location, divisor);
}

View File

@@ -4,7 +4,7 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { GLRenderingContext, COMPAT_instanced_arrays, COMPAT_standard_derivatives, COMPAT_vertex_array_object, getInstancedArrays, getStandardDerivatives, getVertexArrayObject, COMPAT_element_index_uint, getElementIndexUint, COMPAT_texture_float, getTextureFloat, COMPAT_texture_float_linear, getTextureFloatLinear, COMPAT_blend_minmax, getBlendMinMax, getFragDepth, COMPAT_frag_depth, COMPAT_color_buffer_float, getColorBufferFloat, COMPAT_draw_buffers, getDrawBuffers, getShaderTextureLod, COMPAT_shader_texture_lod, getDepthTexture, COMPAT_depth_texture, COMPAT_sRGB, getSRGB, getTextureHalfFloat, getTextureHalfFloatLinear, COMPAT_texture_half_float, COMPAT_texture_half_float_linear, COMPAT_color_buffer_half_float, getColorBufferHalfFloat } from './compat';
import { GLRenderingContext, COMPAT_instanced_arrays, COMPAT_standard_derivatives, COMPAT_vertex_array_object, getInstancedArrays, getStandardDerivatives, COMPAT_element_index_uint, getElementIndexUint, COMPAT_texture_float, getTextureFloat, COMPAT_texture_float_linear, getTextureFloatLinear, COMPAT_blend_minmax, getBlendMinMax, getFragDepth, COMPAT_frag_depth, COMPAT_color_buffer_float, getColorBufferFloat, COMPAT_draw_buffers, getDrawBuffers, getShaderTextureLod, COMPAT_shader_texture_lod, getDepthTexture, COMPAT_depth_texture, COMPAT_sRGB, getSRGB, getTextureHalfFloat, getTextureHalfFloatLinear, COMPAT_texture_half_float, COMPAT_texture_half_float_linear, COMPAT_color_buffer_half_float, getColorBufferHalfFloat } from './compat';
import { isDebugMode } from '../../mol-util/debug';
export type WebGLExtensions = {
@@ -73,7 +73,11 @@ export function createExtensions(gl: GLRenderingContext): WebGLExtensions {
// - can't be a required extension because it is not supported by `headless-gl`
console.log('Could not find support for "blend_minmax"');
}
const vertexArrayObject = getVertexArrayObject(gl);
// TODO: revisit
// switch off VAO support for now
// - https://bugs.chromium.org/p/angleproject/issues/detail?id=6599
// - https://bugs.chromium.org/p/chromium/issues/detail?id=1272238
const vertexArrayObject = null; // getVertexArrayObject(gl);
if (isDebugMode && vertexArrayObject === null) {
console.log('Could not find support for "vertex_array_object"');
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -39,12 +39,12 @@ function getLocations(gl: GLRenderingContext, program: WebGLProgram, schema: Ren
if (spec.type === 'attribute') {
const loc = gl.getAttribLocation(program, k);
// unused attributes will result in a `-1` location which is usually fine
// if (loc === -1) console.info(`Could not get attribute location for '${k}'`)
// if (loc === -1) console.info(`Could not get attribute location for '${k}'`);
locations[k] = loc;
} else if (spec.type === 'uniform' || spec.type === 'texture') {
const loc = gl.getUniformLocation(program, k);
// unused uniforms will result in a `null` location which is usually fine
// if (loc === null) console.info(`Could not get uniform location for '${k}'`)
// if (loc === null) console.info(`Could not get uniform location for '${k}'`);
locations[k] = loc as number;
}
});
@@ -192,11 +192,13 @@ export function createProgram(gl: GLRenderingContext, state: WebGLState, extensi
}
},
bindAttributes: (attributeBuffers: AttributeBuffers) => {
state.clearVertexAttribsState();
for (let i = 0, il = attributeBuffers.length; i < il; ++i) {
const [k, buffer] = attributeBuffers[i];
const l = locations[k];
if (l !== -1) buffer.bind(l);
}
state.disableUnusedVertexAttribs();
},
bindTextures: (textures: Textures, startingTargetUnit: number) => {
for (let i = 0, il = textures.length; i < il; ++i) {

View File

@@ -67,15 +67,9 @@ function createProgramVariant(ctx: WebGLContext, variant: string, defineValues:
//
type ProgramVariants = { [k: string]: Program }
type VertexArrayVariants = { [k: string]: VertexArray | null }
type ProgramVariants = Record<string, Program>
type VertexArrayVariants = Record<string, VertexArray | null>
interface ValueChanges {
attributes: boolean
defines: boolean
elements: boolean
textures: boolean
}
function createValueChanges() {
return {
attributes: false,
@@ -84,6 +78,8 @@ function createValueChanges() {
textures: false,
};
}
type ValueChanges = ReturnType<typeof createValueChanges>
function resetValueChanges(valueChanges: ValueChanges) {
valueChanges.attributes = false;
valueChanges.defines = false;

View File

@@ -114,7 +114,7 @@ export function createResources(gl: GLRenderingContext, state: WebGLState, stats
return {
attribute: (array: ArrayType, itemSize: AttributeItemSize, divisor: number, usageHint?: UsageHint) => {
return wrap('attribute', createAttributeBuffer(gl, extensions, array, itemSize, divisor, usageHint));
return wrap('attribute', createAttributeBuffer(gl, state, extensions, array, itemSize, divisor, usageHint));
},
elements: (array: ElementsType, usageHint?: UsageHint) => {
return wrap('elements', createElementsBuffer(gl, array, usageHint));

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -59,11 +59,15 @@ export type WebGLState = {
/** set the RGB blend equation and alpha blend equation separately, determines how a new pixel is combined with an existing */
blendEquationSeparate: (modeRGB: number, modeAlpha: number) => void
enableVertexAttrib: (index: number) => void
clearVertexAttribsState: () => void
disableUnusedVertexAttribs: () => void
reset: () => void
}
export function createState(gl: GLRenderingContext): WebGLState {
let enabledCapabilities: { [k: number]: boolean } = {};
let enabledCapabilities: Record<number, boolean> = {};
let currentFrontFace = gl.getParameter(gl.FRONT_FACE);
let currentCullFace = gl.getParameter(gl.CULL_FACE_MODE);
@@ -79,6 +83,16 @@ export function createState(gl: GLRenderingContext): WebGLState {
let currentBlendEqRGB = gl.getParameter(gl.BLEND_EQUATION_RGB);
let currentBlendEqAlpha = gl.getParameter(gl.BLEND_EQUATION_ALPHA);
let maxVertexAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
const vertexAttribsState: number[] = [];
const clearVertexAttribsState = () => {
for (let i = 0; i < maxVertexAttribs; ++i) {
vertexAttribsState[i] = 0;
}
};
clearVertexAttribsState();
return {
currentProgramId: -1,
currentMaterialId: -1,
@@ -168,6 +182,17 @@ export function createState(gl: GLRenderingContext): WebGLState {
}
},
enableVertexAttrib: (index: number) => {
gl.enableVertexAttribArray(index);
vertexAttribsState[index] = 1;
},
clearVertexAttribsState,
disableUnusedVertexAttribs: () => {
for (let i = 0; i < maxVertexAttribs; ++i) {
if (vertexAttribsState[i] === 0) gl.disableVertexAttribArray(i);
}
},
reset: () => {
enabledCapabilities = {};
@@ -184,6 +209,12 @@ export function createState(gl: GLRenderingContext): WebGLState {
currentBlendEqRGB = gl.getParameter(gl.BLEND_EQUATION_RGB);
currentBlendEqAlpha = gl.getParameter(gl.BLEND_EQUATION_ALPHA);
maxVertexAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
vertexAttribsState.length = 0;
for (let i = 0; i < maxVertexAttribs; ++i) {
vertexAttribsState[i] = 0;
}
}
};
}

View File

@@ -1,3 +1,5 @@
@use "sass:math";
.msp-control-row {
position: relative;
height: $row-height;
@@ -184,7 +186,7 @@
z-index: 100000;
background: $default-background;
border-top: 1px solid $default-background;
padding-bottom: $control-spacing / 2;
padding-bottom: math.div($control-spacing, 2);
width: 100%;
// input[type=text] {
@@ -195,8 +197,8 @@
.msp-toggle-color-picker-above {
.msp-color-picker {
top: -2 * 32px - 16px - $control-spacing / 2;
height: 2 * 32px + 16px + $control-spacing / 2;
top: -2 * 32px - 16px - math.div($control-spacing, 2);
height: 2 * 32px + 16px + math.div($control-spacing, 2);
}
}
@@ -208,10 +210,6 @@
}
.msp-control-offset {
// border-left-width: $control-spacing / 2;
// border-left-style: solid;
// border-left-color: color-increase-contrast($default-background, 10%);
// padding-left: 1px;
padding-left: $control-spacing;
}
@@ -228,7 +226,7 @@
// }
.msp-control-group-wrapper {
//border-left-width: $control-spacing / 2;
//border-left-width: math.div($control-spacing, 2);
//border-left-style: solid;
//border-left-color: color-increase-contrast($default-background, 10%);
@@ -240,10 +238,10 @@
.msp-control-group-header {
background: $default-background;
> button, div {
padding-left: 4px; // $control-spacing / 2 !important;
padding-left: 4px; // math.div($control-spacing, 2) !important;
text-align: left;
height: 24px !important; // 2 * $row-height / 3 !important;
line-height: 24px !important; // 2 * $row-height / 3 !important;
height: 24px !important;
line-height: 24px !important;
font-size: 85% !important;
background: $default-background !important;
color: color-lower-contrast($font-color, 15%);
@@ -253,8 +251,8 @@
line-height: 24px !important;
}
> span {
padding-left: $control-spacing / 2;
line-height: 2 * $row-height / 3;
padding-left: math.div($control-spacing, 2);
line-height: math.div(2 * $row-height, 3);
font-size: 70%;
background: $default-background;
color: color-lower-contrast($font-color, 15%);
@@ -267,7 +265,7 @@
.msp-control-group-footer {
background: color-increase-contrast($default-background, 5%);
height: $control-spacing / 2;
height: math.div($control-spacing, 2);
font-size: 1px;
margin-top: 1px;
}
@@ -339,7 +337,7 @@
margin-top: 1px;
> div {
padding: ($control-spacing / 2) $control-spacing;
padding: (math.div($control-spacing, 2)) $control-spacing;
text-align: left;
color: color-lower-contrast($font-color, 15%);
}
@@ -359,7 +357,7 @@
height: $control-spacing * 3;
> span {
padding: $control-spacing / 2;
padding: math.div($control-spacing, 2);
color: white;
font-weight: bold;
background-color: rgba(0, 0, 0, 0.2);
@@ -370,7 +368,7 @@
.msp-table-legend {
> div {
// min-width: 60px;
margin-right: $control-spacing / 2;
margin-right: math.div($control-spacing, 2);
display: inline-flex;
.msp-table-legend-color {
@@ -379,7 +377,7 @@
}
.msp-table-legend-text {
margin: 0 ($control-spacing / 2);
margin: 0 (math.div($control-spacing, 2));
}
}
}

View File

@@ -1,4 +1,6 @@
@use "sass:math";
.msp-toast-container {
position: relative;
// bottom: $control-spacing;
@@ -75,7 +77,7 @@
bottom: 0;
width: 100%;
text-align: right;
padding-right: $control-spacing / 2;
padding-right: math.div($control-spacing, 2);
}
}
}

View File

@@ -199,8 +199,7 @@ export class PluginContext {
const pickPadding = this.config.get(PluginConfig.General.PickPadding) ?? 1;
const enableWboit = this.config.get(PluginConfig.General.EnableWboit) || false;
const preferWebGl1 = this.config.get(PluginConfig.General.PreferWebGl1) || false;
(this.canvas3dContext as Canvas3DContext) = Canvas3DContext.fromCanvas(canvas, { antialias, preserveDrawingBuffer, pixelScale, pickScale, enableWboit, preferWebGl1 });
(this.canvas3dContext as Canvas3DContext) = Canvas3DContext.fromCanvas(canvas, { antialias, preserveDrawingBuffer, pixelScale, pickScale, pickPadding, enableWboit });
(this.canvas3dContext as Canvas3DContext) = Canvas3DContext.fromCanvas(canvas, { antialias, preserveDrawingBuffer, pixelScale, pickScale, pickPadding, enableWboit, preferWebGl1 });
}
(this.canvas3d as Canvas3D) = Canvas3D.create(this.canvas3dContext!);
this.canvas3dInit.next(true);

View File

@@ -61,7 +61,7 @@ export function download(data: Blob | string, downloadName = 'download') {
open(data);
}
} else {
const url = URL.createObjectURL(data);
const url = URL.createObjectURL(typeof data === 'string' ? new Blob([data]) : data);
location.href = url;
setTimeout(() => URL.revokeObjectURL(url), 4E4); // 40s
}

View File

@@ -1,8 +1,17 @@
const path = require('path');
const fs = require('fs');
const webpack = require('webpack');
const ExtraWatchWebpackPlugin = require('extra-watch-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const VersionFile = require('webpack-version-file-plugin');
const VERSION = require('./package.json').version;
class VersionFilePlugin {
apply() {
fs.writeFileSync(
path.resolve(__dirname, 'lib/mol-plugin/version.js'),
`export var PLUGIN_VERSION = '${VERSION}';\nexport var PLUGIN_VERSION_DATE = new Date(typeof __MOLSTAR_DEBUG_TIMESTAMP__ !== 'undefined' ? __MOLSTAR_DEBUG_TIMESTAMP__ : ${new Date().valueOf()});`);
}
}
const sharedConfig = {
module: {
@@ -36,12 +45,7 @@ const sharedConfig = {
'__MOLSTAR_DEBUG_TIMESTAMP__': webpack.DefinePlugin.runtimeValue(() => `${new Date().valueOf()}`, true)
}),
new MiniCssExtractPlugin({ filename: 'molstar.css' }),
new VersionFile({
extras: { timestamp: `${new Date().valueOf()}` },
packageFile: path.resolve(__dirname, 'package.json'),
templateString: `export var PLUGIN_VERSION = '<%= package.version %>';\nexport var PLUGIN_VERSION_DATE = new Date(typeof __MOLSTAR_DEBUG_TIMESTAMP__ !== 'undefined' ? __MOLSTAR_DEBUG_TIMESTAMP__ : <%= extras.timestamp %>);`,
outputFile: path.resolve(__dirname, 'lib/mol-plugin/version.js')
})
new VersionFilePlugin(),
],
resolve: {
modules: [