예제 #1
0
def api_ctx_ownership():
    ctx = ngl.Context()
    ctx2 = ngl.Context()
    ret = ctx.configure(offscreen=1, width=16, height=16, backend=_backend)
    assert ret == 0
    ret = ctx2.configure(offscreen=1, width=16, height=16, backend=_backend)
    assert ret == 0
    scene = _get_scene()
    assert ctx.set_scene(scene) == 0
    assert ctx.draw(0) == 0
    assert ctx2.set_scene(scene) != 0
    assert ctx2.draw(0) == 0
    del ctx
    del ctx2
예제 #2
0
def api_resize_fail():
    ctx = ngl.Context()
    ret = ctx.configure(offscreen=1, width=16, height=16, backend=_backend)
    assert ret == 0
    ret = ctx.resize(32, 32)
    assert ret != 0
    del ctx
예제 #3
0
def api_ctx_ownership():
    viewer = ngl.Context()
    viewer2 = ngl.Context()
    assert viewer.configure(offscreen=1, width=16, height=16,
                            backend=_backend) == 0
    assert viewer2.configure(offscreen=1,
                             width=16,
                             height=16,
                             backend=_backend) == 0
    scene = _get_scene()
    assert viewer.set_scene(scene) == 0
    assert viewer.draw(0) == 0
    assert viewer2.set_scene(scene) != 0
    assert viewer2.draw(0) == 0
    del viewer
    del viewer2
예제 #4
0
def api_text_live_change(width=320, height=240):
    import zlib

    ctx = ngl.Context()
    capture_buffer = bytearray(width * height * 4)
    ret = ctx.configure(offscreen=1, width=width, height=height, backend=_backend, capture_buffer=capture_buffer)
    assert ret == 0

    # An empty string forces the text node to deal with a pipeline with nul
    # attributes, this is what we exercise here, along with a varying up and
    # down number of characters
    text_strings = ["foo", "", "foobar", "world", "hello\nworld", "\n\n", "last"]

    # Exercise the diamond-form/prepare mechanism
    text_node = ngl.Text()
    assert ctx.set_scene(autogrid_simple([text_node] * 4)) == 0

    ctx.draw(0)
    last_crc = zlib.crc32(capture_buffer)
    for i, s in enumerate(text_strings, 1):
        text_node.set_text(s)
        ctx.draw(i)
        crc = zlib.crc32(capture_buffer)
        assert crc != last_crc
        last_crc = crc
예제 #5
0
def api_media_sharing_failure():
    ctx = ngl.Context()
    ret = ctx.configure(offscreen=1, width=16, height=16, backend=_backend)
    assert ret == 0
    m = ngl.Media("/dev/null")
    scene = ngl.Group(children=(ngl.Texture2D(data_src=m), ngl.Texture2D(data_src=m)))
    assert _ret_to_fourcc(ctx.set_scene(scene)) == "Eusg"  # Usage error
예제 #6
0
    def createFramebufferObject(self, size):
        fmt = QOpenGLFramebufferObjectFormat()
        fmt.setAttachment(QOpenGLFramebufferObject.CombinedDepthStencil)
        self._fbo = QOpenGLFramebufferObject(size, fmt)

        # Clear any previous OpenGL error. This workarounds an issue on macOS
        # where the current context contains errors (due to Qt OpenGL
        # implementation). These errors need to be cleared before calling the
        # node.gl API otherwise node.gl will in turn error out.
        gl_funcs = QOpenGLFunctions(QOpenGLContext.currentContext())
        gl_funcs.glGetError()

        if not self._context:
            self._context = ngl.Context()
            config_gl = ngl.ConfigGL(external=True,
                                     external_framebuffer=self._fbo.handle())
            self._context.configure(
                backend=ngl.BACKEND_OPENGL,
                width=self._fbo.width(),
                height=self._fbo.height(),
                backend_config=config_gl,
            )
        else:
            self._context.gl_wrap_framebuffer(self._fbo.handle())

        return self._fbo
예제 #7
0
def api_media_sharing_failure():
    import struct
    ctx = ngl.Context()
    assert ctx.configure(offscreen=1, width=16, height=16,
                         backend=_backend) == 0
    m = ngl.Media('/dev/null')
    scene = ngl.Group(children=(m, m))
    assert _ret_to_fourcc(ctx.set_scene(scene)) == 'Eusg'  # Usage error
예제 #8
0
 def _init_ctx(self, rendering_backend):
     if self._ctx:
         return
     self._ctx = ngl.Context()
     self._ctx.configure(backend=misc.get_backend(rendering_backend),
                         offscreen=1,
                         width=16,
                         height=16)
예제 #9
0
def api_hud(width=234, height=123):
    ctx = ngl.Context()
    ret = ctx.configure(offscreen=1, width=width, height=height, backend=_backend, hud=1)
    assert ret == 0
    scene = _get_scene()
    assert ctx.set_scene(scene) == 0
    for i in range(60 * 3):
        assert ctx.draw(i / 60.0) == 0
    del ctx
예제 #10
0
def api_reconfigure_fail():
    ctx = ngl.Context()
    assert ctx.configure(offscreen=1, width=16, height=16,
                         backend=_backend) == 0
    scene = _get_scene()
    assert ctx.set_scene(scene) == 0
    assert ctx.draw(0) == 0
    assert ctx.configure(offscreen=0, backend=_backend) != 0
    assert ctx.draw(1) != 0
    del ctx
예제 #11
0
def api_shader_init_fail(width=320, height=240):
    ctx = ngl.Context()
    ret = ctx.configure(offscreen=1, width=width, height=height, backend=_backend)
    assert ret == 0

    render = ngl.Render(ngl.Quad(), ngl.Program(vertex="<bug>", fragment="<bug>"))

    assert ctx.set_scene(render) != 0
    assert ctx.set_scene(render) != 0  # another try to make sure the state stays consistent
    assert ctx.draw(0) == 0
예제 #12
0
def api_capture_buffer_lifetime(width=1024, height=1024):
    capture_buffer = bytearray(width * height * 4)
    ctx = ngl.Context()
    ret = ctx.configure(offscreen=1, width=width, height=height, backend=_backend, capture_buffer=capture_buffer)
    assert ret == 0
    del capture_buffer
    scene = _get_scene()
    assert ctx.set_scene(scene) == 0
    assert ctx.draw(0) == 0
    del ctx
예제 #13
0
def api_reconfigure():
    viewer = ngl.Context()
    assert viewer.configure(offscreen=1, width=16, height=16,
                            backend=_backend) == 0
    scene = _get_scene()
    assert viewer.set_scene(scene) == 0
    assert viewer.draw(0) == 0
    assert viewer.configure(offscreen=1, width=16, height=16,
                            backend=_backend) == 0
    assert viewer.draw(1) == 0
    del viewer
예제 #14
0
def api_ctx_ownership_subgraph():
    for shared in (True, False):
        ctx = ngl.Context()
        ctx2 = ngl.Context()
        ret = ctx.configure(offscreen=1, width=16, height=16, backend=_backend)
        assert ret == 0
        ret = ctx2.configure(offscreen=1, width=16, height=16, backend=_backend)
        assert ret == 0
        quad = ngl.Quad()
        render1 = _get_scene(quad)
        if not shared:
            quad = ngl.Quad()
        render2 = _get_scene(quad)
        scene = ngl.Group([render1, render2])
        assert ctx.set_scene(render2) == 0
        assert ctx.draw(0) == 0
        assert ctx2.set_scene(scene) != 0
        assert ctx2.draw(0) == 0
        del ctx
        del ctx2
예제 #15
0
def api_hud(width=234, height=123):
    viewer = ngl.Context()
    assert viewer.configure(offscreen=1,
                            width=width,
                            height=height,
                            backend=_backend) == 0
    render = _get_scene()
    scene = ngl.HUD(render)
    assert viewer.set_scene(scene) == 0
    for i in range(60 * 3):
        assert viewer.draw(i / 60.) == 0
    del viewer
예제 #16
0
def api_reset_scene(width=320, height=240):
    ctx = ngl.Context()
    ret = ctx.configure(offscreen=1, width=width, height=height, backend=_backend)
    assert ret == 0
    render = _get_scene()
    assert ctx.set_scene(render) == 0
    ctx.draw(0)
    assert ctx.set_scene(None) == 0
    ctx.draw(1)
    assert ctx.set_scene(render) == 0
    ctx.draw(2)
    assert ctx.set_scene(None) == 0
    ctx.draw(3)
예제 #17
0
def api_ctx_ownership_subgraph():
    for shared in (True, False):
        viewer = ngl.Context()
        viewer2 = ngl.Context()
        assert viewer.configure(offscreen=1,
                                width=16,
                                height=16,
                                backend=_backend) == 0
        assert viewer2.configure(offscreen=1,
                                 width=16,
                                 height=16,
                                 backend=_backend) == 0
        quad = ngl.Quad()
        render1 = _get_scene(quad)
        if not shared:
            quad = ngl.Quad()
        render2 = _get_scene(quad)
        scene = ngl.Group([render1, render2])
        assert viewer.set_scene(render2) == 0
        assert viewer.draw(0) == 0
        assert viewer2.set_scene(scene) != 0
        assert viewer2.draw(0) == 0  # XXX: drawing with no scene is allowed?
        del viewer
        del viewer2
예제 #18
0
def api_reconfigure_clearcolor(width=16, height=16):
    import zlib
    viewer = ngl.Context()
    capture_buffer = bytearray(width * height * 4)
    viewer = ngl.Context()
    assert viewer.configure(offscreen=1,
                            width=width,
                            height=height,
                            backend=_backend,
                            capture_buffer=capture_buffer) == 0
    scene = _get_scene()
    assert viewer.set_scene(scene) == 0
    assert viewer.draw(0) == 0
    assert zlib.crc32(capture_buffer) == 0xb4bd32fa
    assert viewer.configure(offscreen=1,
                            width=width,
                            height=height,
                            backend=_backend,
                            capture_buffer=capture_buffer,
                            clear_color=(0.3, 0.3, 0.3, 1.0)) == 0
    assert viewer.draw(0) == 0
    assert zlib.crc32(capture_buffer) == 0xfeb0bb01
    del capture_buffer
    del viewer
예제 #19
0
    def render_frames(self):
        # We make sure the lists of medias is explicitely empty. If we don't a
        # jobbed make on the tests will attempt concurrent generations of a
        # default ngl-media.mp4.
        idict = dict(medias=[])

        backend = os.environ.get('BACKEND')
        if backend:
            idict['backend'] = backend

        ret = self._scene_func(idict=idict, **self._scene_kwargs)
        width, height = self._width, self._height
        duration = ret['duration']
        scene = ret['scene']

        capture_buffer = bytearray(width * height * 4)
        viewer = ngl.Context()
        assert viewer.configure(
            offscreen=1,
            width=width,
            height=height,
            backend=get_backend(backend) if backend else ngl.BACKEND_AUTO,
            samples=self._samples,
            clear_color=self._clear_color,
            capture_buffer=capture_buffer) == 0
        timescale = duration / float(self._nb_keyframes)

        if self._scene_wrap:
            scene = self._scene_wrap(scene)

        if self._exercise_dot:
            assert scene.dot()

        if self._exercise_serialization:
            scene_str = scene.serialize()
            viewer.set_scene_from_string(scene_str)
        else:
            viewer.set_scene(scene)

        for t_id in range(self._nb_keyframes):
            if self._keyframes_callback:
                self._keyframes_callback(t_id)
            viewer.draw(t_id * timescale)

            yield (width, height, capture_buffer)

            if not self._exercise_serialization and self._exercise_dot:
                scene.dot()
예제 #20
0
def api_capture_buffer(width=16, height=16):
    import zlib

    ctx = ngl.Context()
    ret = ctx.configure(offscreen=1, width=width, height=height, backend=_backend)
    assert ret == 0
    scene = _get_scene()
    assert ctx.set_scene(scene) == 0
    for i in range(2):
        capture_buffer = bytearray(width * height * 4)
        assert ctx.set_capture_buffer(capture_buffer) == 0
        assert ctx.draw(0) == 0
        assert ctx.set_capture_buffer(None) == 0
        assert ctx.draw(0) == 0
        assert zlib.crc32(capture_buffer) == 0xB4BD32FA
    del ctx
예제 #21
0
    def render_frames(self):
        idict = {}

        backend = os.environ.get("BACKEND")
        if backend:
            idict["backend"] = backend

        ret = self._scene_func(idict=idict, **self._scene_kwargs)
        width, height = self._width, self._height
        duration = ret["duration"]
        scene = ret["scene"]

        capture_buffer = bytearray(width * height * 4)
        ctx = ngl.Context()
        ret = ctx.configure(
            offscreen=1,
            width=width,
            height=height,
            backend=get_backend(backend) if backend else ngl.BACKEND_AUTO,
            samples=self._samples,
            clear_color=self._clear_color,
            capture_buffer=capture_buffer,
            hud=self._hud,
            hud_export_filename=self._hud_export_filename,
        )
        assert ret == 0
        timescale = duration / float(self._nb_keyframes)

        if self._exercise_dot:
            assert scene.dot()

        if self._exercise_serialization:
            scene_str = scene.serialize()
            assert ctx.set_scene_from_string(scene_str) == 0
        else:
            assert ctx.set_scene(scene) == 0

        for t_id in range(self._nb_keyframes):
            if self._keyframes_callback:
                self._keyframes_callback(t_id)
            ctx.draw(t_id * timescale)

            yield (width, height, capture_buffer)

            if not self._exercise_serialization and self._exercise_dot:
                scene.dot()
예제 #22
0
def api_denied_node_live_change(width=320, height=240):
    ctx = ngl.Context()
    ret = ctx.configure(offscreen=1, width=width, height=height, backend=_backend)
    assert ret == 0

    scene = ngl.Translate(ngl.Group())

    # Check that we can live change but not into a node
    assert ctx.set_scene(scene) == 0
    assert scene.set_vector(1, 2, 3) == 0
    assert scene.set_vector(ngl.UniformVec3(value=(3, 2, 1))) != 0

    # Check that we can do the change after a reset of the context
    assert ctx.set_scene(None) == 0
    assert scene.set_vector(ngl.UniformVec3(value=(4, 5, 6))) == 0

    # Check that we can not live unplug a node from a live changeable parameter
    assert ctx.set_scene(scene) == 0
    assert scene.set_vector(ngl.UniformVec3(value=(7, 8, 9))) != 0
예제 #23
0
    def __init__(self, window, width, height, config):
        super().__init__()

        self._mutex = QtCore.QMutex()
        self._cond = QtCore.QWaitCondition()

        self._window = window
        self._width = width
        self._height = height

        self._scene = None
        self._framerate = config.get('framerate')
        self._duration = 0.0
        self._clear_color = config.get('clear_color')
        self._aspect_ratio = config.get('aspect_ratio')
        self._samples = config.get('samples')
        self._backend = config.get('backend')

        self._events = []
        self._wait_first_frame = True
        self._clock = Clock(self._framerate, self._duration)
        self._viewer = ngl.Context()
        self._configure_viewer()
예제 #24
0
def api_reconfigure_clearcolor(width=16, height=16):
    import zlib
    capture_buffer = bytearray(width * height * 4)
    ctx = ngl.Context()
    assert ctx.configure(offscreen=1,
                         width=width,
                         height=height,
                         backend=_backend,
                         capture_buffer=capture_buffer) == 0
    scene = _get_scene()
    assert ctx.set_scene(scene) == 0
    assert ctx.draw(0) == 0
    assert zlib.crc32(capture_buffer) == 0xb4bd32fa
    assert ctx.configure(offscreen=1,
                         width=width,
                         height=height,
                         backend=_backend,
                         capture_buffer=capture_buffer,
                         clear_color=(0.4, 0.4, 0.4, 1.0)) == 0
    assert ctx.draw(0) == 0
    assert zlib.crc32(capture_buffer) == 0x05c44869
    del capture_buffer
    del ctx
예제 #25
0
def api_livectls():
    # Build a scene and extract its live controls
    rng = random.Random(0)
    scene = ngl.Group(
        children=(
            ngl.UniformBool(live_id="b"),
            ngl.UniformFloat(live_id="f"),
            ngl.UniformIVec3(live_id="iv3"),
            ngl.UserSwitch(
                ngl.Group(
                    children=(
                        ngl.UniformMat4(live_id="m4"),
                        ngl.UniformColor(live_id="clr"),
                        ngl.UniformQuat(as_mat4=True, live_id="rot"),
                    )
                ),
                live_id="switch",
            ),
            ngl.Text(live_id="txt"),
        )
    )
    livectls = ngl.get_livectls(scene)
    assert len(livectls) == 8

    # Attach scene and run a dummy draw to make sure it's valid
    ctx = ngl.Context()
    ret = ctx.configure(offscreen=1, width=16, height=16, backend=_backend)
    assert ret == 0
    assert ctx.set_scene(scene) == 0
    assert ctx.draw(0) == 0

    # Apply live changes on nodes previously tracked by get_livectls()
    values = dict(
        b=True,
        f=rng.uniform(-1, 1),
        iv3=[rng.randint(-100, 100) for i in range(3)],
        switch=False,
        m4=[rng.uniform(-1, 1) for i in range(16)],
        clr=(0.9, 0.3, 0.8),
        rot=(0.1, -0.2, 0.5, -0.3),
        txt="test string",
    )
    for live_id, value in values.items():
        node = livectls[live_id]["node"]
        node_type = livectls[live_id]["node_type"]
        assert node_type == node.__class__.__name__
        if node_type == "UserSwitch":
            node.set_enabled(value)
        elif node_type == "Text":
            node.set_text(value)
        elif hasattr(value, "__iter__"):
            node.set_value(*value)
        else:
            node.set_value(value)

    # Detach scene from context and grab all live controls again
    assert ctx.set_scene(None) == 0
    livectls = ngl.get_livectls(scene)

    # Inspect nodes to check if they were properly altered by the live changes
    for live_id, expected_value in values.items():
        value = livectls[live_id]["val"]
        node_type = livectls[live_id]["node_type"]
        if node_type == "Text":
            assert value == expected_value, (value, expected_value)
        elif hasattr(value, "__iter__"):
            assert all(math.isclose(v, e, rel_tol=1e-6) for v, e in zip(value, expected_value))
        else:
            assert math.isclose(value, expected_value, rel_tol=1e-6)
예제 #26
0
def api_backend():
    ctx = ngl.Context()
    assert ctx.configure(backend=0x1234) < 0
    del ctx
    def _export(self, filename, width, height, extra_enc_args=None):
        fd_r, fd_w = os.pipe()

        cfg = self._get_scene_func()
        if not cfg:
            self.failed.emit("You didn't select any scene to export.")
            return False

        fps = cfg["framerate"]
        duration = cfg["duration"]
        samples = cfg["samples"]

        cmd = [
            # fmt: off
            "ffmpeg", "-r", "%d/%d" % fps,
            "-nostats", "-nostdin",
            "-f", "rawvideo",
            "-video_size", "%dx%d" % (width, height),
            "-pixel_format", "rgba",
            "-i", "pipe:%d" % fd_r
            # fmt: on
        ]
        if extra_enc_args:
            cmd += extra_enc_args
        cmd += ["-y", filename]

        reader = subprocess.Popen(cmd, pass_fds=(fd_r,))
        os.close(fd_r)

        capture_buffer = bytearray(width * height * 4)

        # node.gl context
        ctx = ngl.Context()
        ctx.configure(
            platform=ngl.PLATFORM_AUTO,
            backend=get_backend(cfg["backend"]),
            offscreen=1,
            width=width,
            height=height,
            viewport=get_viewport(width, height, cfg["aspect_ratio"]),
            samples=samples,
            clear_color=cfg["clear_color"],
            capture_buffer=capture_buffer,
        )
        ctx.set_scene_from_string(cfg["scene"])

        if self._time is not None:
            ctx.draw(self._time)
            os.write(fd_w, capture_buffer)
            self.progressed.emit(100)
        else:
            # Draw every frame
            nb_frame = int(duration * fps[0] / fps[1])
            for i in range(nb_frame):
                if self._cancelled:
                    break
                time = i * fps[1] / float(fps[0])
                ctx.draw(time)
                os.write(fd_w, capture_buffer)
                self.progressed.emit(i * 100 / nb_frame)
            self.progressed.emit(100)

        os.close(fd_w)
        reader.wait()
        return True
예제 #28
0
def api_backend():
    ctx = ngl.Context()
    ret = ctx.configure(backend=0x1234)
    assert ret < 0
    del ctx
예제 #29
0
    def _export(self, filename, width, height, extra_enc_args=None):
        fd_r, fd_w = os.pipe()

        cfg = self._get_scene_func()
        if not cfg:
            self.failed.emit()
            return False

        fps = cfg['framerate']
        duration = cfg['duration']
        samples = cfg['samples']

        cmd = [
            'ffmpeg', '-r',
            '%d/%d' % fps, '-nostats', '-nostdin', '-f', 'rawvideo',
            '-video_size',
            '%dx%d' % (width, height), '-pixel_format', 'rgba', '-i',
            'pipe:%d' % fd_r
        ]
        if extra_enc_args:
            cmd += extra_enc_args
        cmd += ['-y', filename]

        reader = subprocess.Popen(cmd, pass_fds=(fd_r, ))
        os.close(fd_r)

        capture_buffer = bytearray(width * height * 4)

        # node.gl context
        ctx = ngl.Context()
        ctx.configure(
            platform=ngl.PLATFORM_AUTO,
            backend=get_backend(cfg['backend']),
            offscreen=1,
            width=width,
            height=height,
            viewport=get_viewport(width, height, cfg['aspect_ratio']),
            samples=samples,
            clear_color=cfg['clear_color'],
            capture_buffer=capture_buffer,
        )
        ctx.set_scene_from_string(cfg['scene'])

        if self._time is not None:
            ctx.draw(self._time)
            os.write(fd_w, capture_buffer)
            self.progressed.emit(100)
        else:
            # Draw every frame
            nb_frame = int(duration * fps[0] / fps[1])
            for i in range(nb_frame):
                if self._cancelled:
                    break
                time = i * fps[1] / float(fps[0])
                ctx.draw(time)
                os.write(fd_w, capture_buffer)
                self.progressed.emit(i * 100 / nb_frame)
            self.progressed.emit(100)

        os.close(fd_w)
        reader.wait()
        return True
예제 #30
0
def api_backend():
    viewer = ngl.Context()
    assert viewer.configure(backend=0x1234) < 0
    del viewer