265 lines
10 KiB
Python
265 lines
10 KiB
Python
#------------------------------------------------------------------------------
|
|
#
|
|
# PyGUI - OpenGL - Win32
|
|
#
|
|
#------------------------------------------------------------------------------
|
|
|
|
import win32con as wc, win32ui as ui, win32gui as gui
|
|
import GDIPlus as gdi
|
|
import WGL
|
|
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_pixelattrs(self, mode):
|
|
print "GLConfig._as_arb_pixelattrs: mode =", mode ###
|
|
attrs = {}
|
|
attrs[wgl.WGL_SUPPORT_OPENGL_ARB] = True
|
|
if mode == 'screen' or mode == 'both':
|
|
print "GLConfig: requesting screen drawing" ###
|
|
attrs[wgl.WGL_DRAW_TO_WINDOW_ARB] = True
|
|
if self._double_buffer:
|
|
attrs[wgl.WGL_DOUBLE_BUFFER_ARB] = True
|
|
if mode == 'pixmap' or mode == 'both':
|
|
print "GLConfig: requesting pixmap drawing" ###
|
|
attrs[wgl.WGL_DRAW_TO_PBUFFER_ARB] = True
|
|
if self._stereo:
|
|
attrs[wgl.WGL_STEREO_ARB] = True
|
|
attrs[wgl.WGL_PIXEL_TYPE_ARB] = wgl.WGL_TYPE_RGBA_ARB
|
|
bits = self._color_size
|
|
attrs[wgl.WGL_RED_BITS_ARB] = bits
|
|
attrs[wgl.WGL_GREEN_BITS_ARB] = bits
|
|
attrs[wgl.WGL_BLUE_BITS_ARB] = bits
|
|
if self._alpha:
|
|
attrs[wgl.WGL_ALPHA_BITS_ARB] = self._alpha_size
|
|
attrs[wgl.WGL_AUX_BUFFERS_ARB] = self._aux_buffers
|
|
if self._depth_buffer:
|
|
attrs[wgl.WGL_DEPTH_BITS_ARB] = self._depth_size
|
|
if self._stencil_buffer:
|
|
attrs[wgl.WGL_STENCIL_BITS_ARB] = self._stencil_size
|
|
if self._accum_buffer:
|
|
bits = self._accum_size
|
|
attrs[wgl.WGL_ACCUM_RED_BITS_ARB] = bits
|
|
attrs[wgl.WGL_ACCUM_GREEN_BITS_ARB] = bits
|
|
attrs[wgl.WGL_ACCUM_BLUE_BITS_ARB] = bits
|
|
return attrs
|
|
|
|
def _from_win_pixelattrs(cls, attrs):
|
|
self = cls.__new__(cls)
|
|
self._double_buffer = attrs[wgl.WGL_DOUBLE_BUFFER_ARB]
|
|
self._color_size = attrs[wgl.WGL_COLOR_BITS_ARB] // 3
|
|
self._alpha_size = attrs[wgl.WGL_ALPHA_BITS_ARB]
|
|
self._alpha = self._alpha_size > 0
|
|
self._stereo = attrs[wgl.WGL_STEREO_ARB] #flags & wgl.PFD_STEREO != 0
|
|
self._aux_buffers = attrs[wgl.WGL_AUX_BUFFERS_ARB] > 0
|
|
self._depth_size = attrs[wgl.WGL_DEPTH_BITS_ARB]
|
|
self._depth_buffer = self._depth_size > 0
|
|
self._stencil_size = attrs[wgl.WGL_STENCIL_BITS_ARB]
|
|
self._stencil_buffer = self._stencil_bits > 0
|
|
self._accum_size = attrs[wgl.WGL_ACCUM_BITS_ARB] // 3
|
|
self._accum_buffer = self._accum_size > 0
|
|
self._multisample = False
|
|
self._samples_per_pixel = 1
|
|
return self
|
|
|
|
# def _check_win_pixelattrs(self, attrs, mode):
|
|
# if mode == 'screen' or mode == 'both':
|
|
# if not attrs[wgl.WGL_DRAW_TO_WINDOW_ARB]:
|
|
# raise GLConfigError("Rendering to screen not supported")
|
|
# if mode == 'pixmap' or mode == 'both':
|
|
# if not attrs[wgl.WGL_DRAW_TO_PBUFFER_ARB]:
|
|
# raise GLConfigError("Rendering to pixmap not supported")
|
|
# if self._alpha and attrs[wgl.WGL_ALPHA_BITS_ARB] == 0:
|
|
# raise GLConfigError("Alpha channel not available")
|
|
# if self._stereo and not attrs[wgl.WGL_STEREO_ARB]:
|
|
# raise GLConfigError("Stereo buffer not available")
|
|
# if self._aux_buffers and attrs]wgl.WGL_AUX_BUFFERS_ARB] == 0:
|
|
# raise GLConfigError("Auxiliary buffers not available")
|
|
# if self._depth_buffer and attrs[wgl.WGL_DEPTH_BITS_ARB] == 0:
|
|
# raise GLConfigError("Depth buffer not available")
|
|
# if self._stencil_buffer and attrs[wgl.WGL_STENCIL_BITS] == 0:
|
|
# raise GLConfigError("Stencil buffer not available")
|
|
# if self.accum_buffer and attrs[wgl.WGL_ACCUM_BITS] == 0:
|
|
# raise GLConfigError("Accumulation buffer not available")
|
|
|
|
_win_query_pixelattr_keys = [
|
|
wgl.WGL_SUPPORT_OPENGL_ARB,
|
|
wgl.WGL_DRAW_TO_WINDOW_ARB,
|
|
wgl.WGL_DOUBLE_BUFFER_ARB,
|
|
wgl.WGL_DRAW_TO_PBUFFER_ARB,
|
|
wgl.WGL_STEREO_ARB,
|
|
wgl.WGL_PIXEL_TYPE_ARB,
|
|
wgl.WGL_COLOR_BITS_ARB,
|
|
wgl.WGL_ALPHA_BITS_ARB,
|
|
wgl.WGL_AUX_BUFFERS_ARB,
|
|
wgl.WGL_DEPTH_BITS_ARB,
|
|
wgl.WGL_STENCIL_BITS_ARB,
|
|
wgl.WGL_ACCUM_BITS_ARB,
|
|
]
|
|
|
|
def _win_supported_pixelformat(self, hdc, mode):
|
|
req_attrs = self._as_win_pixelattrs(mode)
|
|
print "GLConfig: Choosing pixel format for hdc", hdc ###
|
|
print "Requested attributes:", req_attrs ###
|
|
req_array = WGL.attr_array(req_attrs)
|
|
print "Requested array:", req_array ###
|
|
ipfs, nf = wgl.wglChoosePixelFormatEXT(hdc, req_array, None, 1)
|
|
print "Pixel formats:", ipfs ###
|
|
print "No. of formats:", nf ###
|
|
if not ipfs:
|
|
req_attrs[wgl.WGL_DOUBLE_BUFFER_ARB] = not self._double_buffer
|
|
req_array = WGL.attr_array(req_attrs)
|
|
ipfs, nf = wglChoosePixelFormatARB(hdc, req_array, None, 1)
|
|
if not ipfs:
|
|
return None, None
|
|
print "GLConfig: Describing pixel format", ipf, "for hdc", hdc ###
|
|
keys = _win_query_pixelattr_keys
|
|
values = wglGetPixelFormatAttribivARB(hdc, ipf, 0, keys)
|
|
print "Actual values:", values ###
|
|
act_attrs = WGL.attr_dict(keys, values)
|
|
print "Actual attrs:", act_attrs ###
|
|
return ipfs[0], act_attrs
|
|
|
|
def supported(self, mode = 'both'):
|
|
dc = win_none.GetDC()
|
|
hdc = dc.GetSafeHdc()
|
|
ipf, act_attrs = self._win_supported_pixelformat(hdc, mode)
|
|
win_none.ReleaseDC(dc)
|
|
if ipf is None:
|
|
return None
|
|
return GLConfig._from_win_pixelattrs(act_attrs)
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
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)
|
|
pyhdc = gui.CreateCompatibleDC(0)
|
|
dc = ui.CreateDCFromHandle(pyhdc)
|
|
hdc = dc.GetSafeHdc()
|
|
hbm = gui.CreateCompatibleBitmap(hdc, width, height)
|
|
bm = ui.CreateBitmapFromHandle(hbm)
|
|
dc.SelectObject(bm)
|
|
self._win_dc = dc
|
|
self._win_hbm = hbm
|
|
self._win_bm = 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
|