|
|
|
@ -8,16 +8,16 @@ type SKGLViewInfo = { |
|
|
|
depth: number; |
|
|
|
} |
|
|
|
|
|
|
|
type SKHtmlCanvasElement = { |
|
|
|
SKHtmlCanvas: Canvas | undefined |
|
|
|
type CanvasElement = { |
|
|
|
Canvas: Canvas | undefined |
|
|
|
} & HTMLCanvasElement |
|
|
|
|
|
|
|
export class Canvas { |
|
|
|
static elements: Map<string, HTMLCanvasElement>; |
|
|
|
|
|
|
|
//htmlCanvas: HTMLCanvasElement;
|
|
|
|
htmlCanvas: HTMLCanvasElement; |
|
|
|
glInfo?: SKGLViewInfo; |
|
|
|
//renderFrameCallback: DotNet.DotNetObject;
|
|
|
|
renderFrameCallback: () => void; |
|
|
|
renderLoopEnabled: boolean = false; |
|
|
|
renderLoopRequest: number = 0; |
|
|
|
newWidth?: number; |
|
|
|
@ -31,17 +31,17 @@ export class Canvas { |
|
|
|
return canvas; |
|
|
|
} |
|
|
|
|
|
|
|
public static initGL(element: HTMLCanvasElement, elementId: string): SKGLViewInfo | null { |
|
|
|
public static initGL(element: HTMLCanvasElement, elementId: string, renderFrameCallback: () => void): SKGLViewInfo | null { |
|
|
|
console.log("inside initGL"); |
|
|
|
var view = Canvas.init(true, element, elementId); |
|
|
|
var view = Canvas.init(true, element, elementId, renderFrameCallback); |
|
|
|
if (!view || !view.glInfo) |
|
|
|
return null; |
|
|
|
|
|
|
|
return view.glInfo; |
|
|
|
} |
|
|
|
|
|
|
|
static init(useGL: boolean, element: HTMLCanvasElement, elementId: string): Canvas | null { |
|
|
|
var htmlCanvas = element as SKHtmlCanvasElement; |
|
|
|
static init(useGL: boolean, element: HTMLCanvasElement, elementId: string, renderFrameCallback: () => void): Canvas | null { |
|
|
|
var htmlCanvas = element as CanvasElement; |
|
|
|
if (!htmlCanvas) { |
|
|
|
console.error(`No canvas element was provided.`); |
|
|
|
return null; |
|
|
|
@ -51,17 +51,16 @@ export class Canvas { |
|
|
|
Canvas.elements = new Map<string, HTMLCanvasElement>(); |
|
|
|
Canvas.elements.set(elementId, element); |
|
|
|
|
|
|
|
const view = new Canvas(useGL, element); |
|
|
|
const view = new Canvas(useGL, element, renderFrameCallback); |
|
|
|
|
|
|
|
htmlCanvas.SKHtmlCanvas = view; |
|
|
|
htmlCanvas.Canvas = view; |
|
|
|
|
|
|
|
return view; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public constructor(useGL: boolean, element: HTMLCanvasElement) { |
|
|
|
//this.htmlCanvas = element;
|
|
|
|
//this.renderFrameCallback = callback;
|
|
|
|
public constructor(useGL: boolean, element: HTMLCanvasElement, renderFrameCallback: () => void) { |
|
|
|
this.htmlCanvas = element; |
|
|
|
this.renderFrameCallback = renderFrameCallback; |
|
|
|
|
|
|
|
if (useGL) { |
|
|
|
const ctx = Canvas.createWebGLContext(element); |
|
|
|
@ -79,6 +78,7 @@ export class Canvas { |
|
|
|
|
|
|
|
// read values
|
|
|
|
const fbo = GLctx.getParameter(GLctx.FRAMEBUFFER_BINDING); |
|
|
|
|
|
|
|
this.glInfo = { |
|
|
|
context: ctx, |
|
|
|
fboId: fbo ? fbo.id : 0, |
|
|
|
@ -89,6 +89,88 @@ export class Canvas { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public setEnableRenderLoop(enable: boolean) { |
|
|
|
this.renderLoopEnabled = enable; |
|
|
|
|
|
|
|
// either start the new frame or cancel the existing one
|
|
|
|
if (enable) { |
|
|
|
//console.info(`Enabling render loop with callback ${this.renderFrameCallback._id}...`);
|
|
|
|
this.requestAnimationFrame(); |
|
|
|
} else if (this.renderLoopRequest !== 0) { |
|
|
|
window.cancelAnimationFrame(this.renderLoopRequest); |
|
|
|
this.renderLoopRequest = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public requestAnimationFrame(renderLoop?: boolean) { |
|
|
|
// optionally update the render loop
|
|
|
|
if (renderLoop !== undefined && this.renderLoopEnabled !== renderLoop) |
|
|
|
this.setEnableRenderLoop(renderLoop); |
|
|
|
|
|
|
|
// skip because we have a render loop
|
|
|
|
if (this.renderLoopRequest !== 0) |
|
|
|
return; |
|
|
|
|
|
|
|
// add the draw to the next frame
|
|
|
|
this.renderLoopRequest = window.requestAnimationFrame(() => { |
|
|
|
if (this.glInfo) { |
|
|
|
var GL = (globalThis as any).AvaloniaGL; |
|
|
|
// make current
|
|
|
|
GL.makeContextCurrent(this.glInfo.context); |
|
|
|
} |
|
|
|
|
|
|
|
if (this.htmlCanvas.width != this.newWidth) { |
|
|
|
this.htmlCanvas.width = this.newWidth || 0; |
|
|
|
} |
|
|
|
|
|
|
|
if (this.htmlCanvas.height != this.newHeight) { |
|
|
|
this.htmlCanvas.height = this.newHeight || 0; |
|
|
|
} |
|
|
|
|
|
|
|
this.renderFrameCallback(); |
|
|
|
this.renderLoopRequest = 0; |
|
|
|
|
|
|
|
// we may want to draw the next frame
|
|
|
|
if (this.renderLoopEnabled) |
|
|
|
this.requestAnimationFrame(); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
public setCanvasSize(width: number, height: number) { |
|
|
|
this.newWidth = width; |
|
|
|
this.newHeight = height; |
|
|
|
|
|
|
|
if (this.htmlCanvas.width != this.newWidth) { |
|
|
|
this.htmlCanvas.width = this.newWidth; |
|
|
|
} |
|
|
|
|
|
|
|
if (this.htmlCanvas.height != this.newHeight) { |
|
|
|
this.htmlCanvas.height = this.newHeight; |
|
|
|
} |
|
|
|
|
|
|
|
if (this.glInfo) { |
|
|
|
var GL = (globalThis as any).AvaloniaGL; |
|
|
|
// make current
|
|
|
|
GL.makeContextCurrent(this.glInfo.context); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public static setCanvasSize(element: HTMLCanvasElement, width: number, height: number) { |
|
|
|
const htmlCanvas = element as CanvasElement; |
|
|
|
if (!htmlCanvas || !htmlCanvas.Canvas) |
|
|
|
return; |
|
|
|
|
|
|
|
htmlCanvas.Canvas.setCanvasSize(width, height); |
|
|
|
} |
|
|
|
|
|
|
|
public static requestAnimationFrame(element: HTMLCanvasElement, renderLoop?: boolean) { |
|
|
|
const htmlCanvas = element as CanvasElement; |
|
|
|
if (!htmlCanvas || !htmlCanvas.Canvas) |
|
|
|
return; |
|
|
|
|
|
|
|
htmlCanvas.Canvas.requestAnimationFrame(renderLoop); |
|
|
|
} |
|
|
|
|
|
|
|
static createWebGLContext(htmlCanvas: HTMLCanvasElement): WebGLRenderingContext | WebGL2RenderingContext { |
|
|
|
const contextAttributes = { |
|
|
|
alpha: 1, |
|
|
|
@ -109,6 +191,7 @@ export class Canvas { |
|
|
|
var GL = (globalThis as any).AvaloniaGL; |
|
|
|
|
|
|
|
let ctx: WebGLRenderingContext = GL.createContext(htmlCanvas, contextAttributes); |
|
|
|
|
|
|
|
if (!ctx && contextAttributes.majorVersion > 1) { |
|
|
|
console.warn('Falling back to WebGL 1.0'); |
|
|
|
contextAttributes.majorVersion = 1; |
|
|
|
|