258 lines
9.5 KiB
Python
258 lines
9.5 KiB
Python
#------------------------------------------------------------------------------
|
|
#
|
|
# PyGUI - OpenGL - Win32
|
|
#
|
|
#------------------------------------------------------------------------------
|
|
|
|
import win32con as wc, win32ui as ui, win32gui as gui
|
|
import GUI.GDIPlus as gdi
|
|
from GUI.Components import win_none
|
|
from GUI.OpenGL import WGL as wgl
|
|
from GUI.GGLViews import GLView as GGLView
|
|
from GUI.GGLPixmaps import GLPixmap as GGLPixmap
|
|
from GUI.GGLConfig import GLConfig as GGLConfig, GLConfigError
|
|
from GUI.GLContexts import GLContext
|
|
from GUI.GLTextures import Texture
|
|
|
|
win_style = wc.WS_VISIBLE | wc.WS_CLIPCHILDREN | wc.WS_CLIPSIBLINGS
|
|
win_default_size = GGLView._default_size
|
|
win_default_rect = (0, 0, win_default_size[0], win_default_size[1])
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class GLConfig(GGLConfig):
|
|
|
|
def _as_win_pixelformat(self, mode):
|
|
print "GLConfig._as_win_pixelformat: mode =", mode ###
|
|
pf = wgl.PIXELFORMATDESCRIPTOR()
|
|
flags = wgl.PFD_SUPPORT_OPENGL
|
|
if mode == 'screen' or mode == 'both':
|
|
print "GLConfig: requesting screen drawing" ###
|
|
flags |= wgl.PFD_DRAW_TO_WINDOW
|
|
if self._double_buffer:
|
|
flags |= wgl.PFD_DOUBLEBUFFER | wgl.PFD_SWAP_EXCHANGE
|
|
else:
|
|
flags |= wgl.PFD_DOUBLEBUFFER_DONTCARE
|
|
if mode == 'pixmap' or mode == 'both':
|
|
print "GLConfig: requesting pixmap drawing" ###
|
|
flags |= wgl.PFD_DRAW_TO_BITMAP | wgl.PFD_SUPPORT_GDI
|
|
if not self._depth_buffer:
|
|
flags |= wgl.PFD_DEPTH_DONTCARE
|
|
if self._stereo:
|
|
flags |= wgl.PFD_STEREO
|
|
else:
|
|
flags |= wgl.PFD_STEREO_DONTCARE
|
|
pf.dwFlags = flags & 0xffffffff
|
|
pf.iPixelType = wgl.PFD_TYPE_RGBA
|
|
#pf.cColorBits = 3 * self._color_size
|
|
pf.cColorBits = 32 ###
|
|
pf.cAlphaBits = 8 ###
|
|
pf.cAlphaShift = 24 ###
|
|
if self._alpha:
|
|
pf.cAlphaBits = self._alpha_size
|
|
pf.cAuxBuffers = self._aux_buffers
|
|
if self._depth_buffer:
|
|
pf.cDepthBits = self._depth_size
|
|
if self._stencil_buffer:
|
|
pf.cStencilBits = self._stencil_size
|
|
if self._accum_buffer:
|
|
pf.cAccumBits = 3 * self._accum_size
|
|
pf.iLayerType = wgl.PFD_MAIN_PLANE
|
|
return pf
|
|
|
|
def _from_win_pixelformat(cls, pf):
|
|
self = cls.__new__(cls)
|
|
flags = pf.dwFlags
|
|
self._double_buffer = flags & wgl.PFD_DOUBLEBUFFER != 0
|
|
self._alpha = pf.cAlphaSize > 0
|
|
self._color_size = pf.cColorBits
|
|
self._alpha_size = pf.cAlphaSize
|
|
self._stereo = flags & wgl.PFD_STEREO != 0
|
|
self._aux_buffers = pf.cAuxBuffers
|
|
self._depth_buffer = pf.cDepthBits > 0
|
|
self._depth_size = pf.cDepthBits
|
|
self._stencil_buffer = pf.cStencilBits > 0
|
|
self._stencil_size = pf.cStencilBits
|
|
self._accum_size = pf.cAccumBits
|
|
self._accum_buffer = self._accum_size > 0
|
|
self._multisample = False
|
|
self._samples_per_pixel = 1
|
|
return self
|
|
|
|
def _check_win_pixelformat(self, pf, mode):
|
|
flags = pf.dwFlags
|
|
if mode == 'screen' or mode == 'both':
|
|
if not flags & wgl.PFD_DRAW_TO_WINDOW:
|
|
raise GLConfigError("Rendering to screen not supported")
|
|
if mode == 'pixmap' or mode == 'both':
|
|
if not flags & wgl.PFD_DRAW_TO_BITMAP:
|
|
raise GLConfigError("Rendering to pixmap not supported")
|
|
if self._alpha and pf.cAlphaBits == 0:
|
|
raise GLConfigError("Alpha channel not available")
|
|
if self._stereo and not flags & wgl.PFD_STEREO:
|
|
raise GLConfigError("Stereo buffer not available")
|
|
if self._aux_buffers and pf.cAuxBuffers == 0:
|
|
raise GLConfigError("Auxiliary buffers not available")
|
|
if self._depth_buffer and pf.cDepthBits == 0:
|
|
raise GLConfigError("Depth buffer not available")
|
|
if self._stencil_buffer and pf.cStencilBits == 0:
|
|
raise GLConfigError("Stencil buffer not available")
|
|
if self.accum_buffer and pf.cAccumBits == 0:
|
|
raise GLConfigError("Accumulation buffer not available")
|
|
|
|
def _win_supported_pixelformat(self, hdc, mode):
|
|
reqpf = self._as_win_pixelformat(mode)
|
|
print "GLConfig._win_supported_pixelformat" ###
|
|
print "Requested format:" ###
|
|
win_dump_pixelformat(reqpf) ###
|
|
print "GLConfig: Choosing pixel format for hdc", hdc ###
|
|
ipf = wgl.ChoosePixelFormat(hdc, reqpf)
|
|
print "... result =", ipf ###
|
|
actpf = wgl.PIXELFORMATDESCRIPTOR()
|
|
print "GLConfig: Describing pixel format", ipf, "for hdc", hdc ###
|
|
wgl.DescribePixelFormat(hdc, ipf, actpf.nSize, actpf)
|
|
print "Actual format:" ###
|
|
win_dump_pixelformat(actpf) ###
|
|
return ipf, actpf
|
|
|
|
def supported(self, mode = 'both'):
|
|
dc = win_none.GetDC()
|
|
hdc = dc.GetSafeHdc()
|
|
ipf, actpf = self._win_supported_pixelformat(hdc, mode)
|
|
win_none.ReleaseDC(dc)
|
|
return GLConfig._from_win_pixelformat(actpf)
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class GLView(GGLView):
|
|
|
|
def __init__(self, config = None, share_group = None, **kwds):
|
|
config = GLConfig._from_args(config, kwds)
|
|
win = ui.CreateWnd()
|
|
win.CreateWindow(None, None, win_style, win_default_rect,
|
|
win_none, 0)
|
|
dc = win.GetDC()
|
|
hdc = dc.GetSafeHdc()
|
|
GLContext.__init__(self, share_group, config, hdc, 'screen')
|
|
GGLView.__init__(self, _win = win, **kwds)
|
|
self._with_context(hdc, self._init_context)
|
|
win.ReleaseDC(dc)
|
|
|
|
def destroy(self):
|
|
GLContext.destroy(self)
|
|
GGLView.destroy(self)
|
|
|
|
def with_context(self, proc, flush = False):
|
|
win = self._win
|
|
dc = win.GetDC()
|
|
hdc = dc.GetSafeHdc()
|
|
try:
|
|
self._with_context(hdc, proc, flush)
|
|
finally:
|
|
win.ReleaseDC(dc)
|
|
|
|
def OnPaint(self):
|
|
#print "GLView.OnPaint" ###
|
|
win = self._win
|
|
dc, ps = win.BeginPaint()
|
|
try:
|
|
hdc = dc.GetSafeHdc()
|
|
self._with_context(hdc, self.render, True)
|
|
finally:
|
|
win.EndPaint(ps)
|
|
|
|
def _resized(self, delta):
|
|
self.with_context(self._update_viewport)
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class GLPixmap(GGLPixmap):
|
|
|
|
def __init__(self, width, height, config = None, share_group = None, **kwds):
|
|
print "GLPixmap:", width, height, kwds ###
|
|
config = GLConfig._from_args(config, kwds)
|
|
image = gdi.Bitmap(width, height)
|
|
self._win_image = image
|
|
graphics = gdi.Graphics.from_image(image)
|
|
self._win_graphics = graphics
|
|
hdc = graphics.GetHDC()
|
|
self._win_hdc = hdc
|
|
GLContext.__init__(self, share_group, config, hdc, 'pixmap')
|
|
self._with_context(hdc, self._init_context)
|
|
print "GLPixmap: done" ###
|
|
|
|
def __del__(self):
|
|
graphics = self._win_graphics
|
|
graphics.ReleaseHDC(self._win_hdc)
|
|
|
|
def with_context(self, proc, flush = False):
|
|
try:
|
|
self._with_context(self._hdc, proc, flush)
|
|
finally:
|
|
graphics.ReleaseHDC(hdc)
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
#class GLPixmap(GGLPixmap):
|
|
#
|
|
# def __init__(self, width, height, config = None, share_group = None, **kwds):
|
|
# print "GLPixmap:", width, height, kwds ###
|
|
# config = GLConfig._from_args(config, kwds)
|
|
# dc0 = win_none.GetDC()
|
|
# dc = dc0.CreateCompatibleDC(dc0)
|
|
# bm = ui.CreateBitmap()
|
|
# ###bm.CreateCompatibleBitmap(dc0, width, height)
|
|
# bm.CreateCompatibleBitmap(dc0, 1, 1)
|
|
# win_none.ReleaseDC(dc0)
|
|
# dc.SelectObject(bm)
|
|
# self._win_dc = dc
|
|
# self._win_bm = bm
|
|
# hdc = dc.GetSafeHdc()
|
|
# win_dump_bitmap(bm) ###
|
|
# GLContext.__init__(self, share_group, config, hdc, 'pixmap')
|
|
# self._with_context(hdc, self._init_context)
|
|
# print "GLPixmap: done" ###
|
|
#
|
|
# def with_context(self, proc, flush = False):
|
|
# hdc = self._win_dc.GetSafeHdc()
|
|
# self._with_context(hdc, proc, flush)
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
def win_dump_pixelformat(pf):
|
|
print "nSize =", pf.nSize
|
|
print "nVersion =", pf.nVersion
|
|
print "dwFlags = 0x%08x" % pf.dwFlags
|
|
print "iPixelType =", pf.iPixelType
|
|
print "cColorBits =", pf.cColorBits
|
|
print "cRedBits =", pf.cRedBits
|
|
print "cRedShift =", pf.cRedShift
|
|
print "cGreenBits =", pf.cGreenBits
|
|
print "cGreenShift =", pf.cGreenShift
|
|
print "cBlueBits =", pf.cBlueBits
|
|
print "cBlueShift =", pf.cBlueShift
|
|
print "cAlphaBits =", pf.cAlphaBits
|
|
print "cAlphaShift =", pf.cAlphaShift
|
|
print "cAccumBits =", pf.cAccumBits
|
|
print "cAccumRedBits =", pf.cAccumRedBits
|
|
print "cAccumGreenBits =", pf.cAccumGreenBits
|
|
print "cAccumBlueBits =", pf.cAccumBlueBits
|
|
print "cDepthBits =", pf.cDepthBits
|
|
print "cStencilBits =", pf.cStencilBits
|
|
print "cAuxBuffers =", pf.cAuxBuffers
|
|
print "iLayerType =", pf.iLayerType
|
|
print "bReserved =", pf.bReserved
|
|
print "dwLayerMask =", pf.dwLayerMask
|
|
print "dwVisibleMask =", pf.dwVisibleMask
|
|
print "dwDamageMask =", pf.dwDamageMask
|
|
|
|
def win_dump_bitmap(bm):
|
|
info = bm.GetInfo()
|
|
print "bmType =", info['bmType']
|
|
print "bmWidth =", info['bmWidth']
|
|
print "bmHeight =", info['bmHeight']
|
|
print "bmWidthBytes =", info['bmWidthBytes']
|
|
print "bmPlanes =", info['bmPlanes']
|
|
print "bmBitsPixel =", info['bmBitsPixel']
|
|
|
|
|