remove canvas and context globals

This commit is contained in:
Will Scullin 2021-05-15 18:00:22 -07:00
parent 990de8815e
commit 0cff2414f8
No known key found for this signature in database
GPG Key ID: 26DCD1042C6638CD
3 changed files with 89 additions and 88 deletions

View File

@ -22,9 +22,6 @@ import {
pageNo
} from './videomodes';
const tmpCanvas = document.createElement('canvas');
const tmpContext = tmpCanvas.getContext('2d');
const dim = (c: Color): Color => {
return [
c[0] * 0.75 & 0xff,
@ -136,10 +133,7 @@ export class LoresPage2D implements LoresPage {
private readonly charset: rom,
private readonly e: boolean
) {
if (!tmpContext) {
throw new Error('No 2d context');
}
this.imageData = tmpContext.createImageData(560, 192);
this.imageData = this.vm.context.createImageData(560, 192);
for (let idx = 0; idx < 560 * 192 * 4; idx++) {
this.imageData.data[idx] = 0xff;
}
@ -290,7 +284,7 @@ export class LoresPage2D implements LoresPage {
offset += 546 * 4;
}
} else {
const colorMode = this.vm.mixedMode && !this.vm.textMode && !this.vm._monoMode;
const colorMode = this.vm.mixedMode && !this.vm.textMode && !this.vm.monoMode;
// var val0 = col > 0 ? _buffer[0][base - 1] : 0;
// var val2 = col < 39 ? _buffer[0][base + 1] : 0;
@ -330,7 +324,7 @@ export class LoresPage2D implements LoresPage {
} else {
if (this.vm._80colMode && !this.vm.an3State) {
let offset = (col * 14 + (bank ? 0 : 1) * 7 + row * 560 * 8) * 4;
if (this.vm._monoMode) {
if (this.vm.monoMode) {
for (let jdx = 0; jdx < 8; jdx++) {
let b = (jdx < 4) ? (val & 0x0f) : (val >> 4);
b |= (b << 4);
@ -363,7 +357,7 @@ export class LoresPage2D implements LoresPage {
} else if (bank === 0) {
let offset = (col * 14 + row * 560 * 8) * 4;
if (this.vm._monoMode) {
if (this.vm.monoMode) {
for (let jdx = 0; jdx < 8; jdx++) {
let b = (jdx < 4) ? (val & 0x0f) : (val >> 4);
b |= (b << 4);
@ -519,10 +513,7 @@ export class HiresPage2D implements HiresPage {
private vm: VideoModes,
private page: pageNo,
) {
if (!tmpContext) {
throw new Error('No 2d context');
}
this.imageData = tmpContext.createImageData(560, 192);
this.imageData = this.vm.context.createImageData(560, 192);
for (let idx = 0; idx < 560 * 192 * 4; idx++) {
this.imageData.data[idx] = 0xff;
}
@ -629,7 +620,7 @@ export class HiresPage2D implements HiresPage {
dy = rowa << 4 | rowb << 1;
let bz, b0, b1, b2, b3, b4, c, hb;
if (this.oneSixtyMode && !this.vm._monoMode) {
if (this.oneSixtyMode && !this.vm.monoMode) {
// 1 byte = two pixels, but 3:4 ratio
const c3 = val & 0xf;
const c4 = val >> 4;
@ -691,7 +682,7 @@ export class HiresPage2D implements HiresPage {
let offset = dx * 4 + dy * 280 * 4;
let monoColor = null;
if (this.vm._monoMode || this.monoDHRMode) {
if (this.vm.monoMode || this.monoDHRMode) {
monoColor = whiteCol;
}
@ -765,7 +756,7 @@ export class HiresPage2D implements HiresPage {
let offset = dx * 4 + dy * 280 * 4;
const monoColor = this.vm._monoMode ? whiteCol : null;
const monoColor = this.vm.monoMode ? whiteCol : null;
for (let idx = 0; idx < 9; idx++, offset += 8) {
val >>= 1;
@ -810,9 +801,9 @@ export class HiresPage2D implements HiresPage {
refresh() {
this.highColorHGRMode = !this.vm.an3State && this.vm.hiresMode && !this.vm._80colMode;
this.oneSixtyMode = this.vm._flag == 1 && this.vm.doubleHiresMode;
this.mixedDHRMode = this.vm._flag == 2 && this.vm.doubleHiresMode;
this.monoDHRMode = this.vm._flag == 3 && this.vm.doubleHiresMode;
this.oneSixtyMode = this.vm.flag == 1 && this.vm.doubleHiresMode;
this.mixedDHRMode = this.vm.flag == 2 && this.vm.doubleHiresMode;
this.monoDHRMode = this.vm.flag == 3 && this.vm.doubleHiresMode;
let addr = 0x2000 * this.page;
this._refreshing = true;
@ -863,7 +854,8 @@ export class HiresPage2D implements HiresPage {
export class VideoModes2D implements VideoModes {
private _grs: LoresPage[] = [];
private _hgrs: HiresPage[] = [];
private _context: CanvasRenderingContext2D | null;
private _screenContext: CanvasRenderingContext2D;
private _canvas: HTMLCanvasElement;
private _left: number;
private _top: number;
private _refreshFlag: boolean = true;
@ -879,16 +871,29 @@ export class VideoModes2D implements VideoModes {
an3State: boolean;
doubleHiresMode: boolean;
_flag = 0;
_monoMode = false;
flag = 0;
monoMode = false;
context: CanvasRenderingContext2D;
constructor(
private canvas: HTMLCanvasElement,
private screen: HTMLCanvasElement,
private e: boolean
) {
this._context = this.canvas.getContext('2d');
this._left = (this.canvas.width - 560) / 2;
this._top = (this.canvas.height - 384) / 2;
this._canvas = document.createElement('canvas');
const context = this._canvas.getContext('2d');
if (!context) {
throw new Error('No 2d context');
}
this.context = context;
const screenContext = this.screen.getContext('2d');
if (!screenContext) {
throw new Error('No 2d screen context');
}
this._screenContext = screenContext;
this._left = (this.screen.width - 560) / 2;
this._top = (this.screen.height - 384) / 2;
}
_refresh() {
@ -910,7 +915,7 @@ export class VideoModes2D implements VideoModes {
this._80colMode = false;
this.altCharMode = false;
this._flag = 0;
this.flag = 0;
this.an3State = true;
this._refresh();
@ -928,7 +933,7 @@ export class VideoModes2D implements VideoModes {
const old = this.textMode;
this.textMode = on;
if (on) {
this._flag = 0;
this.flag = 0;
}
if (old != on) {
this._refresh();
@ -960,7 +965,7 @@ export class VideoModes2D implements VideoModes {
const old = this.hiresMode;
this.hiresMode = on;
if (!on) {
this._flag = 0;
this.flag = 0;
}
if (old != on) {
@ -975,7 +980,7 @@ export class VideoModes2D implements VideoModes {
this.an3State = on;
if (on) {
this._flag = ((this._flag << 1) | (this._80colMode ? 0x0 : 0x1)) & 0x3;
this.flag = ((this.flag << 1) | (this._80colMode ? 0x0 : 0x1)) & 0x3;
}
if (old != on) {
@ -1032,25 +1037,25 @@ export class VideoModes2D implements VideoModes {
}
buildScreen(mainData: ImageData, mixData?: ImageData | null) {
if (!tmpContext) {
if (!this.context) {
throw new Error('No 2d context');
}
const { width, height } = { width: 560, height: 192 };
const { x, y } = this._80colMode ? { x: 0, y: 0 } : { x: 0, y: 0 };
tmpCanvas.width = width;
tmpCanvas.height = height;
tmpContext.fillStyle = 'rgba(0,0,0,1)';
tmpContext.fillRect(0, 0, width, height);
this._canvas.width = width;
this._canvas.height = height;
this.context.fillStyle = 'rgba(0,0,0,1)';
this.context.fillRect(0, 0, width, height);
if (mixData) {
tmpContext.putImageData(mainData, x, y, 0, 0, 560, 160);
tmpContext.putImageData(mixData, x, y, 0, 160, 560, 32);
this.context.putImageData(mainData, x, y, 0, 0, 560, 160);
this.context.putImageData(mixData, x, y, 0, 160, 560, 32);
} else {
tmpContext.putImageData(mainData, x, y);
this.context.putImageData(mainData, x, y);
}
return tmpCanvas;
return this._canvas;
}
updateImage(
@ -1059,14 +1064,11 @@ export class VideoModes2D implements VideoModes {
mixData?: ImageData | null,
mixDirty?: Region | null
) {
if (!this._context) {
throw new Error('No 2D context');
}
let blitted = false;
if (mainDirty.bottom !== -1 || (mixDirty && mixDirty.bottom !== -1)) {
const imageData = this.buildScreen(mainData, mixData);
this._context.drawImage(
this._screenContext.drawImage(
imageData,
0, 0, 560, 192,
this._left, this._top, 560, 384
@ -1121,7 +1123,7 @@ export class VideoModes2D implements VideoModes {
_80colMode: this._80colMode,
altCharMode: this.altCharMode,
an3State: this.an3State,
_flag: this._flag
flag: this.flag
};
}
@ -1133,7 +1135,7 @@ export class VideoModes2D implements VideoModes {
this._80colMode = state._80colMode;
this.altCharMode = state.altCharMode;
this.an3State = state.an3State;
this._flag = state._flag;
this.flag = state.flag;
this._grs[0].setState(state.grs[0]);
this._grs[1].setState(state.grs[1]);
@ -1144,17 +1146,17 @@ export class VideoModes2D implements VideoModes {
mono(on: boolean) {
if (on) {
this.canvas.classList.add('mono');
this.screen.classList.add('mono');
} else {
this.canvas.classList.remove('mono');
this.screen.classList.remove('mono');
}
this._monoMode = on;
this.monoMode = on;
this._refresh();
}
scanlines(on: boolean) {
// Can't apply scanline filter to canvas
const parent = this.canvas.parentElement;
const parent = this.screen.parentElement;
if (parent) {
if (on) {
parent.classList.add('scanlines');

View File

@ -25,9 +25,6 @@ import {
pageNo
} from './videomodes';
const tmpCanvas = document.createElement('canvas');
const tmpContext = tmpCanvas.getContext('2d');
// Color constants
const whiteCol: Color = [255, 255, 255];
const blackCol: Color = [0, 0, 0];
@ -63,10 +60,7 @@ export class LoresPageGL implements LoresPage {
private readonly charset: rom,
private readonly e: boolean
) {
if (!tmpContext) {
throw new Error('No 2d context');
}
this.imageData = tmpContext.createImageData(560, 192);
this.imageData = this.vm.context.createImageData(560, 192);
for (let idx = 0; idx < 560 * 192 * 4; idx++) {
this.imageData.data[idx] = 0xff;
}
@ -382,10 +376,7 @@ export class HiresPageGL implements HiresPage {
private vm: VideoModes,
private page: pageNo,
) {
if (!tmpContext) {
throw new Error('No 2d context');
}
this.imageData = tmpContext.createImageData(560, 192);
this.imageData = this.vm.context.createImageData(560, 192);
for (let idx = 0; idx < 560 * 192 * 4; idx++) {
this.imageData.data[idx] = 0xff;
}
@ -574,6 +565,7 @@ export class VideoModesGL implements VideoModes {
private _displayConfig: screenEmu.DisplayConfiguration;
private _scanlines: boolean = false;
private _refreshFlag: boolean = true;
private _canvas: HTMLCanvasElement;
public ready: Promise<void>
@ -586,13 +578,22 @@ export class VideoModesGL implements VideoModes {
an3State: boolean;
doubleHiresMode: boolean;
_flag = 0;
_monoMode: boolean = false;
flag = 0;
monoMode: boolean = false;
context: CanvasRenderingContext2D;
constructor(
private canvas: HTMLCanvasElement,
private e: boolean) {
this._sv = new screenEmu.ScreenView(this.canvas);
private screen: HTMLCanvasElement,
private e: boolean
) {
this._canvas = document.createElement('canvas');
const context = this._canvas.getContext('2d');
if (!context) {
throw new Error('no 2d context');
}
this.context = context;
this._sv = new screenEmu.ScreenView(this.screen);
this.ready = this.init();
}
@ -606,7 +607,7 @@ export class VideoModesGL implements VideoModes {
private defaultMonitor(): screenEmu.DisplayConfiguration {
const config = new screenEmu.DisplayConfiguration();
config.displayResolution = new screenEmu.Size(this.canvas.width, this.canvas.height);
config.displayResolution = new screenEmu.Size(this.screen.width, this.screen.height);
config.displayScanlineLevel = 0.5;
config.videoWhiteOnly = true;
config.videoSaturation = 0.8;
@ -619,14 +620,14 @@ export class VideoModesGL implements VideoModes {
private monitorII(): screenEmu.DisplayConfiguration {
// Values taken from openemulator/libemulation/res/library/Monitors/Apple Monitor II.xml
const config = new screenEmu.DisplayConfiguration();
config.displayResolution = new screenEmu.Size(this.canvas.width, this.canvas.height);
config.displayResolution = new screenEmu.Size(this.screen.width, this.screen.height);
config.videoDecoder = 'CANVAS_MONOCHROME';
config.videoBrightness = 0.15;
config.videoContrast = 0.8;
config.videoSaturation = 1.45;
config.videoHue = 0.27;
config.videoCenter = new screenEmu.Point(0, 0);
config.videoSize = new screenEmu.Size(1.05, 1.05);
config.videoCenter = new screenEmu.Point(0.01, 0.02);
config.videoSize = new screenEmu.Size(1.25, 1.15);
config.videoBandwidth = 6000000;
config.displayBarrel = 0.1;
config.displayScanlineLevel = 0.5;
@ -641,7 +642,7 @@ export class VideoModesGL implements VideoModes {
this._refreshFlag = true;
if (this._displayConfig) {
this._displayConfig.videoWhiteOnly = this.textMode || this._monoMode;
this._displayConfig.videoWhiteOnly = this.textMode || this.monoMode;
this._displayConfig.displayScanlineLevel = this._scanlines ? 0.5 : 0;
this._sv.displayConfiguration = this._displayConfig;
}
@ -789,26 +790,22 @@ export class VideoModesGL implements VideoModes {
}
buildScreen(mainData: ImageData, mixData?: ImageData | null) {
if (!tmpContext) {
throw new Error('No 2d context');
}
const details = screenEmu.C.NTSC_DETAILS;
const { width, height } = details.imageSize;
const { x, y } = this._80colMode ? details.topLeft80Col : details.topLeft;
tmpCanvas.width = width;
tmpCanvas.height = height;
tmpContext.fillStyle = 'rgba(0,0,0,1)';
tmpContext.fillRect(0, 0, width, height);
this._canvas.width = width;
this._canvas.height = height;
this.context.fillStyle = 'rgba(0,0,0,1)';
this.context.fillRect(0, 0, width, height);
if (mixData) {
tmpContext.putImageData(mainData, x, y, 0, 0, 560, 160);
tmpContext.putImageData(mixData, x, y, 0, 160, 560, 32);
this.context.putImageData(mainData, x, y, 0, 0, 560, 160);
this.context.putImageData(mixData, x, y, 0, 160, 560, 32);
} else {
tmpContext.putImageData(mainData, x, y);
this.context.putImageData(mainData, x, y);
}
return tmpContext.getImageData(0, 0, width, height);
return this.context.getImageData(0, 0, width, height);
}
blit(altData?: ImageData) {
@ -856,7 +853,7 @@ export class VideoModesGL implements VideoModes {
_80colMode: this._80colMode,
altCharMode: this.altCharMode,
an3State: this.an3State,
_flag: 0
flag: 0
};
}
@ -877,7 +874,7 @@ export class VideoModesGL implements VideoModes {
}
mono(on: boolean) {
this._monoMode = on;
this.monoMode = on;
this._displayConfig = on ? this.monitorII() : this.defaultMonitor();
this._refresh();
}

View File

@ -24,7 +24,7 @@ export interface VideoModesState {
_80colMode: boolean,
altCharMode: boolean,
an3State: boolean,
_flag: number,
flag: number,
}
export interface VideoPage extends MemoryPages, Restorable<GraphicsState> {
@ -55,8 +55,10 @@ export interface VideoModes extends Restorable<VideoModesState> {
an3State: boolean
doubleHiresMode: boolean
_flag: number
_monoMode: boolean
flag: number
monoMode: boolean
context: CanvasRenderingContext2D;
page(pageNo: number): void