Skip to content
This repository has been archived by the owner on Nov 19, 2023. It is now read-only.

"noOffscreen" mode #83

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
12 changes: 10 additions & 2 deletions src/context/RendererContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Renderer } from '@/graphics'
import { CanvasContext } from './CanvasContext'

interface RendererContextProviderProps {
noOffscreen?: boolean
children: React.ReactNode
}

Expand All @@ -11,21 +12,28 @@ const defaultValue = undefined
export const RendererContext = React.createContext<Renderer | undefined>(defaultValue)

export const RendererContextProvider: React.FC<RendererContextProviderProps> = ({
children
noOffscreen = false,
children,
}) => {
const canvasRef = React.useContext(CanvasContext)
const [renderer, setRenderer] = React.useState<Renderer>()

React.useEffect(() => {
const canvas = canvasRef.current as HTMLCanvasElement
const { width, height } = canvas

if (noOffscreen) {
console.info('"noOffscreen" mode activated: OffscreenCanvas API will not be used even if supported')
}

new Renderer(
canvas,
width,
height,
(r: Renderer) => setRenderer(r),
noOffscreen,
)
}, [canvasRef])
}, [canvasRef, noOffscreen])

return (
<RendererContext.Provider value={renderer}>
Expand Down
9 changes: 5 additions & 4 deletions src/graphics/Renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export class Renderer {
private canvas: HTMLCanvasElement
private width: number
private height: number
private offscreenSupported: boolean
private offscreenMode: boolean
private ctx?: CanvasRenderingContext2D
private offscreenCanvas?: OffscreenCanvas
private rendererWorker?: RendererWorker
Expand All @@ -22,19 +22,20 @@ export class Renderer {
width: number,
height: number,
onReady: (renderer: Renderer) => void,
noOffscreen: boolean = false,
) {
this.canvas = canvas
this.width = width
this.height = height
this.offscreenSupported = OffscreenCanvasFeature.isSupported()
this.offscreenMode = !noOffscreen && OffscreenCanvasFeature.isSupported()

this.init(onReady)
}

private async init(
onReady: (renderer: Renderer) => void,
) {
if (this.offscreenSupported) {
if (this.offscreenMode) {
this.offscreenCanvas = this.canvas.transferControlToOffscreen()
this.rendererWorker = await new Worker(new URL('./workers/renderer', import.meta.url))

Expand Down Expand Up @@ -69,7 +70,7 @@ export class Renderer {
throw new Error('Renderer is not ready yet')
}

if (!this.offscreenSupported) {
if (!this.offscreenMode) {
if (!this.ctx) {
throw new Error('Context wasn\'t not set')
}
Expand Down
7 changes: 6 additions & 1 deletion src/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import '../styles/globals.css'
import type { AppProps } from 'next/app'
import Head from 'next/head'
import { useRouter } from 'next/router'
import { RecoilRoot } from 'recoil'
import { APP_NAME } from '../constants'
import { CanvasContextProvider } from '../context/CanvasContext'
import { RendererContextProvider } from '@/context/RendererContext'

const App = ({ Component, pageProps }: AppProps) => {
const router = useRouter()

const noOffscreen = Boolean(router.query.noOffscreen)

return (
<RecoilRoot>
<CanvasContextProvider>
<RendererContextProvider>
<RendererContextProvider noOffscreen={noOffscreen}>
<Head>
<title>{APP_NAME}</title>
<meta name='viewport' content='minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, viewport-fit=cover' />
Expand Down