{"action":"opened","issue":{"url":"https://api.github.com/repos/mikebmcl/N3888_RefImpl/issues/31","repository_url":"https://api.github.com/repos/mikebmcl/N3888_RefImpl","labels_url":"https://api.github.com/repos/mikebmcl/N3888_RefImpl/issues/31/labels{/name}","comments_url":"https://api.github.com/repos/mikebmcl/N3888_RefImpl/issues/31/comments","events_url":"https://api.github.com/repos/mikebmcl/N3888_RefImpl/issues/31/events","html_url":"https://github.com/mikebmcl/N3888_RefImpl/issues/31","id":137107122,"number":31,"title":"Stateful drawing APIs considered harmful","user":{"login":"seanmiddleditch","id":1817473,"avatar_url":"https://avatars.githubusercontent.com/u/1817473?v=3","gravatar_id":"","url":"https://api.github.com/users/seanmiddleditch","html_url":"https://github.com/seanmiddleditch","followers_url":"https://api.github.com/users/seanmiddleditch/followers","following_url":"https://api.github.com/users/seanmiddleditch/following{/other_user}","gists_url":"https://api.github.com/users/seanmiddleditch/gists{/gist_id}","starred_url":"https://api.github.com/users/seanmiddleditch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seanmiddleditch/subscriptions","organizations_url":"https://api.github.com/users/seanmiddleditch/orgs","repos_url":"https://api.github.com/users/seanmiddleditch/repos","events_url":"https://api.github.com/users/seanmiddleditch/events{/privacy}","received_events_url":"https://api.github.com/users/seanmiddleditch/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2016-02-28T22:51:33Z","updated_at":"2016-02-28T22:51:33Z","closed_at":null,"body":"This proposal is copying the stateful surface interfaces found in 2D canvas libraries of yester-year. We've (re)learned a lot of lessons since then as an industry and now consider that kind of implicit state stack to be harmful.\r\n\r\nThe largest issue is that the implicit state strongly hampers composability. Consider this fragment:\r\n\r\n    surface s;\r\n    s.set_color(red);\r\n\r\n    some_function(s);\r\n    // wait, did I have to save()/restore() around that ?\r\n    // does it break if I don't ? does it perform poorly if I do ?\r\n\r\n    s.fill(rect);\r\n\r\nFunction composition is severely harmed as users now have to do extra work to track the state that `surface` is bundled with, i.e. they are tracking the tracking of the state. The users have to manually deal with implementation concerns of functions they call. If the user just plays it safe and calls `save`/`restore` around any such function then they can end up with degraded efficiency (assuming they never make a mistake and forget, which real users certainly will sometimes!).\r\n\r\nModern graphics APIs have all moved strongly away from implicit state. In the 3D space we've seen misguided OpenGL model superceded by stateless Vulkan, and before that saw its lunch eaten by DirectX's stateless model. On 2D, the under-performing Cairo library that this paper draw inspiration from has been superceded by [Skia](https://skia.org/user/api/) or by [Azure/Moz2D](https://wiki.mozilla.org/Platform/GFX/Moz2D#Stateful_vs_stateless).\r\n\r\nNote both of the linked APIs encode state as a separate object passed to the paint operations directly. There is no implicit state tracking in the API. A user function can only alter state if its interface explicitly takes the state as a non-const reference type, exactly as we would expect of a thoughtfully designed and mature API.\r\n\r\nI very highly recommend reading through the design rationale of Skia or Moz2D. Cairo and Direct2D are the wrong models to base a new drawing library upon, especially one that we might want forever embedded into the C++ standard library. Stateful interfaces are bad for code composability, bad for performance, and bad for modern low-level hardware APIs."}}