Spaces:
Running
Running
| function B3DAcceleratorPlugin() { | |
| "use strict"; | |
| var DEBUG = 0; // 0 = off, 1 = some, 2 = lots | |
| var DEBUG_WAIT = false; // wait after each frame | |
| var renderers = []; // list of all renderers | |
| var rendererId = 0; // unique id for each renderer | |
| var currentRenderer = null; // set by makeCurrent() | |
| var OpenGL = null; // set by setOpenGL() | |
| var GL = null; // set by setOpenGL() | |
| /* Renderer creation flags: | |
| B3D_SOFTWARE_RENDERER: Enable use of software renderers | |
| B3D_HARDWARE_RENDERER: Enable use of hardware renderers | |
| B3D_STENCIL_BUFFER: Request stencil buffer | |
| B3D_ANTIALIASING: Request antialiasing in the renderer. | |
| B3D_STEREO: Request stereo visual from the renderer | |
| B3D_SYNCVBL: Request VBL sync | |
| More flags may be added - if they are not supported by the platform | |
| code the creation primitive should fail. | |
| */ | |
| var B3D_SOFTWARE_RENDERER = 0x0001; | |
| var B3D_HARDWARE_RENDERER = 0x0002; | |
| var B3D_STENCIL_BUFFER = 0x0004; | |
| var B3D_ANTIALIASING = 0x0008; // ignored | |
| var B3D_STEREO = 0x0010; // ignored | |
| var B3D_SYNCVBL = 0x0020; // ignored | |
| return { | |
| getModuleName: function() { return 'B3DAcceleratorPlugin (SqueakJS)'; }, | |
| interpreterProxy: null, | |
| primHandler: null, | |
| setInterpreter: function(anInterpreter) { | |
| this.interpreterProxy = anInterpreter; | |
| this.vm = this.interpreterProxy.vm; | |
| this.primHandler = this.vm.primHandler; | |
| this.prevDCCallback = this.primHandler.display.changedCallback; | |
| this.primHandler.display.changedCallback = () => { | |
| if (this.prevDCCallback) this.prevDCCallback(); | |
| for (const renderer of renderers) { | |
| this.adjustCanvas(renderer); | |
| } | |
| }; | |
| return true; | |
| }, | |
| setOpenGL: function(OpenGLPlugin) { | |
| OpenGL = OpenGLPlugin; | |
| GL = OpenGLPlugin.GL; | |
| if (currentRenderer) OpenGL.makeCurrent(currentRenderer); | |
| }, | |
| makeCurrent(renderer) { | |
| if (currentRenderer !== renderer) { | |
| currentRenderer = renderer; | |
| if (OpenGL) OpenGL.makeCurrent(renderer); | |
| } | |
| if (renderer.webgl.isContextLost()) { | |
| if (!renderer.warning) { | |
| console.warn("B3DAccel: WebGL context lost"); | |
| var div = document.createElement("div"); | |
| div.style.position = "absolute"; | |
| div.style.left = renderer.canvas.offsetLeft + "px"; | |
| div.style.top = renderer.canvas.offsetTop + "px"; | |
| div.style.width = renderer.canvas.width + "px"; | |
| div.style.height = renderer.canvas.height + "px"; | |
| div.style.backgroundColor = "rgba(0,0,0,0.8)"; | |
| div.style.color = "white"; | |
| div.style.fontFamily = "sans-serif"; | |
| div.style.fontSize = "24px"; | |
| div.style.textAlign = "center"; | |
| div.style.lineHeight = renderer.canvas.height + "px"; | |
| div.style.pointerEvents = "none"; | |
| div.style.cursor = "normal"; | |
| div.innerHTML = "WebGL context lost"; | |
| document.body.appendChild(div); | |
| renderer.warning = div; | |
| } | |
| } | |
| }, | |
| currentFromStack: function(i) { | |
| var renderer = this.interpreterProxy.stackObjectValue(i); | |
| if (!renderer.webgl) return null; | |
| this.makeCurrent(renderer); | |
| return renderer; | |
| }, | |
| primitiveAllocateTexture: function(argCount) { | |
| if (argCount !== 4) return false; | |
| var h = this.interpreterProxy.stackIntegerValue(0); | |
| var w = this.interpreterProxy.stackIntegerValue(1); | |
| var d = this.interpreterProxy.stackIntegerValue(2); | |
| if (!this.currentFromStack(3)) return false; | |
| if (w & (w-1)) return false; /* not power of two */ | |
| if (h & (h-1)) return false; /* not power of two */ | |
| DEBUG > 0 && console.log("B3DAccel: primitiveAllocateTexture", w, h, d); | |
| var tex = [0]; | |
| OpenGL.glGenTextures(1, tex); | |
| var texture = tex[0]; | |
| OpenGL.glBindTexture(GL.TEXTURE_2D, texture); | |
| OpenGL.glTexParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR); | |
| OpenGL.glTexParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.LINEAR); | |
| OpenGL.glTexParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.REPEAT); | |
| OpenGL.glTexParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.REPEAT); | |
| OpenGL.glTexEnvi(GL.TEXTURE_ENV, GL.TEXTURE_ENV_MODE, GL.MODULATE); | |
| OpenGL.glTexImage2D(GL.TEXTURE_2D, 0, GL.RGBA, w, h, 0, GL.BGRA, GL.UNSIGNED_BYTE, null); | |
| return this.primHandler.popNandPushIfOK(argCount + 1, texture); | |
| }, | |
| primitiveSetVerboseLevel: function(argCount) { | |
| if (argCount !== 1) return false; | |
| var level = this.interpreterProxy.stackIntegerValue(0); | |
| DEBUG > 0 && console.log("B3DAccel: primitiveSetVerboseLevel", level); | |
| this.interpreterProxy.pop(argCount); | |
| return true; | |
| }, | |
| primitiveCompositeTexture: function(argCount) { | |
| if (argCount !== 7) return false; | |
| if (!this.currentFromStack(6)) return false; | |
| var texHandle = this.interpreterProxy.stackIntegerValue(5); | |
| var x = this.interpreterProxy.stackIntegerValue(4); | |
| var y = this.interpreterProxy.stackIntegerValue(3); | |
| var w = this.interpreterProxy.stackIntegerValue(2); | |
| var h = this.interpreterProxy.stackIntegerValue(1); | |
| var translucent = this.interpreterProxy.booleanValueOf(this.interpreterProxy.stackValue(0)); | |
| if (this.interpreterProxy.failed()) return false; | |
| DEBUG > 1 && console.log("B3DAccel: primitiveCompositeTexture", texHandle, x, y, w, h, translucent); | |
| var result = this.b3dxCompositeTexture(texHandle, x, y, w, h, translucent); | |
| if (!result) return false; | |
| this.interpreterProxy.pop(argCount); | |
| return true; | |
| }, | |
| primitiveCreateRendererFlags: function(argCount) { | |
| if (argCount !== 5) return false; | |
| var flags = this.interpreterProxy.stackIntegerValue(4); | |
| var x = this.interpreterProxy.stackIntegerValue(3); | |
| var y = this.interpreterProxy.stackIntegerValue(2); | |
| var w = this.interpreterProxy.stackIntegerValue(1); | |
| var h = this.interpreterProxy.stackIntegerValue(0); | |
| if (flags & ~(B3D_HARDWARE_RENDERER | B3D_SOFTWARE_RENDERER | B3D_STENCIL_BUFFER)) | |
| return false; | |
| DEBUG > 0 && console.log("B3DAccel: primitiveCreateRendererFlags", x, y, w, h, flags); | |
| // create WebGL canvas | |
| var canvas = document.createElement("canvas"); | |
| canvas.classList.add("b3daccel"); | |
| canvas.width = w; | |
| canvas.height = h; | |
| canvas.style.position = "absolute"; | |
| canvas.style.backgroundColor = "transparent"; | |
| canvas.style.pointerEvents = "none"; | |
| canvas.style.cursor = "normal"; | |
| var options = { depth: true, alpha: false, antialias: true }; | |
| if (flags & B3D_STENCIL_BUFFER) options.stencil = true; | |
| var webgl = canvas.getContext("webgl", options); | |
| if (!webgl) return false; | |
| // create renderer | |
| rendererId++; | |
| var renderer = this.primHandler.makeStString("WebGL#" + rendererId); | |
| renderers.push(renderer); | |
| renderer.rendererId = rendererId; | |
| renderer.canvas = canvas; | |
| renderer.webgl = webgl; | |
| // set viewport | |
| this.b3dxSetViewport(renderer, x, y, w, h); | |
| document.body.appendChild(canvas); | |
| // make renderer accessible to other plugins | |
| this.makeCurrent(renderer); | |
| DEBUG > 0 && console.log("B3DAccel: created renderer", rendererId); | |
| return this.primHandler.popNandPushIfOK(argCount + 1, renderer); | |
| }, | |
| primitiveDestroyRenderer: function(argCount) { | |
| if (argCount !== 1) return false; | |
| if (!this.currentFromStack(0)) return false; | |
| DEBUG > 0 && console.log("B3DAccel: primitiveDestroyRenderer", currentRenderer.rendererId); | |
| renderers = renderers.filter(r => r !== currentRenderer); | |
| if (OpenGL) OpenGL.destroyGL(currentRenderer); | |
| if (currentRenderer.warning) { | |
| currentRenderer.warning.remove(); | |
| currentRenderer.warning = null; | |
| } | |
| currentRenderer.canvas.remove(); | |
| currentRenderer.canvas = null; | |
| currentRenderer.webgl = null; | |
| currentRenderer = null; | |
| DEBUG > 0 && console.log("B3DAccel: destroyed renderer", rendererId); | |
| this.interpreterProxy.pop(argCount); | |
| return true; | |
| }, | |
| primitiveDestroyTexture: function(argCount) { | |
| if (argCount !== 2) return false; | |
| var texture = this.interpreterProxy.stackIntegerValue(0); | |
| if (!this.currentFromStack(1)) return false; | |
| DEBUG > 0 && console.log("B3DAccel: primitiveDestroyTexture", texture); | |
| OpenGL.glDeleteTextures(1, [texture]); | |
| this.interpreterProxy.pop(argCount); | |
| return true; | |
| }, | |
| primitiveFinishRenderer: function(argCount) { | |
| if (argCount !== 1) return false; | |
| if (!this.currentFromStack(0)) return false; | |
| DEBUG > 1 && console.log("B3DAccel: primitiveFinishRenderer", currentRenderer); | |
| OpenGL.glFinish(); | |
| this.interpreterProxy.pop(argCount); | |
| return true; | |
| }, | |
| primitiveFlushRenderer: function(argCount) { | |
| if (argCount !== 1) return false; | |
| if (!this.currentFromStack(0)) return false; | |
| DEBUG > 1 && console.log("B3DAccel: primitiveFlushRenderer", currentRenderer); | |
| OpenGL.glFlush(); | |
| this.interpreterProxy.pop(argCount); | |
| return true; | |
| }, | |
| primitiveGetRendererSurfaceHandle: function(argCount) { | |
| // this would allow BitBlt to draw directly into the renderer surface | |
| // but it was only ever implemented for Direct3D not OpenGL | |
| // so the image will use a texture overlay instead | |
| if (argCount !== 1) return false; | |
| if (!this.currentFromStack(0)) return false; | |
| DEBUG > 1 && console.log("B3DAccel: UNIMPLEMENTED primitiveGetRendererSurfaceHandle", currentRenderer); | |
| return false; | |
| }, | |
| primitiveGetIntProperty: function(argCount) { | |
| if (argCount !== 2) return false; | |
| var property = this.interpreterProxy.stackIntegerValue(0); | |
| if (!this.currentFromStack(1)) return false; | |
| DEBUG > 1 && console.log("B3DAccel: primitiveGetIntProperty", property); | |
| var value = this.b3dxGetIntProperty(currentRenderer, property); | |
| return this.primHandler.popNandPushIfOK(argCount + 1, value); | |
| }, | |
| primitiveGetRendererSurfaceWidth: function(argCount) { | |
| if (argCount !== 1) return false; | |
| if (!this.currentFromStack(0)) return false; | |
| var width = currentRenderer.canvas.width; | |
| DEBUG > 0 && console.log("B3DAccel: primitiveGetRendererSurfaceWidth", width); | |
| return this.primHandler.popNandPushIfOK(argCount + 1, width); | |
| }, | |
| primitiveGetRendererSurfaceHeight: function(argCount) { | |
| if (argCount !== 1) return false; | |
| if (!this.currentFromStack(0)) return false; | |
| var height = currentRenderer.canvas.height; | |
| DEBUG > 0 && console.log("B3DAccel: primitiveGetRendererSurfaceHeight", height); | |
| return this.primHandler.popNandPushIfOK(argCount + 1, height); | |
| }, | |
| primitiveGetRendererSurfaceDepth: function(argCount) { | |
| if (argCount !== 1) return false; | |
| if (!this.currentFromStack(0)) return false; | |
| var depth = 32; | |
| DEBUG > 0 && console.log("B3DAccel: primitiveGetRendererSurfaceDepth", depth); | |
| return this.primHandler.popNandPushIfOK(argCount + 1, depth); | |
| }, | |
| primitiveGetRendererColorMasks: function(argCount) { | |
| if (argCount !== 2) return false; | |
| var array = this.interpreterProxy.stackObjectValue(0); | |
| if (this.currentFromStack(1)) return false; | |
| if (array.pointersSize() !== 4) return false; | |
| var masks = [0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000]; | |
| for (var i = 0; i < 4; i++) { | |
| array.pointers[i] = this.interpreterProxy.positive32BitIntegerFor(masks[i]); | |
| } | |
| DEBUG > 0 && console.log("B3DAccel: primitiveGetRendererColorMasks", masks); | |
| this.interpreterProxy.pop(argCount); | |
| return true; | |
| }, | |
| primitiveSetBufferRect: function(argCount) { | |
| if (argCount !== 5) return false; | |
| if (!this.currentFromStack(4)) return false; | |
| var x = this.interpreterProxy.stackIntegerValue(3); | |
| var y = this.interpreterProxy.stackIntegerValue(2); | |
| var w = this.interpreterProxy.stackIntegerValue(1); | |
| var h = this.interpreterProxy.stackIntegerValue(0); | |
| DEBUG > 1 && console.log("B3DAccel: primitiveSetBufferRect", x, y, w, h); | |
| this.b3dxSetViewport(currentRenderer, x, y, w, h); | |
| this.interpreterProxy.pop(argCount); | |
| return true; | |
| }, | |
| primitiveSetViewport: function(argCount) { | |
| if (argCount !== 5) return false; | |
| if (!this.currentFromStack(4)) return false; | |
| var x = this.interpreterProxy.stackIntegerValue(3); | |
| var y = this.interpreterProxy.stackIntegerValue(2); | |
| var w = this.interpreterProxy.stackIntegerValue(1); | |
| var h = this.interpreterProxy.stackIntegerValue(0); | |
| DEBUG > 1 && console.log("B3DAccel: primitiveSetViewport", x, y, w, h); | |
| this.b3dxSetViewport(currentRenderer, x, y, w, h); | |
| this.interpreterProxy.pop(argCount); | |
| return true; | |
| }, | |
| primitiveSetTransform: function(argCount) { | |
| if (argCount !== 3) return false; | |
| if (!this.currentFromStack(2)) return false; | |
| var modelViewMatrix = this.stackMatrix(1); | |
| var projectionMatrix = this.stackMatrix(0); | |
| if (!modelViewMatrix || !projectionMatrix) return false; | |
| DEBUG > 0 && console.log("B3DAccel: primitiveSetTransform", projectionMatrix, modelViewMatrix); | |
| OpenGL.glMatrixMode(GL.PROJECTION); | |
| OpenGL.glLoadMatrixf(projectionMatrix); | |
| OpenGL.glMatrixMode(GL.MODELVIEW); | |
| OpenGL.glLoadMatrixf(modelViewMatrix); | |
| this.interpreterProxy.pop(argCount); | |
| return true; | |
| }, | |
| primitiveSetLights: function(argCount) { | |
| if (argCount !== 2) return false; | |
| if (!this.currentFromStack(1)) return false; | |
| var lightArray = this.interpreterProxy.stackObjectValue(0); | |
| if (this.interpreterProxy.failed()) return false; | |
| if (!this.b3dxDisableLights(currentRenderer)) return false; | |
| if (!lightArray) return false; | |
| DEBUG > 1 && console.log("B3DAccel: UNIMPLEMENTED primitiveSetLights " + lightArray); | |
| var lightCount = lightArray.pointersSize(); | |
| for (var i = 0; i < lightCount; i++) { | |
| var light = this.fetchLightSource(i, lightArray); | |
| if (!this.b3dxLoadLight(currentRenderer, i, light)) return false; | |
| } | |
| this.interpreterProxy.pop(argCount); | |
| return true; | |
| }, | |
| primitiveSetMaterial: function(argCount) { | |
| if (argCount !== 2) return false; | |
| if (!this.currentFromStack(1)) return false; | |
| var material = this.stackMaterialValue(0); | |
| DEBUG > 0 && console.log("B3DAccel: primitiveSetMaterial", renderer, material); | |
| if (!material) { | |
| OpenGL.glMaterialfv(GL.FRONT, GL.AMBIENT, [0.2, 0.2, 0.2, 1.0]); | |
| OpenGL.glMaterialfv(GL.FRONT, GL.DIFFUSE, [0.8, 0.8, 0.8, 1.0]); | |
| OpenGL.glMaterialfv(GL.FRONT, GL.SPECULAR, [0.0, 0.0, 0.0, 1.0]); | |
| OpenGL.glMaterialfv(GL.FRONT, GL.EMISSION, [0.0, 0.0, 0.0, 1.0]); | |
| OpenGL.glMaterialf(GL.FRONT, GL.SHININESS, 0.0); | |
| OpenGL.glDisable(GL.TEXTURE_2D); | |
| } else { | |
| // 0: ambient, 4: diffuse, 8: specular, 12: emission, 16: shininess | |
| this.vm.warnOnce("B3DAccel: primitiveSetMaterial not fully implemented"); | |
| DEBUG > 1 && console.log("B3DAccel: UNIMPLEMENTED primitiveSetMaterial", material); | |
| } | |
| this.interpreterProxy.pop(argCount); | |
| return true; | |
| }, | |
| primitiveSwapRendererBuffers: function(argCount) { | |
| if (argCount !== 1) return false; | |
| if (!this.currentFromStack(0)) return false; | |
| DEBUG > 1 && console.log("B3DAccel: primitiveSwapRendererBuffers", currentRenderer); | |
| // let browser display the rendered frame | |
| this.interpreterProxy.vm.breakNow(); | |
| // tell the spinner we have been rendering | |
| this.primHandler.display.lastTick = this.vm.lastTick; | |
| if (DEBUG_WAIT) debugger; // wait after each frame | |
| this.interpreterProxy.pop(argCount); | |
| return true; | |
| }, | |
| primitiveTextureDepth: function(argCount) { | |
| if (argCount !== 2) return false; | |
| if (!this.currentFromStack(1)) return false; | |
| var depth = 32; | |
| DEBUG > 0 && console.log("B3DAccel: primitiveTextureDepth", depth); | |
| return this.primHandler.popNandPushIfOK(argCount + 1, depth); | |
| }, | |
| primitiveTextureGetColorMasks: function(argCount) { | |
| if (argCount !== 3) return false; | |
| if (!this.currentFromStack(2)) return false; | |
| var texture = this.interpreterProxy.stackIntegerValue(1); | |
| var array = this.interpreterProxy.stackObjectValue(0); | |
| if (array.pointersSize() !== 4) return false; | |
| var masks = [0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000]; | |
| for (var i = 0; i < 4; i++) { | |
| array.pointers[i] = this.interpreterProxy.positive32BitIntegerFor(masks[i]); | |
| } | |
| DEBUG > 0 && console.log("B3DAccel: primitiveTextureGetColorMasks", texture, masks); | |
| this.interpreterProxy.pop(argCount); | |
| return true; | |
| }, | |
| primitiveTextureByteSex: function(argCount) { | |
| if (argCount !== 2) return false; | |
| if (!this.currentFromStack(1)) return false; | |
| // return > 0 if MSB, = 0 if LSB, | |
| var byteSex = 0; | |
| DEBUG > 0 && console.log("B3DAccel: primitiveTextureByteSex", byteSex); | |
| return this.primHandler.popNandPushIfOK(argCount + 1, byteSex); | |
| }, | |
| primitiveTextureSurfaceHandle: function(argCount) { | |
| /* GL textures are not directly accessible */ | |
| return false; | |
| }, | |
| primitiveTextureUpload: function(argCount) { | |
| if (argCount !== 3) return false; | |
| if (!this.currentFromStack(2)) return false; | |
| var texture = this.interpreterProxy.stackIntegerValue(1); | |
| var form = this.interpreterProxy.stackObjectValue(0); | |
| if (form.pointersSize() < 4) return false; | |
| var bits = form.pointers[Squeak.Form_bits].words; | |
| var w = form.pointers[Squeak.Form_width]; | |
| var h = form.pointers[Squeak.Form_height]; | |
| var d = form.pointers[Squeak.Form_depth]; | |
| var ppw = 32 / d; | |
| if (!bits || bits.length !== (w + ppw - 1) / ppw * h) return false; | |
| DEBUG > 1 && console.log("B3DAccel: primitiveTextureUpload", texture, w, h, d, bits); | |
| var result = this.b3dxUploadTexture(texture, w, h, d, bits); | |
| if (!result) return false; | |
| this.interpreterProxy.pop(argCount); | |
| return true; | |
| }, | |
| b3dxCompositeTexture: function(texture, x, y, w, h, translucent) { | |
| DEBUG > 1 && console.log("B3DAccel: b3dxCompositeTexture", texture, x, y, w, h, translucent); | |
| if (!OpenGL.glIsTexture(texture)) return false; | |
| OpenGL.glMatrixMode(GL.MODELVIEW); | |
| OpenGL.glPushMatrix(); | |
| OpenGL.glLoadIdentity(); | |
| OpenGL.glMatrixMode(GL.PROJECTION); | |
| OpenGL.glPushMatrix(); | |
| OpenGL.glLoadIdentity(); | |
| var width = currentRenderer.viewport.w; | |
| var height = currentRenderer.viewport.h; | |
| OpenGL.glViewport(0, 0, width, height); | |
| OpenGL.glScaled(2.0/width, -2.0/height, 1.0); | |
| OpenGL.glTranslated(width*-0.5, height*-0.5, 0.0); | |
| //We haven't implemented glPushAttrib and glPopAttrib yet | |
| //OpenGL.glPushAttrib(GL.ALL_ATTRIB_BITS); | |
| // OpenGL.glShadeModel(GL.FLAT); // not implemented | |
| OpenGL.glEnable(GL.TEXTURE_2D); | |
| // OpenGL.glDisable(GL.COLOR_MATERIAL); // not implemented | |
| // OpenGL.glDisable(GL.DITHER); // | |
| OpenGL.glDisable(GL.LIGHTING); | |
| OpenGL.glDisable(GL.DEPTH_TEST); | |
| OpenGL.glDisable(GL.BLEND); | |
| OpenGL.glDisable(GL.CULL_FACE); | |
| OpenGL.glDepthMask(GL.FALSE); | |
| OpenGL.glColor4d(1.0, 1.0, 1.0, 1.0); | |
| if (translucent) { | |
| OpenGL.glEnable(GL.BLEND); | |
| OpenGL.glBlendFunc(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA); | |
| } | |
| // subtract top and left position of canvas | |
| x -= currentRenderer.viewport.x; | |
| y -= currentRenderer.viewport.y; | |
| OpenGL.glBindTexture(GL.TEXTURE_2D, texture); | |
| OpenGL.glBegin(GL.QUADS); | |
| OpenGL.glTexCoord2d(0.0, 0.0); | |
| OpenGL.glVertex2i(x, y); | |
| OpenGL.glTexCoord2d(1.0, 0.0); | |
| OpenGL.glVertex2i(x+w, y); | |
| OpenGL.glTexCoord2d(1.0, 1.0); | |
| OpenGL.glVertex2i(x+w, y+h); | |
| OpenGL.glTexCoord2d(0.0, 1.0); | |
| OpenGL.glVertex2i(x, y+h); | |
| OpenGL.glEnd(); | |
| // instead of this ... | |
| // OpenGL.glPopAttrib(); | |
| // we do this: | |
| OpenGL.glDepthMask(GL.TRUE); | |
| OpenGL.glEnable(GL.DEPTH_TEST); | |
| OpenGL.glEnable(GL.CULL_FACE); | |
| OpenGL.glDisable(GL.BLEND); | |
| // OpenGL.glEnable(GL.COLOR_MATERIAL); // not implemented | |
| // OpenGL.glEnable(GL.DITHER); // not implemented | |
| OpenGL.glDisable(GL.TEXTURE_2D); | |
| // OpenGL.glShadeModel(GL.SMOOTH); // not implemented | |
| OpenGL.glPopMatrix(); | |
| OpenGL.glMatrixMode(GL.MODELVIEW); | |
| OpenGL.glPopMatrix(); | |
| return true; | |
| }, | |
| adjustCanvas: function(renderer) { | |
| var canvas = renderer.canvas; | |
| var sq = this.primHandler.display.css; | |
| var x = renderer.viewport.x; | |
| var y = renderer.viewport.y; | |
| var w = renderer.viewport.w; | |
| var h = renderer.viewport.h; | |
| canvas.width = w; | |
| canvas.height = h; | |
| canvas.style.left = (sq.left + x * sq.scale) + "px"; | |
| canvas.style.top = (sq.top + y * sq.scale) + "px"; | |
| canvas.style.width = (w * sq.scale) + "px"; | |
| canvas.style.height = (h * sq.scale) + "px"; | |
| var warning = renderer.warning; | |
| if (warning) { | |
| warning.style.left = (sq.left + x * sq.scale) + "px"; | |
| warning.style.top = (sq.top + y * sq.scale) + "px"; | |
| warning.style.width = (w * sq.scale) + "px"; | |
| warning.style.height = (h * sq.scale) + "px"; | |
| } | |
| }, | |
| b3dxSetViewport: function(renderer, x, y, w, h) { | |
| renderer.viewport = {x: x, y: y, w: w, h: h}; | |
| this.adjustCanvas(renderer); | |
| }, | |
| b3dxDisableLights: function(renderer) { | |
| OpenGL.glDisable(GL.LIGHTING); | |
| for (var i = 0; i < 8; i++) { | |
| OpenGL.glDisable(GL.LIGHT0 + i); | |
| } | |
| return true; | |
| }, | |
| b3dxLoadLight: function(renderer, index, light) { | |
| DEBUG > 0 && console.log("B3DAccel: b3dxLoadLight", renderer, index, light); | |
| return true; | |
| }, | |
| b3dxGetIntProperty: function(renderer, prop) { | |
| // switch (prop) { | |
| // case 1: /* backface culling */ | |
| // if (!glIsEnabled(GL_CULL_FACE)) return 0; | |
| // glGetIntegerv(GL_FRONT_FACE, & v); | |
| // if (v == GL_CW) return 1; | |
| // if (v == GL_CCW) return -1; | |
| // return 0; | |
| // case 2: /* polygon mode */ | |
| // glGetIntegerv(GL_POLYGON_MODE, & v); | |
| // ERROR_CHECK; | |
| // return v; | |
| // case 3: /* point size */ | |
| // glGetIntegerv(GL_POINT_SIZE, & v); | |
| // ERROR_CHECK; | |
| // return v; | |
| // case 4: /* line width */ | |
| // glGetIntegerv(GL_LINE_WIDTH, & v); | |
| // ERROR_CHECK; | |
| // return v; | |
| // case 5: /* blend enable */ | |
| // return glIsEnabled(GL_BLEND); | |
| // case 6: /* blend source factor */ | |
| // case 7: /* blend dest factor */ | |
| // if (prop == 6) | |
| // glGetIntegerv(GL_BLEND_SRC, & v); | |
| // else | |
| // glGetIntegerv(GL_BLEND_DST, & v); | |
| // ERROR_CHECK; | |
| // switch (v) { | |
| // case GL_ZERO: return 0; | |
| // case GL_ONE: return 1; | |
| // case GL_SRC_COLOR: return 2; | |
| // case GL_ONE_MINUS_SRC_COLOR: return 3; | |
| // case GL_DST_COLOR: return 4; | |
| // case GL_ONE_MINUS_DST_COLOR: return 5; | |
| // case GL_SRC_ALPHA: return 6; | |
| // case GL_ONE_MINUS_SRC_ALPHA: return 7; | |
| // case GL_DST_ALPHA: return 8; | |
| // case GL_ONE_MINUS_DST_ALPHA: return 9; | |
| // case GL_SRC_ALPHA_SATURATE: return 10; | |
| // default: return -1; | |
| // } | |
| // } | |
| return 0; | |
| }, | |
| b3dxUploadTexture: function(texture, w, h, d, bits) { | |
| if (!OpenGL.glIsTexture(texture)) return false; | |
| OpenGL.glBindTexture(GL.TEXTURE_2D, texture); | |
| OpenGL.glTexSubImage2D(GL.TEXTURE_2D, 0, 0, 0, w, h, GL.RGBA, GL.UNSIGNED_BYTE, bits.buffer); | |
| return true; | |
| }, | |
| fetchLightSource: function(index, lightArray) { | |
| var light = lightArray.pointers[index]; | |
| if (!light) return null; | |
| DEBUG > 0 && console.log("B3DAccel: fetchLightSource", index, light); | |
| return light; | |
| }, | |
| stackMatrix: function(stackIndex) { | |
| var m = this.interpreterProxy.stackObjectValue(stackIndex); | |
| if (!m.words || m.words.length !== 16) return null; | |
| return m.wordsAsFloat32Array(); | |
| }, | |
| stackMaterialValue: function(stackIndex) { | |
| var material = this.interpreterProxy.stackObjectValue(stackIndex); | |
| if (!material.words) return null; | |
| return material.wordsAsFloat32Array(); | |
| }, | |
| } | |
| } | |
| function registerB3DAcceleratorPlugin() { | |
| if (typeof Squeak === "object" && Squeak.registerExternalModule) { | |
| Squeak.registerExternalModule('B3DAcceleratorPlugin', B3DAcceleratorPlugin()); | |
| } else self.setTimeout(registerB3DAcceleratorPlugin, 100); | |
| }; | |
| registerB3DAcceleratorPlugin(); | |