Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add option to disable WebGL rendering #2134

Merged
merged 5 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions packages/app-utils/src/storage/LocalWorkspaceStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ export class LocalWorkspaceStorage implements WorkspaceStorage {
defaultNotebookSettings: {
isMinimapEnabled: false,
},
webgl: true,
webglEditable: true,
};
const serverSettings = {
defaultDateTimeFormat: serverConfigValues?.get('dateTimeFormat'),
Expand Down Expand Up @@ -109,6 +111,14 @@ export class LocalWorkspaceStorage implements WorkspaceStorage {
) as boolean,
}
: undefined,
webgl: LocalWorkspaceStorage.getBooleanServerConfig(
serverConfigValues,
'web.webgl'
),
webglEditable: LocalWorkspaceStorage.getBooleanServerConfig(
serverConfigValues,
'web.webgl.editable'
),
};

const keys = Object.keys(serverSettings) as Array<keyof typeof settings>;
Expand Down
30 changes: 25 additions & 5 deletions packages/chart/src/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,29 @@ import useChartTheme from './useChartTheme';

const log = Log.module('Chart');

type FormatterSettings = ColumnFormatSettings &
type ChartSettings = ColumnFormatSettings &
DateTimeFormatSettings & {
decimalFormatOptions?: DecimalColumnFormatterOptions;
integerFormatOptions?: IntegerColumnFormatterOptions;
webgl?: boolean;
};

interface ChartProps {
model: ChartModel;
theme: ChartTheme;
settings: FormatterSettings;

/** User settings that are relevant to the chart, e.g. formatter settings */
settings: ChartSettings;

isActive: boolean;
Plotly: typeof Plotly;
containerRef?: React.RefObject<HTMLDivElement>;
onDisconnect: () => void;
onReconnect: () => void;
onUpdate: (obj: { isLoading: boolean }) => void;
onError: (error: Error) => void;

/** Called when the settings for the ChartModel are changed */
onSettingsChanged: (settings: Partial<ChartModelSettings>) => void;
}

Expand Down Expand Up @@ -91,6 +97,7 @@ class Chart extends Component<ChartProps, ChartState> {
showTimeZone: false,
showTSeparator: true,
formatter: [],
webgl: true,
},
Plotly,
onDisconnect: (): void => undefined,
Expand Down Expand Up @@ -195,7 +202,7 @@ class Chart extends Component<ChartProps, ChartState> {

componentDidUpdate(prevProps: ChartProps): void {
const { isActive, model, settings, theme } = this.props;
this.updateFormatterSettings(settings as FormatterSettings);
this.updateFormatterSettings(settings);

if (model !== prevProps.model) {
this.unsubscribe(prevProps.model);
Expand Down Expand Up @@ -239,6 +246,8 @@ class Chart extends Component<ChartProps, ChartState> {

integerFormatOptions: IntegerColumnFormatterOptions;

webgl?: boolean;

rect?: DOMRect;

ranges?: unknown;
Expand Down Expand Up @@ -612,10 +621,10 @@ class Chart extends Component<ChartProps, ChartState> {

initFormatter(): void {
const { settings } = this.props;
this.updateFormatterSettings(settings as FormatterSettings);
this.updateFormatterSettings(settings);
}

updateFormatterSettings(settings: FormatterSettings): void {
updateFormatterSettings(settings: ChartSettings): void {
const columnFormats = FormatterUtils.getColumnFormats(settings);
const dateTimeFormatterOptions =
FormatterUtils.getDateTimeFormatterOptions(settings);
Expand All @@ -633,6 +642,11 @@ class Chart extends Component<ChartProps, ChartState> {
this.integerFormatOptions = integerFormatOptions;
this.updateFormatter();
}

if (this.webgl !== settings.webgl) {
this.webgl = settings.webgl;
this.updateRenderOptions();
}
}

updateFormatter(): void {
Expand All @@ -647,6 +661,12 @@ class Chart extends Component<ChartProps, ChartState> {
model.setFormatter(formatter);
}

updateRenderOptions(): void {
const { model } = this.props;
const renderOptions = { webgl: this.webgl };
model.setRenderOptions(renderOptions);
}

updateDimensions(): void {
const rect = this.getPlotRect();
const { Plotly: PlotlyProp } = this.props;
Expand Down
17 changes: 17 additions & 0 deletions packages/chart/src/ChartModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ import type { Layout, Data } from 'plotly.js';
import { FilterColumnMap, FilterMap } from './ChartUtils';

export type ChartEvent = CustomEvent;

export type RenderOptions = {
/** Allow WebGL as an option. Defaults to `true`, explicitly set to `false` to disable. */
webgl?: boolean;
};

/**
* Model for a Chart
* All of these methods should return very quickly.
Expand Down Expand Up @@ -41,8 +47,11 @@ class ChartModel {

listeners: ((event: ChartEvent) => void)[];

/** Formatter settings for the chart, such as how to format dates and numbers */
formatter?: Formatter;

renderOptions?: RenderOptions;

rect?: DOMRect;

isDownsamplingDisabled: boolean;
Expand Down Expand Up @@ -86,6 +95,14 @@ class ChartModel {
this.formatter = formatter;
}

/**
* Set additional options for rendering the chart
* @param renderOptions Options for rendering the chart
*/
setRenderOptions(renderOptions: RenderOptions): void {
this.renderOptions = renderOptions;
}

/**
* Disable downsampling
* @param isDownsamplingDisabled True if downsampling should be disabled
Expand Down
21 changes: 14 additions & 7 deletions packages/chart/src/ChartUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -681,17 +681,22 @@ class ChartUtils {
* Converts the Iris plot style into a plotly chart type
* @param plotStyle The plotStyle to use, see dh.plot.SeriesPlotStyle
* @param isBusinessTime If the plot is using business time for an axis
* @param allowWebGL If WebGL is allowedd
*/
getPlotlyChartType(
plotStyle: DhType.plot.SeriesPlotStyle,
isBusinessTime: boolean
isBusinessTime: boolean,
allowWebGL = true
): PlotType | undefined {
const { dh } = this;
switch (plotStyle) {
case dh.plot.SeriesPlotStyle.SCATTER:
case dh.plot.SeriesPlotStyle.LINE:
// scattergl mode is more performant, but doesn't support the rangebreaks we need for businessTime calendars
return !isBusinessTime && IS_WEBGL_SUPPORTED ? 'scattergl' : 'scatter';
// scattergl mode is more performant (usually), but doesn't support the rangebreaks we need for businessTime calendars
// In some cases, WebGL is less performant (like in virtual desktop environments), so we also allow the option of the user explicitly disabling it even if it's supported
return !isBusinessTime && IS_WEBGL_SUPPORTED && allowWebGL
? 'scattergl'
: 'scatter';
case dh.plot.SeriesPlotStyle.BAR:
case dh.plot.SeriesPlotStyle.STACKED_BAR:
return 'bar';
Expand Down Expand Up @@ -871,7 +876,8 @@ class ChartUtils {
series: DhType.plot.Series,
axisTypeMap: AxisTypeMap,
seriesVisibility: boolean | 'legendonly',
showLegend: boolean | null = null
showLegend: boolean | null = null,
allowWebGL = true
): Partial<PlotData> {
const {
name,
Expand All @@ -888,7 +894,7 @@ class ChartUtils {
const isBusinessTime = sources.some(
source => source.axis?.businessCalendar
);
const type = this.getChartType(plotStyle, isBusinessTime);
const type = this.getChartType(plotStyle, isBusinessTime, allowWebGL);
const mode = this.getPlotlyChartMode(
plotStyle,
isLinesVisible ?? undefined,
Expand Down Expand Up @@ -1019,7 +1025,8 @@ class ChartUtils {

getChartType(
plotStyle: DhType.plot.SeriesPlotStyle,
isBusinessTime: boolean
isBusinessTime: boolean,
allowWebGL = true
): PlotType | undefined {
const { dh } = this;
switch (plotStyle) {
Expand All @@ -1028,7 +1035,7 @@ class ChartUtils {
// plot.ly to calculate the bins and sum values, just convert it to a bar chart
return 'bar';
default:
return this.getPlotlyChartType(plotStyle, isBusinessTime);
return this.getPlotlyChartType(plotStyle, isBusinessTime, allowWebGL);
}
}

Expand Down
12 changes: 10 additions & 2 deletions packages/chart/src/FigureChartModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type {
DateTimeColumnFormatter,
Formatter,
} from '@deephaven/jsapi-utils';
import ChartModel, { ChartEvent } from './ChartModel';
import ChartModel, { ChartEvent, RenderOptions } from './ChartModel';
import ChartUtils, {
AxisTypeMap,
ChartModelSettings,
Expand Down Expand Up @@ -219,7 +219,8 @@ class FigureChartModel extends ChartModel {
series,
axisTypeMap,
ChartUtils.getSeriesVisibility(series.name, this.settings),
showLegend
showLegend,
this.renderOptions?.webgl ?? true
);

this.seriesDataMap.set(series.name, seriesData);
Expand Down Expand Up @@ -535,6 +536,13 @@ class FigureChartModel extends ChartModel {
this.resubscribe();
}

setRenderOptions(renderOptions: RenderOptions): void {
super.setRenderOptions(renderOptions);

// Reset all the series to re-render them with the correct rendering options
this.initAllSeries();
}

setDownsamplingDisabled(isDownsamplingDisabled: boolean): void {
super.setDownsamplingDisabled(isDownsamplingDisabled);

Expand Down
66 changes: 66 additions & 0 deletions packages/code-studio/src/settings/AdvancedSectionContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React, { useCallback } from 'react';
import { useDispatch } from 'react-redux';
import {
Content,
ContextualHelp,
Heading,
Switch,
Text,
} from '@deephaven/components';
import { getWebGL, getWebGLEditable, updateSettings } from '@deephaven/redux';
import { useAppSelector } from '@deephaven/dashboard';

function AdvancedSectionContent(): JSX.Element {
const dispatch = useDispatch();
const webgl = useAppSelector(getWebGL);
const webglEditable = useAppSelector(getWebGLEditable);

const handleWebglChange = useCallback(
newValue => {
dispatch(updateSettings({ webgl: newValue }));
},
[dispatch]
);

const helpText = webglEditable ? (
<Text>
WebGL in most cases has significant performance improvements, particularly
when plotting large datasets. However, in some environments (such as
remote desktop environments), WebGL may not use hardware acceleration and
have degraded performance. If you are experiencing issues with WebGL, you
can disable it here.
</Text>
) : (
<Text>
WebGL is disabled by your system administrator. Contact your system
administrator to enable.
</Text>
);

return (
<>
<div className="app-settings-menu-description">
Advanced settings here. Be careful!
</div>

<div className="form-row mb-3 pl-1">
<Switch
isSelected={webgl}
isDisabled={!webglEditable}
onChange={handleWebglChange}
marginEnd="size-0"
>
Enable WebGL
</Switch>
<ContextualHelp variant="info" marginTop="size-50">
<Heading>Enable WebGL</Heading>
<Content>
<Text>{helpText}</Text>
</Content>
</ContextualHelp>
</div>
</>
);
}

export default AdvancedSectionContent;
29 changes: 28 additions & 1 deletion packages/code-studio/src/settings/SettingsMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
vsPaintcan,
dhUserIncognito,
dhUser,
vsTools,
} from '@deephaven/icons';
import {
Button,
Expand Down Expand Up @@ -38,6 +39,7 @@ import {
getFormattedPluginInfo,
getFormattedVersionInfo,
} from './SettingsUtils';
import AdvancedSectionContent from './AdvancedSectionContent';

interface SettingsMenuProps {
serverConfigValues: ServerConfigValues;
Expand Down Expand Up @@ -68,6 +70,8 @@ export class SettingsMenu extends Component<

static THEME_SECTION_KEY = 'SettingsMenu.theme';

static ADVANCED_SECTION_KEY = 'SettingsMenu.advanced';

static focusFirstInputInContainer(container: HTMLDivElement | null): void {
const input = container?.querySelector('input, select, textarea');
if (input) {
Expand Down Expand Up @@ -289,14 +293,37 @@ export class SettingsMenu extends Component<
)}
title={
<>
<FontAwesomeIcon icon={vsRecordKeys} transform="grow-2" />{' '}
<FontAwesomeIcon
icon={vsRecordKeys}
transform="grow-2"
className="mr-2"
/>
Keyboard Shortcuts
</>
}
onToggle={this.handleSectionToggle}
>
<ShortcutSectionContent />
</SettingsMenuSection>
<SettingsMenuSection
sectionKey={SettingsMenu.ADVANCED_SECTION_KEY}
isExpanded={this.isSectionExpanded(
SettingsMenu.ADVANCED_SECTION_KEY
)}
title={
<>
<FontAwesomeIcon
icon={vsTools}
transform="grow-4"
className="mr-2"
/>
Advanced
</>
}
onToggle={this.handleSectionToggle}
>
<AdvancedSectionContent />
</SettingsMenuSection>

<div className="app-settings-footer">
<div className="app-settings-footer-section">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,4 +199,7 @@

/* Editing */
--dh-color-modified: var(--dh-color-yellow-1300);

/* Components */
--dh-toggle-switch-bg: var(--dh-color-gray-500);
mofojed marked this conversation as resolved.
Show resolved Hide resolved
}
Loading
Loading