"""Implementations for "held-pointers" of various types
This argument type is special because it is stored, that is, it
needs to be cached on our side so that the memory address does not
go out-of-scope
storedPointers = {}
def glVertexPointerd( array ):
"Natural writing of glVertexPointerd using standard ctypes"
arg2 = GL_DOUBLE
arg3 = 0 # stride
arg4 = arrays.asArray(array, GL_DOUBLE)
arg1 = arrays.arraySize( arg4, 'd' )
platform.OpenGL.glVertexPointer( arg1, arg2, arg3, arrays.ArrayDatatype.dataPointer(arg4) )
glCheckError()
# only store if we successfully set the value...
storedPointers[ GL_VERTEX_ARRAY ] = arg4
return arg4
"""
from OpenGL import platform,arrays,error,wrapper,contextdata,converters,constant,ERROR_ON_COPY
from OpenGL.raw import GL
from OpenGL.raw.GL import annotations
import ctypes
import weakref
GLsizei = ctypes.c_int
GLenum = ctypes.c_uint
GLint = ctypes.c_int
# OpenGL-ctypes variables that mimic OpenGL constant operation...
GL_INTERLEAVED_ARRAY_POINTER = constant.Constant( 'GL_INTERLEAVED_ARRAY_POINTER', -32910 )
__all__ = (
'glColorPointer',
'glColorPointerb','glColorPointerd','glColorPointerf','glColorPointeri',
'glColorPointers','glColorPointerub','glColorPointerui','glColorPointerus',
'glEdgeFlagPointer',
'glEdgeFlagPointerb',
'glIndexPointer',
'glIndexPointerb','glIndexPointerd','glIndexPointerf',
'glIndexPointeri','glIndexPointers','glIndexPointerub',
'glNormalPointer',
'glNormalPointerb',
'glNormalPointerd','glNormalPointerf','glNormalPointeri','glNormalPointers',
'glTexCoordPointer',
'glTexCoordPointerb','glTexCoordPointerd','glTexCoordPointerf',
'glTexCoordPointeri','glTexCoordPointers',
'glVertexPointer',
'glVertexPointerb','glVertexPointerd','glVertexPointerf','glVertexPointeri',
'glVertexPointers',
'glDrawElements','glDrawElementsui','glDrawElementsub','glDrawElementsus',
'glFeedbackBuffer',
'glSelectBuffer',
'glRenderMode',
'glGetPointerv',
'glInterleavedArrays',
'GL_INTERLEAVED_ARRAY_POINTER',
)
# Have to create *new* ctypes wrappers for the platform object!
# We can't just alter the default one since we have different ways of
# calling it
POINTER_FUNCTION_DATA = [
('glColorPointerd', simple.glColorPointer, simple.GL_DOUBLE, simple.GL_COLOR_ARRAY_POINTER, 0, 3),
('glColorPointerf', simple.glColorPointer, simple.GL_FLOAT, simple.GL_COLOR_ARRAY_POINTER, 0, 3),
('glColorPointeri', simple.glColorPointer, simple.GL_INT, simple.GL_COLOR_ARRAY_POINTER, 0, 3),
('glColorPointers', simple.glColorPointer, simple.GL_SHORT, simple.GL_COLOR_ARRAY_POINTER, 0, 3),
('glColorPointerub', simple.glColorPointer, simple.GL_UNSIGNED_BYTE, simple.GL_COLOR_ARRAY_POINTER, 0, 3),
# these data-types are mapped from diff Numeric types
('glColorPointerb', simple.glColorPointer, simple.GL_BYTE, simple.GL_COLOR_ARRAY_POINTER, 0, 3),
('glColorPointerui', simple.glColorPointer, simple.GL_UNSIGNED_INT, simple.GL_COLOR_ARRAY_POINTER, 0, 3),
('glColorPointerus', simple.glColorPointer, simple.GL_UNSIGNED_SHORT, simple.GL_COLOR_ARRAY_POINTER, 0, 3),
('glEdgeFlagPointerb', simple.glEdgeFlagPointer, simple.GL_BYTE, simple.GL_EDGE_FLAG_ARRAY_POINTER, 2, None),
('glIndexPointerd', simple.glIndexPointer, simple.GL_DOUBLE, simple.GL_INDEX_ARRAY_POINTER, 1, None),
('glIndexPointerf', simple.glIndexPointer, simple.GL_FLOAT, simple.GL_INDEX_ARRAY_POINTER, 1, None),
('glIndexPointeri', simple.glIndexPointer, simple.GL_INT, simple.GL_INDEX_ARRAY_POINTER, 1, None),
('glIndexPointerub', simple.glIndexPointer, simple.GL_UNSIGNED_BYTE, simple.GL_INDEX_ARRAY_POINTER, 1, None),
('glIndexPointers', simple.glIndexPointer, simple.GL_SHORT, simple.GL_INDEX_ARRAY_POINTER, 1, None),
# these data-types are mapped from diff Numeric types
('glIndexPointerb', simple.glIndexPointer, simple.GL_BYTE, simple.GL_INDEX_ARRAY_POINTER, 1, None),
('glNormalPointerd', simple.glNormalPointer, simple.GL_DOUBLE, simple.GL_NORMAL_ARRAY_POINTER, 1, None),
('glNormalPointerf', simple.glNormalPointer, simple.GL_FLOAT, simple.GL_NORMAL_ARRAY_POINTER, 1, None),
('glNormalPointeri', simple.glNormalPointer, simple.GL_INT, simple.GL_NORMAL_ARRAY_POINTER, 1, None),
('glNormalPointerb', simple.glNormalPointer, simple.GL_BYTE, simple.GL_NORMAL_ARRAY_POINTER, 1, None),
('glNormalPointers', simple.glNormalPointer, simple.GL_SHORT, simple.GL_NORMAL_ARRAY_POINTER, 1, None),
('glTexCoordPointerd', simple.glTexCoordPointer, simple.GL_DOUBLE, simple.GL_TEXTURE_COORD_ARRAY_POINTER, 0, 2),
('glTexCoordPointerf', simple.glTexCoordPointer, simple.GL_FLOAT, simple.GL_TEXTURE_COORD_ARRAY_POINTER, 0, 2),
('glTexCoordPointeri', simple.glTexCoordPointer, simple.GL_INT, simple.GL_TEXTURE_COORD_ARRAY_POINTER, 0, 2),
('glTexCoordPointerb', simple.glTexCoordPointer, simple.GL_BYTE, simple.GL_TEXTURE_COORD_ARRAY_POINTER, 0, 2),
('glTexCoordPointers', simple.glTexCoordPointer, simple.GL_SHORT, simple.GL_TEXTURE_COORD_ARRAY_POINTER, 0, 2),
('glVertexPointerd', simple.glVertexPointer, simple.GL_DOUBLE, simple.GL_VERTEX_ARRAY_POINTER, 0, 3),
('glVertexPointerf', simple.glVertexPointer, simple.GL_FLOAT, simple.GL_VERTEX_ARRAY_POINTER, 0, 3),
('glVertexPointeri', simple.glVertexPointer, simple.GL_INT, simple.GL_VERTEX_ARRAY_POINTER, 0, 3),
('glVertexPointerb', simple.glVertexPointer, simple.GL_INT, simple.GL_VERTEX_ARRAY_POINTER, 0, 3),
('glVertexPointers', simple.glVertexPointer, simple.GL_SHORT, simple.GL_VERTEX_ARRAY_POINTER, 0, 3),
]
def wrapPointerFunction( name, baseFunction, glType, arrayType,startArgs, defaultSize ):
"""Wrap the given pointer-setting function"""
function= wrapper.wrapper( baseFunction )
assert not getattr( function, 'pyConverters', None ), """Reusing wrappers?"""
if arrayType:
arrayModuleType = arrays.GL_CONSTANT_TO_ARRAY_TYPE[ glType ]
function.setPyConverter( 'pointer', arrays.asArrayType(arrayModuleType) )
else:
function.setPyConverter( 'pointer', arrays.AsArrayOfType('pointer','type') )
function.setCConverter( 'pointer', converters.getPyArgsName( 'pointer' ) )
if 'size' in function.argNames:
function.setPyConverter( 'size' )
function.setCConverter( 'size', arrays.arraySizeOfFirstType(arrayModuleType,defaultSize) )
if 'type' in function.argNames:
function.setPyConverter( 'type' )
function.setCConverter( 'type', glType )
if 'stride' in function.argNames:
function.setPyConverter( 'stride' )
function.setCConverter( 'stride', 0 )
function.setStoreValues( arrays.storePointerType( 'pointer', arrayType ) )
function.setReturnValues( wrapper.returnPyArgument( 'pointer' ) )
return name,function
for name,function in [
wrapPointerFunction( *args )
for args in POINTER_FUNCTION_DATA
]:
globals()[name] = function
del name, function
glVertexPointer = wrapper.wrapper( simple.glVertexPointer ).setPyConverter(
'pointer', arrays.AsArrayOfType( 'pointer', 'type' ),
).setStoreValues(
arrays.storePointerType( 'pointer', simple.GL_VERTEX_ARRAY_POINTER )
).setReturnValues(
wrapper.returnPyArgument( 'pointer' )
)
glTexCoordPointer = wrapper.wrapper( simple.glTexCoordPointer ).setPyConverter(
'pointer', arrays.AsArrayOfType( 'pointer', 'type' ),
).setStoreValues(
arrays.storePointerType( 'pointer', simple.GL_TEXTURE_COORD_ARRAY_POINTER )
).setReturnValues(
wrapper.returnPyArgument( 'pointer' )
)
glNormalPointer = wrapper.wrapper( simple.glNormalPointer ).setPyConverter(
'pointer', arrays.AsArrayOfType( 'pointer', 'type' ),
).setStoreValues(
arrays.storePointerType( 'pointer', simple.GL_NORMAL_ARRAY_POINTER )
).setReturnValues(
wrapper.returnPyArgument( 'pointer' )
)
glIndexPointer = wrapper.wrapper( simple.glIndexPointer ).setPyConverter(
'pointer', arrays.AsArrayOfType( 'pointer', 'type' ),
).setStoreValues(
arrays.storePointerType( 'pointer', simple.GL_INDEX_ARRAY_POINTER )
).setReturnValues(
wrapper.returnPyArgument( 'pointer' )
)
glEdgeFlagPointer = wrapper.wrapper( simple.glEdgeFlagPointer ).setPyConverter(
# XXX type is wrong!
'pointer', arrays.AsArrayTyped( 'pointer', arrays.GLushortArray ),
).setStoreValues(
arrays.storePointerType( 'pointer', simple.GL_EDGE_FLAG_ARRAY_POINTER )
).setReturnValues(
wrapper.returnPyArgument( 'pointer' )
)
glColorPointer = wrapper.wrapper( simple.glColorPointer ).setPyConverter(
'pointer', arrays.AsArrayOfType( 'pointer', 'type' ),
).setStoreValues(
arrays.storePointerType( 'pointer', simple.GL_COLOR_ARRAY_POINTER )
).setReturnValues(
wrapper.returnPyArgument( 'pointer' )
)
glInterleavedArrays = wrapper.wrapper( simple.glInterleavedArrays ).setStoreValues(
arrays.storePointerType( 'pointer', GL_INTERLEAVED_ARRAY_POINTER )
).setReturnValues(
wrapper.returnPyArgument( 'pointer' )
)
glDrawElements = wrapper.wrapper( simple.glDrawElements ).setPyConverter(
'indices', arrays.AsArrayOfType( 'indices', 'type' ),
).setReturnValues(
wrapper.returnPyArgument( 'indices' )
)
def glDrawElementsTyped( type, suffix ):
arrayType = arrays.GL_CONSTANT_TO_ARRAY_TYPE[ type ]
function = wrapper.wrapper(
simple.glDrawElements
).setPyConverter('type').setCConverter(
'type', type
).setPyConverter('count').setCConverter(
'count', arrays.AsArrayTypedSize( 'indices', arrayType ),
).setPyConverter(
'indices', arrays.AsArrayTyped( 'indices', arrayType ),
).setReturnValues(
wrapper.returnPyArgument( 'indices' )
)
return function
for type,suffix in ((simple.GL_UNSIGNED_BYTE,'ub'),(simple.GL_UNSIGNED_INT,'ui'),(simple.GL_UNSIGNED_SHORT,'us')):
globals()['glDrawElements%(suffix)s'%globals()] = glDrawElementsTyped( type,suffix )
del type,suffix,glDrawElementsTyped
# create buffer of given size and return it for future reference
# keep a per-context weakref around to allow us to return the original
# array we returned IFF the user has kept a reference as well...
def glSelectBuffer( size, buffer = None ):
"""Create a selection buffer of the given size
"""
if buffer is None:
buffer = arrays.GLuintArray.zeros( (size,) )
simple.glSelectBuffer( size, buffer )
contextdata.setValue( simple.GL_SELECTION_BUFFER_POINTER, buffer )
return buffer
def glFeedbackBuffer( size, type, buffer = None ):
"""Create a selection buffer of the given size
"""
if buffer is None:
buffer = arrays.GLfloatArray.zeros( (size,) )
simple.glFeedbackBuffer( size, type, buffer )
contextdata.setValue( simple.GL_FEEDBACK_BUFFER_POINTER, buffer )
contextdata.setValue( "GL_FEEDBACK_BUFFER_TYPE", type )
return buffer
def glRenderMode( newMode ):
"""Change to the given rendering mode
If the current mode is GL_FEEDBACK or GL_SELECT, return
the current buffer appropriate to the mode
"""
# must get the current mode to determine operation...
from OpenGL.GL import glGetIntegerv
from OpenGL.GL import selection,feedback
currentMode = glGetIntegerv( simple.GL_RENDER_MODE )
try:
currentMode = currentMode[0]
except (TypeError,ValueError,IndexError), err:
pass
if currentMode in (simple.GL_RENDER,0):
# no array needs to be returned...
return simple.glRenderMode( newMode )
result = simple.glRenderMode( newMode )
# result is now an integer telling us how many elements were copied...
if result < 0:
if currentMode == simple.GL_SELECT:
raise error.GLError(
simple.GL_STACK_OVERFLOW,
"glSelectBuffer too small to hold selection results",
)
elif currentMode == simple.GL_FEEDBACK:
raise error.GLError(
simple.GL_STACK_OVERFLOW,
"glFeedbackBuffer too small to hold selection results",
)
else:
raise error.GLError(
simple.GL_STACK_OVERFLOW,
"Unknown glRenderMode buffer (%s) too small to hold selection results"%(
currentMode,
),
)
# Okay, now that the easy cases are out of the way...
# Do we have a pre-stored pointer about which the user already knows?
context = platform.GetCurrentContext()
if context == 0:
raise error.Error(
"""Returning from glRenderMode without a valid context!"""
)
arrayConstant, wrapperFunction = {
simple.GL_FEEDBACK: (simple.GL_FEEDBACK_BUFFER_POINTER,feedback.parseFeedback),
simple.GL_SELECT: (simple.GL_SELECTION_BUFFER_POINTER, selection.GLSelectRecord.fromArray),
}[ currentMode ]
current = contextdata.getValue( arrayConstant )
# XXX check to see if it's the *same* array we set currently!
if current is None:
current = glGetPointerv( arrayConstant )
# XXX now, can turn the array into the appropriate wrapper type...
if wrapperFunction:
current = wrapperFunction( current, result )
return current
# XXX this belongs in the GL module, not here!
def glGetPointerv( constant ):
"""Retrieve a stored pointer constant"""
# do we have a cached version of the pointer?
# get the base pointer from the underlying operation
vp = ctypes.voidp()
simple.glGetPointerv( constant, ctypes.byref(vp) )
current = contextdata.getValue( constant )
if current is not None:
if arrays.ArrayDatatype.dataPointer( current ) == vp.value:
return current
# XXX should be coercing to the proper type and converting to an array
return vp
|