Skip to content

Commit 235b675

Browse files
authored
Merge pull request #2659 from oddbookworm/window-create-context
Window(opengl=True) will now create an OpenGL context
2 parents be47901 + 7405ce6 commit 235b675

File tree

7 files changed

+212
-49
lines changed

7 files changed

+212
-49
lines changed

buildconfig/stubs/pygame/window.pyi

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class Window:
2828
def set_icon(self, icon: Surface, /) -> None: ...
2929
def get_surface(self) -> Surface: ...
3030
def flip(self) -> None: ...
31-
31+
3232
grab_mouse: bool
3333
grab_keyboard: bool
3434
title: str
@@ -64,5 +64,7 @@ class Window:
6464
def position(self) -> Tuple[int, int]: ...
6565
@position.setter
6666
def position(self, value: Union[int, Coordinate]) -> None: ...
67+
@property
68+
def opengl(self) -> bool: ...
6769
@classmethod
6870
def from_display_module(cls) -> Window: ...

docs/reST/ref/window.rst

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
1313
The Window class (formerly known as _sdl2.video.Window), is an experimental
1414
feature of pygame-ce. This class allows for programs to drive multiple
15-
Windows on-screen at once, something not possible with the
15+
Windows on-screen at once, something not possible with the
1616
:func:`pygame.display.set_mode` API. Not everything possible with
1717
:mod:`pygame.display` is possible yet in the Window API, but the new
1818
window class will continue to be developed, and we're excited to share
@@ -26,8 +26,7 @@
2626
the resolution (videomode change).
2727
:param bool fullscreen_desktop: Create a fullscreen window using the current
2828
desktop resolution.
29-
:param bool opengl: Create a window with support for an OpenGL context. You
30-
will still need to create an OpenGL context separately.
29+
:param bool opengl: Create a window with support for an OpenGL context.
3130
:param bool vulkan: Create a window with support for a Vulkan instance.
3231
:param bool hidden: Create a hidden window.
3332
:param bool borderless: Create a window without borders.
@@ -46,6 +45,7 @@
4645
others.
4746

4847
.. versionadded:: 2.4.0
48+
.. versionchanged:: 2.5.0 when ``opengl`` is ``True``, the ``Window`` has an OpenGL context created by pygame
4949

5050

5151
.. attribute:: grab_mouse
@@ -63,19 +63,19 @@
6363
.. seealso:: :attr:`mouse_grabbed`
6464

6565
.. versionadded:: 2.4.0
66-
66+
6767
.. attribute:: grab_keyboard
6868

6969
| :sl:`Get or set the window's keyboard grab mode`
7070
| :sg:`grab_keyboard -> bool`
71-
72-
When this attribute is set to ``True``, the window will try to capture system
73-
keyboard shortcuts like ``Alt+Tab`` or the ``Meta/Super`` key.
71+
72+
When this attribute is set to ``True``, the window will try to capture system
73+
keyboard shortcuts like ``Alt+Tab`` or the ``Meta/Super`` key.
7474

7575
This attribute only set the "mode" of grab. The keyboard may be captured by
76-
another window depending on the window focus. To get if keyboard is currently
76+
another window depending on the window focus. To get if keyboard is currently
7777
captured by this window, please use :attr:`keyboard_grabbed`.
78-
78+
7979
Note that not all system keyboard shortcuts can be captured by applications
8080
(one example is ``Ctrl+Alt+Del`` on Windows).
8181

@@ -90,7 +90,7 @@
9090
.. seealso:: :attr:`keyboard_grabbed`
9191

9292
.. versionadded:: 2.4.0
93-
93+
9494
.. attribute:: mouse_grabbed
9595

9696
| :sl:`Get if the mouse cursor is confined to the window (**read-only**)`
@@ -99,15 +99,15 @@
9999
Get if the mouse cursor is currently grabbed and confined to the window.
100100

101101
Roughly equivalent to this expression:
102-
102+
103103
::
104104

105105
win.grab_mouse and (win is get_grabbed_window())
106-
106+
107107
.. seealso:: :attr:`grab_mouse`
108-
108+
109109
.. versionadded:: 2.4.0
110-
110+
111111
.. attribute:: keyboard_grabbed
112112

113113
| :sl:`Get if the keyboard shortcuts are captured by the window (**read-only**)`
@@ -116,15 +116,15 @@
116116
Get if the keyboard shortcuts are currently grabbed and captured by the window.
117117

118118
Roughly equivalent to this expression:
119-
119+
120120
::
121121

122122
win.grab_keyboard and (win is get_grabbed_window())
123-
123+
124124
This attribute requires SDL 2.0.16+.
125-
125+
126126
.. seealso:: :attr:`grab_keyboard`
127-
127+
128128
.. versionadded:: 2.4.0
129129

130130
.. attribute:: title
@@ -147,7 +147,7 @@
147147
Gets or sets whether the window is borderless.
148148

149149
.. note:: You can't change the border state of a fullscreen window.
150-
150+
151151
.. attribute:: always_on_top
152152

153153
| :sl:`Get or set whether the window is always on top`
@@ -163,7 +163,7 @@
163163

164164
| :sl:`Get the unique window ID (**read-only**)`
165165
| :sg:`id -> int`
166-
166+
167167
.. attribute:: mouse_rect
168168

169169
| :sl:`Get or set the mouse confinement rectangle of the window`
@@ -173,7 +173,7 @@
173173
cursor to the specified area of this window.
174174

175175
This attribute can be None, meaning that there is no mouse rect.
176-
176+
177177
Note that this does NOT grab the cursor, it only defines the area a
178178
cursor is restricted to when the window has mouse focus.
179179

@@ -183,7 +183,7 @@
183183

184184
| :sl:`Get or set the window size in pixels`
185185
| :sg:`size -> (int, int)`
186-
186+
187187
.. attribute:: minimum_size
188188

189189
| :sl:`Get or set the minimum size of the window's client area`
@@ -193,25 +193,25 @@
193193
was used to create the window and :func:`pygame.display.set_mode` was
194194
called with the ``SCALED`` flag, the initial value is the size used in
195195
that call.
196-
197-
Raises a ``ValueError`` if negative values are provided or
198-
if the width or height provided are greater than set
199-
maximum width or height respectively. Unless maximum size
196+
197+
Raises a ``ValueError`` if negative values are provided or
198+
if the width or height provided are greater than set
199+
maximum width or height respectively. Unless maximum size
200200
is ``(0, 0)`` (initial value).
201201

202202
.. seealso:: :attr:`maximum_size`.
203203

204204
.. versionadded:: 2.4.0
205-
205+
206206
.. attribute:: maximum_size
207207

208208
| :sl:`Get or set the maximum size of the window's client area`
209209
| :sg:`maximum_size -> (int, int)`
210210
211211
Initial value is ``(0, 0)``.
212212

213-
Raises a ``ValueError`` if negative values are provided or
214-
if the width or height provided are less than set minimum
213+
Raises a ``ValueError`` if negative values are provided or
214+
if the width or height provided are less than set minimum
215215
width or height respectively.
216216

217217
.. seealso:: :attr:`minimum_size`.
@@ -228,6 +228,15 @@
228228
| :sl:`Get or set the window opacity, between 0.0 (fully transparent) and 1.0 (fully opaque)`
229229
| :sg:`opacity -> float`
230230
231+
.. attribute:: opengl
232+
233+
| :sl:`Get if the window supports OpenGL`
234+
| :sg:`opengl -> bool`
235+
236+
``True`` if the ``Window`` has an OpenGL context associated with it, ``False`` otherwise
237+
238+
.. versionadded:: 2.5.0
239+
231240
.. classmethod:: from_display_module
232241

233242
| :sl:`Create a Window object using window data from display module`
@@ -256,22 +265,22 @@
256265
Similarly to the "display surface" returned by :mod:`pygame.display`,
257266
this surface will change size with the Window, and will become invalid
258267
after the Window's destruction.
259-
268+
260269
.. seealso:: :func:`flip`
261270

262271
.. versionadded:: 2.4.0
263-
272+
264273
.. method:: flip
265274

266275
| :sl:`Update the display surface to the window.`
267276
| :sg:`flip() -> None`
268277
269-
Update content from the display surface to the window. This is the Window
278+
Update pixel data from memory to be displayed in the window. This is the Window
270279
class equivalent of :func:`pygame.display.flip`.
271280

272-
This method allows software rendering (classic pygame rendering) on top
273-
of the Window API. This method should not be called when using hardware
274-
rendering (coming soon).
281+
With ``get_surface()`` this method allows software rendering (classic pygame rendering) flipping pixel data
282+
from an associated surface in memory to be displayed in the window. Alternatively, when this window has an
283+
associated OpenGL context, this method will instead perform a GL buffer swap to the window.
275284

276285
Here is a runnable example of using ``get_surface`` and ``flip``:
277286

@@ -355,7 +364,7 @@
355364
| :sl:`Maximize the window`
356365
| :sg:`maximize() -> None`
357366
358-
.. method:: minimize
367+
.. method:: minimize
359368

360369
| :sl:`Minimize the window`
361370
| :sg:`maximize() -> None`
@@ -375,7 +384,7 @@
375384
| :sg:`set_modal_for(parent, /) -> None`
376385
377386
:param Window parent: The parent window.
378-
387+
379388
.. note:: This function is only supported on X11.
380389

381390
.. ## pygame.Window ##

examples/window_opengl.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
"""pygame.examples.window_opengl
2+
3+
Slightly modified version of the example at https://github.com/szabolcsdombi/zengl/blob/main/examples/pygame/hello_world.py
4+
Modified to use Window API instead of the display module
5+
6+
Posted here with permission from https://github.com/szabolcsdombi given in the PGC discord server
7+
"""
8+
9+
import pygame
10+
import zengl
11+
12+
window_size = (1280, 720)
13+
14+
pygame.init()
15+
window = pygame.Window(size=window_size, opengl=True)
16+
17+
ctx = zengl.context()
18+
19+
image = ctx.image(window_size, "rgba8unorm", samples=4)
20+
21+
pipeline = ctx.pipeline(
22+
vertex_shader="""
23+
#version 330 core
24+
25+
out vec3 v_color;
26+
27+
vec2 vertices[3] = vec2[](
28+
vec2(0.0, 0.8),
29+
vec2(-0.6, -0.8),
30+
vec2(0.6, -0.8)
31+
);
32+
33+
vec3 colors[3] = vec3[](
34+
vec3(1.0, 0.0, 0.0),
35+
vec3(0.0, 1.0, 0.0),
36+
vec3(0.0, 0.0, 1.0)
37+
);
38+
39+
void main() {
40+
gl_Position = vec4(vertices[gl_VertexID], 0.0, 1.0);
41+
v_color = colors[gl_VertexID];
42+
}
43+
""",
44+
fragment_shader="""
45+
#version 330 core
46+
47+
in vec3 v_color;
48+
49+
layout (location = 0) out vec4 out_color;
50+
51+
void main() {
52+
out_color = vec4(v_color, 1.0);
53+
out_color.rgb = pow(out_color.rgb, vec3(1.0 / 2.2));
54+
}
55+
""",
56+
framebuffer=[image],
57+
topology="triangles",
58+
vertex_count=3,
59+
)
60+
61+
clock = pygame.Clock()
62+
63+
while True:
64+
for event in pygame.event.get():
65+
if event.type == pygame.QUIT:
66+
pygame.quit()
67+
quit()
68+
69+
ctx.new_frame()
70+
image.clear()
71+
pipeline.render()
72+
image.blit()
73+
ctx.end_frame()
74+
75+
window.flip()
76+
clock.tick(60)

src_c/doc/window_doc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define DOC_WINDOW_MAXIMUMSIZE "maximum_size -> (int, int)\nGet or set the maximum size of the window's client area"
1616
#define DOC_WINDOW_POSITION "position -> (int, int) or WINDOWPOS_CENTERED or WINDOWPOS_UNDEFINED\nGet or set the window position in screen coordinates"
1717
#define DOC_WINDOW_OPACITY "opacity -> float\nGet or set the window opacity, between 0.0 (fully transparent) and 1.0 (fully opaque)"
18+
#define DOC_WINDOW_OPENGL "opengl -> bool\nGet if the window supports OpenGL"
1819
#define DOC_WINDOW_FROMDISPLAYMODULE "from_display_module() -> Window\nCreate a Window object using window data from display module"
1920
#define DOC_WINDOW_GETSURFACE "get_surface() -> Surface\nGet the window surface"
2021
#define DOC_WINDOW_FLIP "flip() -> None\nUpdate the display surface to the window."

src_c/include/_pygame.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,7 @@ typedef struct {
513513
PyObject_HEAD SDL_Window *_win;
514514
SDL_bool _is_borrowed;
515515
pgSurfaceObject *surf;
516+
SDL_GLContext context;
516517
} pgWindowObject;
517518

518519
#ifndef PYGAMEAPI_WINDOW_INTERNAL

0 commit comments

Comments
 (0)