Just some insight of implementing this for OpenGL:
I had tried to hook wglSwapBuffers using EasyHook in C# to do both capture and fps display before. I believe OBS now also do the same thing in order to capture OpenGL games, just without the fps display part.
However, what I basically implemented is to display the fps counter using pre-OpenGL 3.1 default pipeline, and it breaks custom shaders. I would like to remind any developer to beware of this: the code need to be compatible with both pre-OpenGL 3.1 and post-OpenGL 3.1. Texture binding is also something that should be carefully handled.
By the way, if anyone need fps number texture, I have one which I will release to the Public Domain (which is pretty simple anyway):