Skip to content

Commit

Permalink
line chart: introduce onContextLost renderer callback
Browse files Browse the repository at this point in the history
  • Loading branch information
psybuzz committed Aug 13, 2021
1 parent 74e7b70 commit c2ececa
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 5 deletions.
3 changes: 2 additions & 1 deletion tensorboard/webapp/widgets/line_chart_v2/lib/chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ export class ChartImpl implements Chart {
this.renderer = new ThreeRenderer(
option.container,
coordinator,
option.devicePixelRatio
option.devicePixelRatio,
option.callbacks.onContextLost
);
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export interface Chart {

export interface ChartCallbacks {
onDrawEnd(): void;
onContextLost(): void;
}

export interface BaseChartOptions {
Expand Down
41 changes: 41 additions & 0 deletions tensorboard/webapp/widgets/line_chart_v2/lib/integration_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ describe('line_chart_v2/lib/integration test', () => {
dom = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
callbacks = {
onDrawEnd: jasmine.createSpy(),
onContextLost: jasmine.createSpy(),
};
chart = new ChartImpl({
type: RendererType.SVG,
Expand Down Expand Up @@ -460,4 +461,44 @@ describe('line_chart_v2/lib/integration test', () => {
expect(circle.getAttribute('cy')).toBe('5');
});
});

describe('webgl', () => {
it('invokes onContextLost after losing webgl context', async () => {
const canvas = document.createElement('canvas');
chart = new ChartImpl({
type: RendererType.WEBGL,
container: canvas,
callbacks,
domDimension: {width: 200, height: 100},
useDarkMode: false,
devicePixelRatio: 1,
});
chart.setXScaleType(ScaleType.LINEAR);
chart.setYScaleType(ScaleType.LINEAR);

expect(callbacks.onContextLost).not.toHaveBeenCalled();

// For more info about forcing context loss, see
// https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_lose_context/loseContext
const glExtension = canvas
.getContext('webgl2')
?.getExtension('WEBGL_lose_context');
if (!glExtension) {
console.log(
'The browser used for testing does not ' +
'support WebGL or extensions needed for testing.'
);
return;
}

// The `loseContext` triggers the event asynchronously, which.
const contextLostPromise = new Promise((resolve) => {
canvas.addEventListener('webglcontextlost', resolve);
});
glExtension.loseContext();

await contextLostPromise;
expect(callbacks.onContextLost).toHaveBeenCalledTimes(1);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -268,12 +268,19 @@ export class ThreeRenderer implements ObjectRenderer<CacheValue> {
constructor(
canvas: HTMLCanvasElement | OffscreenCanvas,
private readonly coordinator: ThreeCoordinator,
devicePixelRatio: number
devicePixelRatio: number,
onContextLost?: EventListener
) {
if (isOffscreenCanvasSupported() && canvas instanceof OffscreenCanvas) {
// THREE.js require the style object which Offscreen canvas lacks.
(canvas as any).style = (canvas as any).style || {};
}
// WebGL contexts may be abandoned by the browser if too many contexts are
// created on the same page.
if (onContextLost) {
canvas.addEventListener('webglcontextlost', onContextLost);
}

this.renderer = new THREE.WebGLRenderer({
canvas: canvas as HTMLCanvasElement,
context: canvas.getContext('webgl2', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,15 @@ export type HostToGuestMessage =

export enum GuestToMainType {
ON_REDRAW_END,
ON_CONTEXT_LOST,
}

export interface RedrawEndMessage {
type: GuestToMainType.ON_REDRAW_END;
}

export type GuestToMainMessage = RedrawEndMessage;
export interface ContextLostMessage {
type: GuestToMainType.ON_CONTEXT_LOST;
}

export type GuestToMainMessage = RedrawEndMessage | ContextLostMessage;
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ export class WorkerChart implements Chart {
this.callbacks.onDrawEnd();
break;
}
case GuestToMainType.ON_CONTEXT_LOST: {
this.callbacks.onContextLost();
break;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ function createPortHandler(port: MessagePort, initMessage: InitMessage) {
type: GuestToMainType.ON_REDRAW_END,
});
},
onContextLost: () => {
port.postMessage({
type: GuestToMainType.ON_CONTEXT_LOST,
});
},
};

let chartOptions: ChartOptions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ describe('line_chart_v2/lib/worker_chart test', () => {
let workerPostMessageSpy: jasmine.Spy;
let channelTxSpy: jasmine.Spy;
let onDrawEndSpy: jasmine.Spy;
let onContextLostSpy: jasmine.Spy;
let chart: WorkerChart;

beforeEach(() => {
Expand All @@ -41,10 +42,11 @@ describe('line_chart_v2/lib/worker_chart test', () => {
});

onDrawEndSpy = jasmine.createSpy();
onContextLostSpy = jasmine.createSpy();
chart = new WorkerChart({
type: RendererType.WEBGL,
devicePixelRatio: 1,
callbacks: {onDrawEnd: onDrawEndSpy},
callbacks: {onDrawEnd: onDrawEndSpy, onContextLost: onContextLostSpy},
container: document.createElement('canvas'),
domDimension: {width: 100, height: 200},
useDarkMode: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,10 @@ export class LineChartComponent

const rendererType = this.getRendererType();
// Do not yet need to subscribe to the `onDrawEnd`.
const callbacks: ChartCallbacks = {onDrawEnd: () => {}};
const callbacks: ChartCallbacks = {
onDrawEnd: () => {},
onContextLost: () => {},
};
let params: ChartOptions | null = null;

this.readAndUpdateDomDimensions();
Expand Down

0 comments on commit c2ececa

Please sign in to comment.