From 10fef2fe9a5e8ff3e08ea9b6c47ad9bceba6706c Mon Sep 17 00:00:00 2001 From: Andrey Sidorov Date: Mon, 10 Dec 2012 00:01:24 +1100 Subject: [PATCH] glx extension and glxRender-encoded commands --- lib/x11/ext/glx.js | 197 +++++++++++++++++++++++++++++++++++- lib/x11/ext/glxconstants.js | 51 ++++++++++ lib/x11/ext/glxrender.js | 132 ++++++++++++++++++++++++ 3 files changed, 379 insertions(+), 1 deletion(-) create mode 100644 lib/x11/ext/glxconstants.js create mode 100644 lib/x11/ext/glxrender.js diff --git a/lib/x11/ext/glx.js b/lib/x11/ext/glx.js index 277b553..bfe4df7 100644 --- a/lib/x11/ext/glx.js +++ b/lib/x11/ext/glx.js @@ -8,4 +8,199 @@ http://www.opengl.org/wiki/Tutorial:_OpenGL_3.0_Context_Creation_(GLX) -*/ \ No newline at end of file +*/ +var x11 = require('..'); +// TODO: move to templates +exports.requireExt = function(display, callback) +{ + var X = display.client; + X.QueryExtension('GLX', function(err, ext) { + var constants = require('./glxconstants'); + for (var i in constants) + ext[i] = constants[i]; + + if (!ext.present) + return callback(new Error('extension not available')); + + ext.QueryVersion = function(clientMaj, clientMin, callback) + { + X.seq_num++; + X.pack_stream.pack('CCSLL', [ext.majorOpcode, 7, 3, clientMaj, clientMin]); + X.replies[X.seq_num] = [ + function(buf, opt) { + var res = buf.unpack('LL'); + return res; + }, + callback + ]; + X.pack_stream.flush(); + } + + ext.QueryServerString = function(screen, name, callback) { + X.seq_num++; + X.pack_stream.pack('CCSLL', [ext.majorOpcode, 19, 3, screen, name]); + X.replies[X.seq_num] = [ + function(buf, opt) { + var len = buf.unpack('xxxxL')[0]; + return buf.toString().substring(24, 24+len*4); + }, + callback + ]; + X.pack_stream.flush(); + } + + ext.QueryExtensionsString = function(screen, callback) { + X.seq_num++; + X.pack_stream.pack('CCSL', [ext.majorOpcode, 18, 2, screen]); + X.replies[X.seq_num] = [ + function(buf, opt) { + var len = buf.unpack('xxxxL')[0]; + return buf.toString().substring(24, 24+len*4); + }, + callback + ]; + X.pack_stream.flush(); + } + + // see __glXInitializeVisualConfigFromTags in mesa/src/glx/glxext.c + // + ext.GetVisualConfigs = function(screen, callback) { + X.seq_num++; + X.pack_stream.pack('CCSL', [ext.majorOpcode, 14, 2, screen]); + X.replies[X.seq_num] = [ + function(buf, opt) { + var res = buf.unpack('LL'); + var numConfigs = res[0]; + var numProps = res[1]; + var configs = new Array(numConfigs); + var i,j; + for (i=0; i < numConfigs; ++i) { + var props = {}; //new Array(numProps); + var names = 'visualID visualType rgbMode redBits greenBits blueBits alphaBits accumRedBits accumGreen accumBlueBits accumAlphaBits doubleBufferMode stereoMode rgbBits depthBits stencilBits numAuxBuffers level'.split(' '); + for (var j=0; j < 18 && j < numProps; ++j) { + props[names[j]] = buf.unpack('L', 24+(i*numProps +j)*4)[0]; + } + // read tag + property + configs[i] = props; + } + + return configs; + }, + callback + ]; + X.pack_stream.flush(); + } + + ext.GetFBConfigs = function(screen, callback) { + X.seq_num++; + X.pack_stream.pack('CCSL', [ext.majorOpcode, 21, 2, screen]); + X.replies[X.seq_num] = [ + function(buf, opt) { + var res = buf.unpack('LL'); + var numConfigs = res[0]; + var numProps = res[1]; + var configs = new Array(numConfigs); + var i,j; + for (i=0; i < numConfigs; ++i) { + var props = new Array(numProps); + for (var j=0; j < numProps; ++j) { + props[j] = buf.unpack('LL', 24+(i*numProps +j)*8); + } + configs[i] = props; + } + return configs; + }, + callback + ]; + X.pack_stream.flush(); + } + + ext.CreateContext = function(ctx, visual, screen, shareListCtx, isDirect) + { + X.seq_num++; + X.pack_stream.pack('CCSLLLLCxxx', [ext.majorOpcode, 3, 6, ctx, visual, screen, shareListCtx, isDirect]); + X.pack_stream.flush(); + } + + ext.SwapBuffers = function(ctx, drawable) + { + X.seq_num++; + X.pack_stream.pack('CCSLL', [ext.majorOpcode, 11, 3, ctx, drawable]); + X.pack_stream.flush(); + } + + ext.NewList = function(ctx, list, mode) + { + X.seq_num++; + X.pack_stream.pack('CCSLLL', [ext.majorOpcode, 101, 4, ctx, list, mode]); + X.pack_stream.flush(); + } + + ext.EndList = function(ctx) + { + X.seq_num++; + X.pack_stream.pack('CCSL', [ext.majorOpcode, 102, 2, ctx]); + X.pack_stream.flush(); + } + + ext.GenLists = function(ctx, count, callback) + { + X.seq_num++; + X.pack_stream.pack('CCSLL', [ext.majorOpcode, 104, 3, ctx, count]); + X.replies[X.seq_num] = [ + function(buf, opt) { + return buf.unpack('L')[0]; + }, + callback + ]; + X.pack_stream.flush(); + } + + ext.MakeCurrent = function(drawable, ctx, oldctx, callback) + { + X.seq_num++; + X.pack_stream.pack('CCSLLL', [ext.majorOpcode, 5, 4, drawable, ctx, oldctx]); + X.replies[X.seq_num] = [ + function(buf, opt) { + return buf.unpack('L')[0]; + }, + callback + ]; + X.pack_stream.flush(); + } + + // glClearColor ( 0, 0.5, 1, 1 ); glClear ( GL_COLOR_BUFFER_BIT ); + // xtrace: render commands={command=ClearColor(0x0082) unknown=0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f;},{command=Clear(0x007f) mask=0x00004000 }; + // (context 0300 4004) (1400 8200 0000 803f 0000 003f 0000 0000 0000 803f) (0800 7f00 0040 0000) + + ext.Render = function(ctx, data) { + X.seq_num++; + var length = 0; + //console.log(data); + if (Buffer.isBuffer(data)) + length = 2+data.length/4; + else if (Array.isArray(data)) { + length = 2; + for (var i=0; i < data.length; ++i) + length += data[i].length/4; + } + //console.log('LENGTH: ', length); + X.pack_stream.pack('CCSL', [ext.majorOpcode, 1, length, ctx]); + if (Buffer.isBuffer(data)) + X.pack_stream.write_queue.push(data); + else if (Array.isArray(data)) + for (var i=0; i < data.length; ++i) + X.pack_stream.write_queue.push(data[i]); + else + throw new Error('invalid data, expected buffer or buffers array', data); + X.pack_stream.flush(); + } + + ext.renderPipeline = function() { + return require('./glxrender')(this); + } + + callback(ext); + }); +} + diff --git a/lib/x11/ext/glxconstants.js b/lib/x11/ext/glxconstants.js new file mode 100644 index 0000000..0e1698c --- /dev/null +++ b/lib/x11/ext/glxconstants.js @@ -0,0 +1,51 @@ +module.exports = { + // + LIGHT0: 0x4000, + + // glEnable + POSITION: 0x1203, + CULL_FACE: 0x0B44, + LIGHTING: 0x0B50, + DEPTH_TEST: 0x0B71, + NORMALIZE: 0x0BA1, + + // glShadeModel + FLAT: 0x1D00, + SMOOTH: 0x1D01, + + // + TRUE: 1, + FALSE: 0, + + // glBegin + POINTS: 0x0000, + LINES: 0x0001, + LINE_LOOP: 0x0002, + LINE_STRIP: 0x0003, + TRIANGLES: 0x0004, + TRIANGLES_STRIP: 0x0005, + TRIANGLES_FAN: 0x0006, + QUADS: 0x0007, + QUAD_STRIP: 0x0008, + POLYGON: 0x0009, + + // glClear + COLOR_BUFFER_BIT: 0x00004000, + DEPTH_BUFFER_BIT: 0x00000100, + + // glMatrixMode + PROJECTION: 0x1701, + MODELVIEW: 0x1700, + + // glMaterial + FRONT: 0x0404, + AMBIENT_AND_DIFFUSE: 0x1602, + + COMPILE: 0x1300, + + // glGetString + RENDERER: 0x1F01, + VERSION: 0x1F02, + VENDOR: 0x1F00, + EXTENSIONS: 0x1F03 +} diff --git a/lib/x11/ext/glxrender.js b/lib/x11/ext/glxrender.js new file mode 100644 index 0000000..8d6b033 --- /dev/null +++ b/lib/x11/ext/glxrender.js @@ -0,0 +1,132 @@ +// see http://cgit.freedesktop.org/mesa/mesa/tree/src/mapi/glapi/gen/gl_API.xml + +module.exports = function(GLX) { + buffers = []; + + function commandBuffer(opcode, len) { + var res = Buffer(len); + res.writeUInt16LE(len, 0); + res.writeUInt16LE(opcode, 2); + return res; + } + + function serialize0(opcode) { + buffers.push(commandBuffer(opcode, 4)); + } + + function serialize3fv(opcode, c1, c2, c3) { + var res = commandBuffer(opcode, 16); + res.writeFloatLE(c1, 4); + res.writeFloatLE(c2, 8); + res.writeFloatLE(c3, 12); + buffers.push(res); + } + + function serialize4fv(opcode, c1, c2, c3, c4) { + var res = commandBuffer(opcode, 20); + res.writeFloatLE(c1, 4); + res.writeFloatLE(c2, 8); + res.writeFloatLE(c3, 12); + res.writeFloatLE(c4, 16); + buffers.push(res); + } + + function serialize4i(opcode, c1, c2, c3, c4) { + var res = commandBuffer(opcode, 20); + res.writeInt32LE(c1, 4); + res.writeInt32LE(c2, 8); + res.writeInt32LE(c3, 12); + res.writeInt32LE(c4, 16); + buffers.push(res); + } + + function serialize6d(opcode, d1, d2, d3, d4, d5, d6) + { + var res = commandBuffer(opcode, 52); + res.writeDoubleLE(d1, 4); + res.writeDoubleLE(d2, 12); + res.writeDoubleLE(d3, 20); + res.writeDoubleLE(d4, 28); + res.writeDoubleLE(d5, 36); + res.writeDoubleLE(d6, 44); + buffers.push(res); + }; + + + function serialize1i(opcode, value) { + var res = commandBuffer(opcode, 8); + res.writeUInt32LE(value, 4); + buffers.push(res); + } + + return { + render: function(ctx) { + GLX.Render(ctx, buffers); + buffers = []; + }, + Begin: function(what) { + serialize1i(4, what); + }, + End: function() { + serialize0(23); + }, + Ortho: function(left, right, bottom, top, znear, zfar) { + serialize6d(182, left, right, bottom, top, znear, zfar); + }, + Frustum: function(left, right, bottom, top, znear, zfar) { + serialize6d(182, left, right, bottom, top, znear, zfar); + }, + PopMatrix: function() { + serialize0(183); + }, + PushMatrix: function() { + serialize0(184); + }, + LoadIdentity: function() { + serialize0(176); + }, + Rotatef: function(a, x, y, z) { + serialize4fv(186, a, x, y, z); + }, + CallList: function(list) { + serialize1i(1, list); + }, + Viewport: function(x, y, w, h) { + serialize4i(191, x, y, w, h); // TODO: x,y - signed, w,h - unsigned (currently all 4 unsigned) + }, + Vertex3f: function(x, y, z) { + serialize3fv(70, x, y, z); + }, + Color3f: function(r, g, b) { + serialize3fv(8, r, g, b); + }, + Color4f: function(r, g, b, a) { + serialize4fv(16, r, g, b, a); + }, + Scalef: function(x, y, z) { + serialize3fv(188, x, y, z); + }, + Translatef: function(x, y, z) { + serialize3fv(190, x, y, z); + }, + ClearColor: function(r, g, b, a) { + serialize4fv(0x82, r, g, b, a); + }, + MatrixMode: function(mode) { + serialize1i(179, mode); + }, + Enable: function(value) { + serialize1i(139, value); + }, + Lightfv: function(light, name, p1, p2, p3, p4) { + seralize2i4f(87, light, name, p1, p2, p3, p4); + }, + Clear: function(mask) { + serialize1i(0x7f, mask); + }, + ShadeModel: function(model) { + serialize1i(104, model); + }, + + }; +}