Source

glutton / test_background_drawing_threads.py

Full commit
import threading
import multiprocessing as mp
from ctypes import c_float, c_int32

import wx
from OpenGL.GL import *
import numpy as np

import glutton_tester
from glutton import canvas
from glutton.mixins.navigate2d import Navigate2D

from sierpinski_triangle import construct_sierpinski_triangle


NUMBER_OF_POINTS = 1000000
MULTIPROCESSING = False


class TestCanvas(canvas.Canvas, Navigate2D):
    def __init__(self, parent):
        canvas.Canvas.__init__(self, parent, enforce_fps=60)

    def start_background_drawing(self):
        self.raw_points = mp.Array(c_float, 2 * NUMBER_OF_POINTS)
        self.points = np.frombuffer(self.raw_points.get_obj(), np.float32)
        
        self.points_count = mp.Value(c_int32)
        self.points_count.value = 0
        
        Worker = mp.Process if MULTIPROCESSING else threading.Thread
        self.worker = Worker(
            target=construct_sierpinski_triangle, 
            args=(self.raw_points, NUMBER_OF_POINTS, self.points_count)
        )
        self.worker.start()

    def init_context(self):
        glColor3ub(255, 255, 255)
        wx.CallAfter(self.pan, 5, 5)
        
        self.start_background_drawing()
        
        self.Parent.Bind(wx.EVT_CLOSE, self.OnExit)

    def OnExit(self, event):
        self.worker.join()
        event.Skip()

    def render_scene(self):
        glClear(GL_COLOR_BUFFER_BIT)
        glEnableClientState(GL_VERTEX_ARRAY)
        glVertexPointer(2, GL_FLOAT, 0, self.points)
        glDrawArrays(GL_POINTS, 0, self.points_count.value)
        glDisableClientState(GL_VERTEX_ARRAY)


if __name__ == "__main__":
    glutton_tester.test(TestCanvas, maximize=True)