{"action":"created","issue":{"url":"https://api.github.com/repos/google/gxui/issues/49","labels_url":"https://api.github.com/repos/google/gxui/issues/49/labels{/name}","comments_url":"https://api.github.com/repos/google/gxui/issues/49/comments","events_url":"https://api.github.com/repos/google/gxui/issues/49/events","html_url":"https://github.com/google/gxui/issues/49","id":63381443,"number":49,"title":"Support wider set of platforms. Mobile? Web?","user":{"login":"shurcooL","id":1924134,"avatar_url":"https://avatars.githubusercontent.com/u/1924134?v=3","gravatar_id":"","url":"https://api.github.com/users/shurcooL","html_url":"https://github.com/shurcooL","followers_url":"https://api.github.com/users/shurcooL/followers","following_url":"https://api.github.com/users/shurcooL/following{/other_user}","gists_url":"https://api.github.com/users/shurcooL/gists{/gist_id}","starred_url":"https://api.github.com/users/shurcooL/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shurcooL/subscriptions","organizations_url":"https://api.github.com/users/shurcooL/orgs","repos_url":"https://api.github.com/users/shurcooL/repos","events_url":"https://api.github.com/users/shurcooL/events{/privacy}","received_events_url":"https://api.github.com/users/shurcooL/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":19,"created_at":"2015-03-21T09:26:50Z","updated_at":"2015-07-02T08:50:58Z","closed_at":"2015-06-19T13:57:35Z","body":"First off, thank you for creating this incredible Go library! I've recently discovered it and I'm a huge fan! I really like the approach of using OpenGL for platform-independent, high performance UI rendering, since it allows one to stay general and not to be constrained by each platform's UI toolkits. I've experimented with OpenGL UIs [here](https://github.com/shurcooL/Conception-go#screenshot).\r\n\r\n## Introduction\r\n\r\nNow, the description of this project says:\r\n\r\n> GXUI - A Go **cross platform** UI library.\r\n\r\nCurrently, it is cross platform in that it will run and look/behave the same on OS X, Linux and Windows. However, with relatively little work, it seems it could be expanded to support more platforms: mobile and perhaps even web.\r\n\r\nFirst, let me be a little imprecise and describe OpenGL APIs in this way:\r\n\r\n- OpenGL 3.2 Core - \"Largest\" OpenGL API available. Available on most desktop platforms (OS X, Linux, Windows). \r\n- OpenGL ES 2.0 - Roughly speaking, a subset of OpenGL API (with minor deviations). Available on most mobile platforms (iOS, Android).\r\n- WebGL 1.0 - Roughly speaking, a subset of OpenGL ES 2.0 (with minor deviations). Available in all major browsers (Chrome, Safari, Firefox, Opera, IE).\r\n\r\nOpenGL 3.2 Core API is currently used in `gxui` [1]. But with a few changes (outlined in considerations section), it's possible to reduce what it used so that it can mapped to WebGL API.\r\n\r\nI wanted to see what it would take to get `gxui` to run in browsers (and see how it'd perform), so I made a quick little prototype tonight in just a few hours. Some screenshots:\r\n\r\n![1](https://cloud.githubusercontent.com/assets/1924134/6764426/775736b0-cf6c-11e4-9a8c-75a0cd5740fd.png)\r\n\r\n![2](https://cloud.githubusercontent.com/assets/1924134/6764427/7765273e-cf6c-11e4-975e-01557c4e546f.png)\r\n\r\n![3](https://cloud.githubusercontent.com/assets/1924134/6764428/7769398c-cf6c-11e4-9863-40c0b96e2d47.png)\r\n\r\n## Demo\r\n\r\nHere's a demo you can try in your browser (no gzip compression on served assets, sorry):\r\n\r\nhttp://dmitri.shuralyov.com/projects/gxui-tree/index.html\r\n\r\n## Approaches\r\n\r\nThere are two different approaches to supporting additional platforms that I can see.\r\n\r\nFirst approach is to create additional drivers, similar to the existing `gl` one. This seems to be suggested in related issue #45.\r\n\r\nAnother approach, which is the one I've used so far, is a little different.\r\n\r\nSince the three OpenGL APIs are similar enough, it's possible to create a Go package that has a single OpenGL-like API, but using **build tags**, it can have three different **backend implementations** depending on what is available on the given platform:\r\n\r\n- OpenGL 2.1 or 3.2 Core, etc., backend on desktops.\r\n- OpenGL ES backend on mobile devices.\r\n- WebGL backend in browser.\r\n\r\nThe [`github.com/shurcooL/gogl`](https://github.com/shurcooL/gogl) package used in my quick prototype is an example of that. It only has OpenGL 2.1 and WebGL backend implementations (incomplete), but adding OpenGL ES one would be trivial since it's a superset of WebGL. It's a WIP package with unpolished API, but I think the general approach is solid and can be turned into a production ready package.\r\n\r\n## Considerations\r\n\r\nHere are some implementation details of the changes I needed to do to make `gxui` samples run in the browser.\r\n\r\n1. `glPolygonMode` is not available in WebGL (since its implementation is very inefficient; a shame because it's useful for debugging). I commented it out since it was just a debugging feature.\r\n\r\n2. Index buffers with `uint32` types were used. It seems my WebGL implementation (latest stable Chrome on OS X) did not support that type, so I dropped it down to `uint16` which worked well.\r\n\r\n3. My WebGL implementation seemed not to support `gl.UniformMatrix3fv` calls with transpose equal to `true`, so I had to transpose the matrix before calling the gl func. I'm guessing the WebGL implementation opts to support fewer choices for performance reasons. It'd be better to avoid needless conversions between one format to the other when rendering.\r\n\r\n4. WebGL fragment shaders require precision to be set, so I added this to all fragment shaders to allow them to compile under all OpenGL/WebGL versions:\r\n\r\n    ```glsl\r\n    #ifdef GL_ES\r\n    \tprecision lowp float;\r\n    #endif\r\n```\r\n\r\n5. Previous commits read the font directly from disk via `ioutil.ReadFile`. This can't work on all other platforms, so it's better to read from a virtual filesystem and each platform can provide that. It's no longer a problem since latest version embeds the font in code.\r\n\r\n6. My existing `gogl` package happens to use a higher level-style API (similar to `x/mobile/gl`) with types like `*Texture` instead of `uint32`, and it favors using `int` over `int32` or `uint32` the way the low-level C-style `github.com/go-gl/gl/...` packages do. This is a design decision that is orthogonal to all other API changes, but it required me to make some changes like:\r\n\r\n\t```diff\r\n\t-framebuffer uint32\r\n\t-texture     uint32\r\n\t+framebuffer *gogl.Framebuffer\r\n\t+texture     *gogl.Texture\r\n\t```\r\n\t\r\n\t```diff\r\n\t-gl.DeleteFramebuffers(1, &f.framebuffer)\r\n\t-gl.DeleteTextures(1, &f.texture)\r\n\t-f.framebuffer = 0\r\n\t-f.texture = 0\r\n\t+gl.DeleteFramebuffer(f.framebuffer)\r\n\t+gl.DeleteTexture(f.texture)\r\n\t+f.framebuffer = nil\r\n\t+f.texture = nil\r\n\t```\r\n\t\r\n\t```diff\r\n\t-gl.Viewport(0, 0, int32(fw), int32(fh))\r\n\t-gl.Scissor(0, 0, int32(fw), int32(fh))\r\n\t+gl.Viewport(0, 0, fw, fh)\r\n\t+gl.Scissor(0, 0, fw, fh)\r\n\t```\r\n\r\n7. Consts like `gl.TRIANGLE_STRIP` are not const on all platforms. For example, to get that value in a browser, you either need to create a WebGLContext first (which can't be done at const-time), or just hardcode the const value from spec. I went with the latter for now.\r\n\r\nYou can see the entire code change I made at https://github.com/shurcooL/gxui/commit/469940010c8be6abd4feb535ba14a8b4e707720d. Keep in mind it's a quick prototype to test what it would take, and not a fully finished and polished version.\r\n\r\nThe performance of the web version (with Go compiled to JavaScript via [GopherJS](https://github.com/gopherjs/gopherjs)) is not as good as the desktop version with native Go. I am seeing around 20 fps. This is the result I got after doing the minimum work required to get samples to run without any profiling or optimizations. I am sure the performance can be improved if time is spent on it.\r\n\r\n## Conclusion\r\n\r\nWith just a few changes (do not use transpose `true`, use `uint16` type for index buffers, etc.) it is possible to avoid using OpenGL-only features that are not available in OpenGL ES and WebGL. Doing that seems like a good idea as it enables `gxui` to be more cross platform.\r\n\r\nThis issue is to demonstrate what I've created. I'd love to hear feedback and thoughts. If you are interested, I'd love to help out with adding support for mobile and/or web and taking this prototype further.\r\n\r\n---\r\n\r\n[1] The imported package is `v3.2-core/gl`, so that's the API used, but since context version glfw hints are not set, it creates an OpenGL 2.1 context. Add this snippet after `gl.Init()` call to confirm:\r\n\r\n```Go\r\n{\r\n\tvar samples int32\r\n\tgl.GetIntegerv(gl.SAMPLES, &samples)\r\n\tfmt.Printf(\"OpenGL %s %s %s; %s; %v samples.\\n\", gl.GoStr(gl.GetString(gl.VENDOR)), gl.GoStr(gl.GetString(gl.RENDERER)), gl.GoStr(gl.GetString(gl.VERSION)),\r\n\t\tgl.GoStr(gl.GetString(gl.SHADING_LANGUAGE_VERSION)), samples)\r\n}\r\n```\r\n\r\nOn my Mac, I got `OpenGL ATI Technologies Inc. AMD Radeon HD 6770M OpenGL Engine 2.1 ATI-1.30.5; 1.20; 4 samples.`. OpenGL 2.1."},"comment":{"url":"https://api.github.com/repos/google/gxui/issues/comments/117962950","html_url":"https://github.com/google/gxui/issues/49#issuecomment-117962950","issue_url":"https://api.github.com/repos/google/gxui/issues/49","id":117962950,"user":{"login":"awoland","id":971289,"avatar_url":"https://avatars.githubusercontent.com/u/971289?v=3","gravatar_id":"","url":"https://api.github.com/users/awoland","html_url":"https://github.com/awoland","followers_url":"https://api.github.com/users/awoland/followers","following_url":"https://api.github.com/users/awoland/following{/other_user}","gists_url":"https://api.github.com/users/awoland/gists{/gist_id}","starred_url":"https://api.github.com/users/awoland/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/awoland/subscriptions","organizations_url":"https://api.github.com/users/awoland/orgs","repos_url":"https://api.github.com/users/awoland/repos","events_url":"https://api.github.com/users/awoland/events{/privacy}","received_events_url":"https://api.github.com/users/awoland/received_events","type":"User","site_admin":false},"created_at":"2015-07-02T08:50:58Z","updated_at":"2015-07-02T08:50:58Z","body":"gxui looks fine ..."}}