-
Notifications
You must be signed in to change notification settings - Fork 83
Description
任务
- 确认skyline页面时http server提供的
- 能否直接使用nodejs(win)调用模块?(不能,必须用nwjs的环境)
-
确认http server的port如何传输给skyline module - 整理渲染流程
- 开发SharedMemory模块
- 开发websocket服务端(Wine/Windows)
- 开发websocket客户端(Linux)
- Wine与Linux共享内存互访。(关键)
- 完善交互逻辑
- 优化交互速度
- worklet支持(https://github.com/software-mansion/react-native-reanimated)
- 动画支持(目前没报错,但是体验有问题)
说明
前言
前置信息:#88
Skyline在开发工具中是一个node module,结合SharedMemory使用。
通过进一步分析,发现在开发工具中,本质还是去使用webview加载页面:
分析
04-02 17:30
目前猜测,开发工具调用module后,module创建了一个http webserver;
展示页面访问http页面渲染,重新编译等操作是通过js层直接交互的。
04-02 20:50
使用Linux环境打开Skyline项目,相关地址有生成且默认页面与Windows环境一致;
然后,Linux才出现模块报错。
说明,此HTTP Server是开发者工具创建的;在此Server中,调用了Skyline等模块,与此前猜测不一致。
从此图可知 require 是在页面的 index.js 中执行的;
所以HTTP Server不动最好,对页面的 require 的行为进行代理。
04-02 22:36
初步分析得出的渲染逻辑:
- 创建共享内存区域A
- Canvas使用WebGL读取内存区域A渲染图像到模拟器区域(无限渲染)
- Skyline将源码渲染成图像写入内存区域A
- 用户操作界面,通过API通知Skyline
- Skyline执行对应操作生成新图像写入内存区域
04-03 17:50
根据渲染逻辑可以确定,SharedMemory模块用于处理共享,逻辑相对简单,先试着实现一个;
实现后,就可以移植到Linux。
- 在wine中启动skyline,启动rpc服务器;
- Linux端启动rpc客户端。
- wine与Linux共享内存互访。
(function(){
document.body.style.margin = 0
document.body.style.background = 'black'
const runtimePath = '${r}'
const libConfigMap = require(runtimePath)
const item = libConfigMap['sharedMemory']
if (item) {
const sharedMemory = require(item.path)
const canvas = document.createElement('canvas')
canvas.style.background = 'black'
canvas.width = ${i}
canvas.height = ${o}
const buffer = sharedMemory.getMemory('${c}')
const sharedBufferView = new Uint8Array(buffer)
sharedMemory.removeMemory('${c}')
document.body.appendChild(canvas)
const vs = `#version 100
attribute vec2 a_position;
attribute vec2 a_texcoord;
varying vec2 v_texcoord;
void main() {
gl_Position = vec4(a_position, 1.0, 1.0);
v_texcoord = a_texcoord;
}
`;
const fs = `#version 100
precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D u_texture;
void main() {
gl_FragColor = texture2D(u_texture, v_texcoord);
}
`;
const gl = canvas.getContext('webgl', { preserveDrawingBuffer: true })
const texture = gl.createTexture();
const program = gl.createProgram()
const texcoordBuffer = gl.createBuffer();
const positionBuffer = gl.createBuffer();
const vertexShader = gl.createShader(gl.VERTEX_SHADER)
gl.shaderSource(vertexShader, vs);
gl.compileShader(vertexShader);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
gl.shaderSource(fragmentShader, fs);
gl.compileShader(fragmentShader);
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
const positions = [
-1, -1,
-1, 1,
1, -1,
1, -1,
-1, 1,
1, 1,
];
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
const texcoords = [
0, 0,
0, 1,
1, 0,
1, 0,
0, 1,
1, 1,
];
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texcoords), gl.STATIC_DRAW);
if (sharedBufferView) {
const render = () => {
gl.viewport(0, 0, ${i}, ${o});
gl.scissor(0, 0, ${i}, ${o});
gl.useProgram(program);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, ${s}, ${a}, 0, gl.RGBA, gl.UNSIGNED_BYTE, sharedBufferView);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
const positionLoc = gl.getAttribLocation(program, "a_position");
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLoc);
const texcoordLoc = gl.getAttribLocation(program, "a_texcoord");
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
gl.vertexAttribPointer(texcoordLoc, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(texcoordLoc);
const textureLocation = gl.getUniformLocation(program, "u_texture");
gl.uniform1i(textureLocation, 0);
gl.drawArrays(gl.TRIANGLES, 0, 6);
if (render) {
requestAnimationFrame(render);
}
}
render()
}
}
})()垃圾模块,一调用createWindow就崩溃。
04-07 23:00
createWindow崩溃已解决;(new global.SkylineShell(window))
基础客户/服务端通信开发出初版。
用初版跑的时候,一调用notifyAppLaunch就一直崩溃😫
不知道是不是window, global引起的。。。
待测试,一开始就window = global看会不会崩溃。
04-08 10:00
加个500ms延迟,notifyAppLaunch不崩溃了。
新问题:
搜索报错关键字,找不到。。。怪
在奇怪得地方找到了:
04-08 16:00
拦截SkylineGlobal,有一些额外操作。
04-15 10:00
目前已经实现部分功能,能正常加载 address-book 示例。
支持基础交互。
worklet暂不支持。
04-22 10:00
debugger 发现一处写法有问题,导致 worklet 动画不生效。
04-22 16:00
审查元素时,发现有大量matches调用,导致响应异常的慢。
看起来是在比较类名,应该可以加本地缓存解决;但是,6是什么意思?

04-26 22:00
Wine -> sharedMemory(windows) -> shardMemory(linux) -> webview
共享内存工作正常,但是Wine似乎没有把图像数据写入内存区域。
04-30 14:00
抱着试试看的想法,在虚拟机跑了一下,竟然可以;看来是WSL的问题。
想法
在wine中启动一个skyline server(无UI),额外编写一个RPC服务器,在Linux层加入RPC客户端;
把“重新编译”这些操作通过RPC进行交互。
这个wine server可以跑在宿主或者docker环境中。
结语
wine最好是能用,效率不谈(
待验证。。。









