I agree that a window and its renderer or a window and its display surface belong together as a single object. And I am looking at doing that now. It is just I am now running into the limitations of Python and Cython. Extension types only support single inheritance. To add full window support—title, hiding, resizing, brightness, and more—to both a Surface subclass and a Renderer subclass means duplicating all that window specific code for both subclass declarations. If Cython supported mixins (and I thought it could, but no such luck), it would be easy. It just seemed safer avoid code duplication with a Window class instead.
It's worth noting that switching the graphics context betweenI don't see anything in SDL 2 for binding contexts. Maybe SDL does that for you. I don't know. If there is a way to do this in the SDL api, it will get exposed in the Pygame API at some point. The OpenGL stuff will also be added at some point.
windows (to do hardware draws) isn't free, and simple code
(that e.g. draws a bunch of things on two windows, switching
every draw call for code clarity) might not run very well.
Perhaps the API should discourage this somehow, especially if
full HW drawing is encouraged.
Again I don't understand. Given a window, its renderer, and a
bunch of textures: render the textures to various locations on the
window, update (expose) the renderer, then repeat. How is this not
hardware drawing. What am I missing?
Mmm I realize I was not very clear. Let me try again: whenever you /transition/ from HW drawing in one window to HW drawing into another, the windowing system (SDL, SDL2, etc.) needs to internally call something like:
wglMakeCurrent(window,context); //(on Windows) 1: Set up a graphics context that will be shared by all windows created. Draw calls go to a per-window hardware buffer. Then display.flip() iterates through all extant windows, binds to the window, and draws the hardware buffer into it. This adds the overhead of a second pass, but would perform okay. (It is /critical/ that the graphics context be shared, or else draws will incur the cost of binds also and we're back to square 0. It's not hard to make graphics contexts shared, but IDK if/what SDL2 does.)
glXMakeCurrent(display,window,context); //(on X11)
//Other platforms similar
This call does a bunch of bureaucratic stuff, mainly to rebind the GPU's destination framebuffer onto the new window's HW surface. To the point, that call is actually fairly expensive, and if you did something in a revamped pygame like:
for i in range(100):
window1.draw(lines[i])
window2.draw(lines[i])
Then the windowing system needs to insert 199 calls to it.
There are two options that occur to me: