File: conftest.py

package info (click to toggle)
python-moderngl 5.12.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,700 kB
  • sloc: python: 15,758; cpp: 14,665; makefile: 14
file content (127 lines) | stat: -rw-r--r-- 3,188 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
"""
Global fixtures for moderngl tests.

We rely on Context.gc_mode = "auto" to clean up resources.
Mainly a global context is used it test, but some test needs a new context

* ctx_static: A global context that is reused for all tests
* ctx: Also a global context, but it is cleaned before and after each test
* ctx_new: A new context for each test

Context creation can be refined in _create_context if issues arise
"""
import pytest
import numpy as np
import moderngl
from glcontext import egl

VERSION_CODES = 430, 410, 330
_ctx = None
_fbo = None  # Fake framebuffer to avoid errors during transforms

@pytest.fixture(scope="session")
def ctx_static():
    """Session context"""
    return _get_context()


@pytest.fixture(scope="function")
def ctx():
    """
    Per function context.

    The same context is reused, but the context is cleaned before and after each test.
    """
    ctx = _get_context()
    error = ctx.error
    if error != "GL_NO_ERROR":
        raise RuntimeError("Context has error before use: {}".format(error))
    _clean_ctx(ctx)
    yield ctx
    error = ctx.error
    if error != "GL_NO_ERROR":
        raise RuntimeError("Context has error after use: {}".format(error))
    _clean_ctx(ctx)


@pytest.fixture(scope="function")
def ctx_new():
    """Returns a new context for each test"""
    ctx = _create_context()
    yield ctx
    ctx.release()


def _get_context():
    """Get the global test context"""
    global _ctx, _fbo
    if _ctx is None:
        _ctx = _create_context()
        _ctx.gc_mode = "auto"
        _fbo = _ctx.simple_framebuffer((2, 2))

    _ctx.__enter__()
    _fbo.use()
    return _ctx

def _create_context():
    """
    Create a new context.

    This is the only place context creation should happen.
    For now we just brute force context creation.
"""
    return moderngl.create_context(standalone=True, context=egl.create_context(glversion=330, mode="standalone"))

def _clean_ctx(ctx):
    """Clean the context"""
    # Reset the context
    ctx.blend_func = moderngl.DEFAULT_BLENDING
    ctx.blend_equation = moderngl.FUNC_ADD
    ctx.enable_only(moderngl.NOTHING)
    ctx.point_size = 1.0
    ctx.line_width = 1.0
    ctx.front_face = 'ccw'
    ctx.cull_face = 'back'
    ctx.wireframe = False
    ctx.provoking_vertex = moderngl.FIRST_VERTEX_CONVENTION
    ctx.polygon_offset = 0.0, 0.0    
    ctx.gc()


@pytest.fixture(scope="session")
def color_prog(ctx_static):
    """A simple program that renders a solid color."""
    return ctx_static.program(
        vertex_shader='''
            #version 330

            in vec2 in_vert;

            void main() {
                gl_Position = vec4(in_vert, 0.0, 1.0);
            }
        ''',
        fragment_shader='''
            #version 330

            out vec4 fragColor;
            uniform vec4 color;

            void main() {
                fragColor = color;
            }
        ''',
    )


@pytest.fixture(scope="session")
def ndc_quad(ctx_static):
    """Creates a buffer with an NDC quad."""
    quad = [
        -1.0,  1.0,
        -1.0, -1.0,
        1.0, 1.0,
        1.0, -1.0,
    ]
    return ctx_static.buffer(np.array(quad, dtype='f4'))