2014-01-27 00:02:21 +00:00
//regarding binding and vertex arrays:
//http://stackoverflow.com/questions/8704801/glvertexattribpointer-clarification
//http://stackoverflow.com/questions/9536973/oes-vertex-array-object-and-client-state
//http://www.opengl.org/wiki/Vertex_Specification
//etc
//glBindAttribLocation (programID, 0, "vertexPosition_modelspace");
//for future reference: c# tesselators
//http://www.opentk.com/node/437 (AGG#, codes on Tao forums)
using System ;
2014-01-27 02:06:05 +00:00
using System.Reflection ;
2014-01-27 00:02:21 +00:00
using System.Threading ;
using System.IO ;
using System.Collections.Generic ;
using sd = System . Drawing ;
using sdi = System . Drawing . Imaging ;
using swf = System . Windows . Forms ;
using BizHawk.Bizware.BizwareGL ;
using OpenTK ;
using OpenTK.Graphics ;
using OpenTK.Graphics.OpenGL ;
namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK
{
/// <summary>
/// OpenTK implementation of the BizwareGL.IGL interface.
/// TODO - can we have more than one of these? could be dangerous. such dangerous things to be possibly reconsidered are marked with HAMNUTS
/// TODO - if we have any way of making contexts, we also need a way of freeing it, and then we can cleanup our dictionaries
/// </summary>
public class IGL_TK : IGL
{
static IGL_TK ( )
{
//make sure OpenTK initializes without getting wrecked on the SDL check and throwing an exception to annoy our MDA's
var toolkitOptions = global :: OpenTK . ToolkitOptions . Default ;
toolkitOptions . Backend = PlatformBackend . PreferNative ;
global :: OpenTK . Toolkit . Init ( toolkitOptions ) ;
//NOTE: this throws EGL exceptions anyway. I'm going to ignore it and whine about it later
}
public IGL_TK ( )
{
2014-01-27 05:37:04 +00:00
//make an 'offscreen context' so we can at least do things without having to create a window
2014-01-27 00:02:21 +00:00
OffscreenNativeWindow = new NativeWindow ( ) ;
OffscreenNativeWindow . ClientSize = new sd . Size ( 8 , 8 ) ;
this . GraphicsContext = new GraphicsContext ( GraphicsMode . Default , OffscreenNativeWindow . WindowInfo , 2 , 0 , GraphicsContextFlags . Default ) ;
MakeDefaultCurrent ( ) ;
2014-01-27 05:37:04 +00:00
//this is important for reasons unknown
this . GraphicsContext . LoadAll ( ) ;
//misc initialization
2014-01-27 00:02:21 +00:00
CreateRenderStates ( ) ;
2014-01-27 09:36:18 +00:00
GL . Enable ( EnableCap . Texture2D ) ;
2014-01-30 04:54:02 +00:00
PurgeStateCache ( ) ;
2014-01-27 00:02:21 +00:00
}
2014-01-27 05:37:04 +00:00
void IDisposable . Dispose ( )
{
//TODO - a lot of analysis here
OffscreenNativeWindow . Dispose ( ) ; OffscreenNativeWindow = null ;
GraphicsContext . Dispose ( ) ; GraphicsContext = null ;
}
2014-01-27 00:02:21 +00:00
void IGL . Clear ( ClearBufferMask mask )
{
GL . Clear ( ( global :: OpenTK . Graphics . OpenGL . ClearBufferMask ) mask ) ;
}
2014-01-27 09:45:16 +00:00
void IGL . SetClearColor ( sd . Color color )
2014-01-27 00:02:21 +00:00
{
GL . ClearColor ( color ) ;
}
2014-01-28 19:33:49 +00:00
IGraphicsControl IGL . Internal_CreateGraphicsControl ( )
2014-01-27 00:02:21 +00:00
{
2014-01-28 19:33:49 +00:00
var glc = new GLControlWrapper ( this ) ;
2014-01-27 00:02:21 +00:00
glc . CreateControl ( ) ;
//now the control's context will be current. annoying! fix it.
MakeDefaultCurrent ( ) ;
2014-01-27 02:06:05 +00:00
2014-01-28 19:33:49 +00:00
return glc ;
2014-01-27 00:02:21 +00:00
}
IntPtr IGL . GenTexture ( ) { return new IntPtr ( GL . GenTexture ( ) ) ; }
void IGL . FreeTexture ( IntPtr texHandle ) { GL . DeleteTexture ( texHandle . ToInt32 ( ) ) ; }
IntPtr IGL . GetEmptyHandle ( ) { return new IntPtr ( 0 ) ; }
IntPtr IGL . GetEmptyUniformHandle ( ) { return new IntPtr ( - 1 ) ; }
Shader IGL . CreateFragmentShader ( string source )
{
int sid = GL . CreateShader ( ShaderType . FragmentShader ) ;
CompileShaderSimple ( sid , source ) ;
return new Shader ( this , new IntPtr ( sid ) ) ;
}
Shader IGL . CreateVertexShader ( string source )
{
int sid = GL . CreateShader ( ShaderType . VertexShader ) ;
CompileShaderSimple ( sid , source ) ;
2014-01-27 09:36:18 +00:00
2014-01-27 00:02:21 +00:00
return new Shader ( this , new IntPtr ( sid ) ) ;
}
void IGL . FreeShader ( IntPtr shader ) { GL . DeleteShader ( shader . ToInt32 ( ) ) ; }
class MyBlendState : IBlendState
{
public bool enabled ;
public global :: OpenTK . Graphics . OpenGL . BlendingFactorSrc colorSource ;
public global :: OpenTK . Graphics . OpenGL . BlendEquationMode colorEquation ;
public global :: OpenTK . Graphics . OpenGL . BlendingFactorDest colorDest ;
public global :: OpenTK . Graphics . OpenGL . BlendingFactorSrc alphaSource ;
public global :: OpenTK . Graphics . OpenGL . BlendEquationMode alphaEquation ;
public global :: OpenTK . Graphics . OpenGL . BlendingFactorDest alphaDest ;
2014-01-27 09:45:16 +00:00
public MyBlendState ( bool enabled , BlendingFactorSrc colorSource , BlendEquationMode colorEquation , BlendingFactorDest colorDest ,
BlendingFactorSrc alphaSource , BlendEquationMode alphaEquation , BlendingFactorDest alphaDest )
2014-01-27 00:02:21 +00:00
{
this . enabled = enabled ;
this . colorSource = ( global :: OpenTK . Graphics . OpenGL . BlendingFactorSrc ) colorSource ;
this . colorEquation = ( global :: OpenTK . Graphics . OpenGL . BlendEquationMode ) colorEquation ;
this . colorDest = ( global :: OpenTK . Graphics . OpenGL . BlendingFactorDest ) colorDest ;
this . alphaSource = ( global :: OpenTK . Graphics . OpenGL . BlendingFactorSrc ) alphaSource ;
this . alphaEquation = ( global :: OpenTK . Graphics . OpenGL . BlendEquationMode ) alphaEquation ;
this . alphaDest = ( global :: OpenTK . Graphics . OpenGL . BlendingFactorDest ) alphaDest ;
}
}
2014-01-27 09:45:16 +00:00
IBlendState IGL . CreateBlendState ( BlendingFactorSrc colorSource , BlendEquationMode colorEquation , BlendingFactorDest colorDest ,
BlendingFactorSrc alphaSource , BlendEquationMode alphaEquation , BlendingFactorDest alphaDest )
2014-01-27 00:02:21 +00:00
{
return new MyBlendState ( true , colorSource , colorEquation , colorDest , alphaSource , alphaEquation , alphaDest ) ;
}
void IGL . SetBlendState ( IBlendState rsBlend )
{
var mybs = rsBlend as MyBlendState ;
if ( mybs . enabled )
{
GL . Enable ( EnableCap . Blend ) ;
GL . BlendEquationSeparate ( mybs . colorEquation , mybs . alphaEquation ) ;
GL . BlendFuncSeparate ( mybs . colorSource , mybs . colorDest , mybs . alphaSource , mybs . alphaDest ) ;
}
else GL . Disable ( EnableCap . Blend ) ;
}
IBlendState IGL . BlendNone { get { return _rsBlendNone ; } }
IBlendState IGL . BlendNormal { get { return _rsBlendNormal ; } }
Pipeline IGL . CreatePipeline ( Shader vertexShader , Shader fragmentShader )
{
ErrorCode errcode ;
int pid = GL . CreateProgram ( ) ;
GL . AttachShader ( pid , vertexShader . Id . ToInt32 ( ) ) ;
errcode = GL . GetError ( ) ;
GL . AttachShader ( pid , fragmentShader . Id . ToInt32 ( ) ) ;
errcode = GL . GetError ( ) ;
2014-01-27 00:23:53 +00:00
2014-01-27 00:02:21 +00:00
GL . LinkProgram ( pid ) ;
errcode = GL . GetError ( ) ;
2014-01-27 00:23:53 +00:00
string resultLog = GL . GetProgramInfoLog ( pid ) ;
if ( errcode ! = ErrorCode . NoError )
throw new InvalidOperationException ( "Error creating pipeline (error returned from glLinkProgram): " + errcode + "\r\n\r\n" + resultLog ) ;
2014-01-27 00:02:21 +00:00
2014-01-27 00:23:53 +00:00
int linkStatus ;
GL . GetProgram ( pid , GetProgramParameterName . LinkStatus , out linkStatus ) ;
if ( linkStatus = = 0 )
2014-01-27 19:25:48 +00:00
throw new InvalidOperationException ( "Error creating pipeline (link status false returned from glLinkProgram): " + "\r\n\r\n" + resultLog ) ;
2014-01-27 00:02:21 +00:00
2014-01-28 01:58:54 +00:00
//need to work on validation. apparently there are some weird caveats to glValidate which make it complicated and possibly excuses (barely) the intel drivers' dysfunctional operation
2014-01-28 02:07:50 +00:00
//"A sampler points to a texture unit used by fixed function with an incompatible target"
/ /
//info:
//http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgram.xml
//This function mimics the validation operation that OpenGL implementations must perform when rendering commands are issued while programmable shaders are part of current state.
//glValidateProgram checks to see whether the executables contained in program can execute given the current OpenGL state
//This function is typically useful only during application development.
/ /
//So, this is no big deal. we shouldnt be calling validate right now anyway.
//conclusion: glValidate is very complicated and is of virtually no use unless your draw calls are returning errors and you want to know why
2014-01-28 01:58:54 +00:00
//GL.ValidateProgram(pid);
//errcode = GL.GetError();
//resultLog = GL.GetProgramInfoLog(pid);
//if (errcode != ErrorCode.NoError)
// throw new InvalidOperationException("Error creating pipeline (error returned from glValidateProgram): " + errcode + "\r\n\r\n" + resultLog);
//int validateStatus;
//GL.GetProgram(pid, GetProgramParameterName.ValidateStatus, out validateStatus);
//if (validateStatus == 0)
// throw new InvalidOperationException("Error creating pipeline (validateStatus status false returned from glValidateProgram): " + "\r\n\r\n" + resultLog);
2014-01-27 00:02:21 +00:00
2014-01-27 09:36:18 +00:00
//set the program to active, in case we need to set sampler uniforms on it
GL . UseProgram ( pid ) ;
2014-01-27 00:02:21 +00:00
//get all the uniforms
List < UniformInfo > uniforms = new List < UniformInfo > ( ) ;
int nUniforms ;
int nSamplers = 0 ;
GL . GetProgram ( pid , GetProgramParameterName . ActiveUniforms , out nUniforms ) ;
2014-01-27 09:36:18 +00:00
2014-01-27 00:02:21 +00:00
for ( int i = 0 ; i < nUniforms ; i + + )
{
int size , length ;
ActiveUniformType type ;
var sbName = new System . Text . StringBuilder ( ) ;
GL . GetActiveUniform ( pid , i , 1024 , out length , out size , out type , sbName ) ;
2014-01-27 09:36:18 +00:00
errcode = GL . GetError ( ) ;
2014-01-27 00:02:21 +00:00
string name = sbName . ToString ( ) ;
int loc = GL . GetUniformLocation ( pid , name ) ;
var ui = new UniformInfo ( ) ;
ui . Name = name ;
ui . Handle = new IntPtr ( loc ) ;
//automatically assign sampler uniforms to texture units (and bind them)
bool isSampler = ( type = = ActiveUniformType . Sampler2D ) ;
if ( isSampler )
{
ui . SamplerIndex = nSamplers ;
GL . Uniform1 ( loc , nSamplers ) ;
nSamplers + + ;
}
uniforms . Add ( ui ) ;
}
2014-01-27 09:36:18 +00:00
//deactivate the program, so we dont accidentally use it
GL . UseProgram ( 0 ) ;
2014-01-27 00:02:21 +00:00
return new Pipeline ( this , new IntPtr ( pid ) , uniforms ) ;
}
VertexLayout IGL . CreateVertexLayout ( ) { return new VertexLayout ( this , new IntPtr ( 0 ) ) ; }
void IGL . BindTexture2d ( Texture2d tex )
{
GL . BindTexture ( TextureTarget . Texture2D , tex . Id . ToInt32 ( ) ) ;
}
unsafe void IGL . BindVertexLayout ( VertexLayout layout )
{
2014-01-30 04:54:02 +00:00
sStatePendingVertexLayout = layout ;
2014-01-27 00:02:21 +00:00
}
unsafe void IGL . BindArrayData ( void * pData )
{
2014-01-30 04:54:02 +00:00
MyBindArrayData ( sStatePendingVertexLayout , pData ) ;
2014-01-27 00:02:21 +00:00
}
void IGL . DrawArrays ( PrimitiveType mode , int first , int count )
{
GL . DrawArrays ( ( global :: OpenTK . Graphics . OpenGL . PrimitiveType ) mode , first , count ) ;
}
void IGL . BindPipeline ( Pipeline pipeline )
{
GL . UseProgram ( pipeline . Id . ToInt32 ( ) ) ;
}
2014-01-27 00:38:10 +00:00
unsafe void IGL . SetPipelineUniformMatrix ( PipelineUniform uniform , Matrix4 mat , bool transpose )
2014-01-27 00:02:21 +00:00
{
GL . UniformMatrix4 ( uniform . Id . ToInt32 ( ) , 1 , transpose , ( float * ) & mat ) ;
}
2014-01-27 00:38:10 +00:00
unsafe void IGL . SetPipelineUniformMatrix ( PipelineUniform uniform , ref Matrix4 mat , bool transpose )
2014-01-27 00:02:21 +00:00
{
2014-01-27 00:38:10 +00:00
fixed ( Matrix4 * pMat = & mat )
2014-01-27 00:02:21 +00:00
GL . UniformMatrix4 ( uniform . Id . ToInt32 ( ) , 1 , transpose , ( float * ) pMat ) ;
}
void IGL . SetPipelineUniform ( PipelineUniform uniform , Vector4 value )
{
GL . Uniform4 ( uniform . Id . ToInt32 ( ) , value . X , value . Y , value . Z , value . W ) ;
}
void IGL . SetPipelineUniformSampler ( PipelineUniform uniform , IntPtr texHandle )
{
//set the sampler index into the uniform first
//now bind the texture
2014-01-30 04:54:02 +00:00
if ( sActiveTexture ! = uniform . SamplerIndex )
{
sActiveTexture = uniform . SamplerIndex ;
var selectedUnit = ( TextureUnit ) ( ( int ) TextureUnit . Texture0 + uniform . SamplerIndex ) ;
GL . ActiveTexture ( selectedUnit ) ;
}
2014-01-27 00:02:21 +00:00
GL . BindTexture ( TextureTarget . Texture2D , texHandle . ToInt32 ( ) ) ;
}
void IGL . TexParameter2d ( TextureParameterName pname , int param )
{
GL . TexParameter ( TextureTarget . Texture2D , ( global :: OpenTK . Graphics . OpenGL . TextureParameterName ) pname , param ) ;
}
Texture2d IGL . LoadTexture ( sd . Bitmap bitmap )
{
using ( var bmp = new BitmapBuffer ( bitmap , new BitmapLoadOptions ( ) ) )
return ( this as IGL ) . LoadTexture ( bmp ) ;
}
Texture2d IGL . LoadTexture ( Stream stream )
{
using ( var bmp = new BitmapBuffer ( stream , new BitmapLoadOptions ( ) ) )
return ( this as IGL ) . LoadTexture ( bmp ) ;
}
Texture2d IGL . CreateTexture ( int width , int height )
{
IntPtr id = ( this as IGL ) . GenTexture ( ) ;
return new Texture2d ( this , id , width , height ) ;
}
void IGL . LoadTextureData ( Texture2d tex , BitmapBuffer bmp )
{
sdi . BitmapData bmp_data = bmp . LockBits ( ) ;
try
{
GL . BindTexture ( TextureTarget . Texture2D , tex . Id . ToInt32 ( ) ) ;
GL . TexSubImage2D ( TextureTarget . Texture2D , 0 , 0 , 0 , bmp . Width , bmp . Height , PixelFormat . Bgra , PixelType . UnsignedByte , bmp_data . Scan0 ) ;
}
finally
{
bmp . UnlockBits ( bmp_data ) ;
}
}
2014-01-28 19:33:49 +00:00
void IGL . FreeRenderTarget ( RenderTarget rt )
{
rt . Texture2d . Dispose ( ) ;
GL . DeleteFramebuffer ( rt . Id . ToInt32 ( ) ) ;
}
2014-01-27 09:36:18 +00:00
unsafe RenderTarget IGL . CreateRenderTarget ( int w , int h )
{
//create a texture for it
IntPtr texid = ( this as IGL ) . GenTexture ( ) ;
Texture2d tex = new Texture2d ( this , texid , w , h ) ;
GL . BindTexture ( TextureTarget . Texture2D , texid . ToInt32 ( ) ) ;
GL . TexImage2D ( TextureTarget . Texture2D , 0 , PixelInternalFormat . Rgba , w , h , 0 , PixelFormat . Bgra , PixelType . UnsignedByte , IntPtr . Zero ) ;
tex . SetMagFilter ( TextureMagFilter . Nearest ) ;
tex . SetMinFilter ( TextureMinFilter . Nearest ) ;
//create the FBO
int fbid = GL . GenFramebuffer ( ) ;
GL . BindFramebuffer ( FramebufferTarget . Framebuffer , fbid ) ;
//bind the tex to the FBO
GL . FramebufferTexture2D ( FramebufferTarget . Framebuffer , FramebufferAttachment . ColorAttachment0 , TextureTarget . Texture2D , texid . ToInt32 ( ) , 0 ) ;
//do something, I guess say which colorbuffers are used by the framebuffer
DrawBuffersEnum * buffers = stackalloc DrawBuffersEnum [ 1 ] ;
buffers [ 0 ] = DrawBuffersEnum . ColorAttachment0 ;
GL . DrawBuffers ( 1 , buffers ) ;
if ( GL . CheckFramebufferStatus ( FramebufferTarget . Framebuffer ) ! = FramebufferErrorCode . FramebufferComplete )
throw new InvalidOperationException ( "Error creating framebuffer (at CheckFramebufferStatus)" ) ;
//since we're done configuring unbind this framebuffer, to return to the default
GL . BindFramebuffer ( FramebufferTarget . Framebuffer , 0 ) ;
return new RenderTarget ( this , new IntPtr ( fbid ) , tex ) ;
}
void IGL . BindRenderTarget ( RenderTarget rt )
{
if ( rt = = null )
GL . BindFramebuffer ( FramebufferTarget . Framebuffer , 0 ) ;
else
GL . BindFramebuffer ( FramebufferTarget . Framebuffer , rt . Id . ToInt32 ( ) ) ;
}
2014-01-27 00:02:21 +00:00
Texture2d IGL . LoadTexture ( BitmapBuffer bmp )
{
Texture2d ret = null ;
IntPtr id = ( this as IGL ) . GenTexture ( ) ;
try
{
ret = new Texture2d ( this , id , bmp . Width , bmp . Height ) ;
GL . BindTexture ( TextureTarget . Texture2D , id . ToInt32 ( ) ) ;
//picking a color order that matches doesnt seem to help, any. maybe my driver is accelerating it, or maybe it isnt a big deal. but its something to study on another day
GL . TexImage2D ( TextureTarget . Texture2D , 0 , PixelInternalFormat . Rgba , bmp . Width , bmp . Height , 0 , PixelFormat . Bgra , PixelType . UnsignedByte , IntPtr . Zero ) ;
( this as IGL ) . LoadTextureData ( ret , bmp ) ;
}
catch
{
( this as IGL ) . FreeTexture ( id ) ;
throw ;
}
//set default filtering.. its safest to do this always
ret . SetFilterNearest ( ) ;
return ret ;
}
Texture2d IGL . LoadTexture ( string path )
{
using ( var fs = new FileStream ( path , FileMode . Open , FileAccess . Read , FileShare . Read ) )
return ( this as IGL ) . LoadTexture ( fs ) ;
}
2014-01-27 00:38:10 +00:00
Matrix4 IGL . CreateGuiProjectionMatrix ( int w , int h )
2014-01-27 00:02:21 +00:00
{
2014-01-27 00:38:10 +00:00
Matrix4 ret = Matrix4 . Identity ;
2014-01-27 00:02:21 +00:00
ret . M11 = 2.0f / ( float ) w ;
ret . M22 = 2.0f / ( float ) h ;
return ret ;
}
2014-01-27 00:38:10 +00:00
Matrix4 IGL . CreateGuiViewMatrix ( int w , int h )
2014-01-27 00:02:21 +00:00
{
2014-01-27 00:38:10 +00:00
Matrix4 ret = Matrix4 . Identity ;
2014-01-27 00:02:21 +00:00
ret . M22 = - 1.0f ;
ret . M41 = - w * 0.5f ; // -0.5f;
ret . M42 = h * 0.5f ; // +0.5f;
return ret ;
}
void IGL . SetViewport ( int x , int y , int width , int height )
{
GL . Viewport ( x , y , width , height ) ;
2014-01-27 09:36:18 +00:00
}
void IGL . SetViewport ( int width , int height )
{
GL . Viewport ( 0 , 0 , width , height ) ;
2014-01-27 00:02:21 +00:00
}
void IGL . SetViewport ( swf . Control control )
{
var r = control . ClientRectangle ;
GL . Viewport ( r . Left , r . Top , r . Width , r . Height ) ;
}
//------------------
INativeWindow OffscreenNativeWindow ;
IGraphicsContext GraphicsContext ;
//---------------
//my utility methods
GLControl CastControl ( swf . Control swfControl )
{
GLControl glc = swfControl as GLControl ;
if ( glc = = null )
throw new ArgumentException ( "Argument isn't a control created by the IGL interface" , "glControl" ) ;
return glc ;
}
void CompileShaderSimple ( int sid , string source )
{
2014-01-27 18:30:28 +00:00
ErrorCode errcode ;
2014-01-27 00:02:21 +00:00
GL . ShaderSource ( sid , source ) ;
2014-01-27 18:30:28 +00:00
errcode = GL . GetError ( ) ;
if ( errcode ! = ErrorCode . NoError )
throw new InvalidOperationException ( "Error compiling shader (ShaderSource)" + errcode ) ;
2014-01-27 00:02:21 +00:00
GL . CompileShader ( sid ) ;
errcode = GL . GetError ( ) ;
2014-01-27 18:30:28 +00:00
string resultLog = GL . GetShaderInfoLog ( sid ) ;
if ( errcode ! = ErrorCode . NoError )
throw new InvalidOperationException ( "Error compiling shader (CompileShader)" + errcode + "\r\n\r\n" + resultLog ) ;
2014-01-27 00:02:21 +00:00
int n ;
GL . GetShader ( sid , ShaderParameter . CompileStatus , out n ) ;
2014-01-27 18:30:28 +00:00
if ( n = = 0 )
throw new InvalidOperationException ( "Error compiling shader (CompileShader)" + "\r\n\r\n" + resultLog ) ;
2014-01-27 00:02:21 +00:00
}
2014-01-30 04:54:02 +00:00
2014-01-27 00:02:21 +00:00
void UnbindVertexAttributes ( )
{
//HAMNUTS:
//its not clear how many bindings we'll have to disable before we can enable the ones we need..
//so lets just disable the ones we remember we have bound
2014-01-30 04:54:02 +00:00
var currBindings = sVertexAttribEnables ;
2014-01-27 00:02:21 +00:00
foreach ( var index in currBindings )
GL . DisableVertexAttribArray ( index ) ;
currBindings . Clear ( ) ;
}
unsafe void MyBindArrayData ( VertexLayout layout , void * pData )
{
UnbindVertexAttributes ( ) ;
//HAMNUTS (continued)
2014-01-30 04:54:02 +00:00
var currBindings = sVertexAttribEnables ;
sStateCurrentVertexLayout = sStatePendingVertexLayout ;
2014-01-27 00:02:21 +00:00
foreach ( var kvp in layout . Items )
{
GL . VertexAttribPointer ( kvp . Key , kvp . Value . Components , ( VertexAttribPointerType ) kvp . Value . AttribType , kvp . Value . Normalized , kvp . Value . Stride , new IntPtr ( pData ) + kvp . Value . Offset ) ;
GL . EnableVertexAttribArray ( kvp . Key ) ;
currBindings . Add ( kvp . Key ) ;
}
}
2014-01-28 19:33:49 +00:00
internal void MakeDefaultCurrent ( )
2014-01-27 00:02:21 +00:00
{
2014-01-30 04:54:02 +00:00
MakeContextCurrent ( this . GraphicsContext , OffscreenNativeWindow . WindowInfo ) ;
2014-01-27 00:02:21 +00:00
}
2014-01-28 19:33:49 +00:00
internal void MakeContextCurrent ( IGraphicsContext context , global :: OpenTK . Platform . IWindowInfo windowInfo )
2014-01-27 00:02:21 +00:00
{
context . MakeCurrent ( windowInfo ) ;
2014-01-30 04:54:02 +00:00
PurgeStateCache ( ) ;
2014-01-27 00:02:21 +00:00
}
void CreateRenderStates ( )
{
2014-01-27 09:45:16 +00:00
_rsBlendNone = new MyBlendState ( false , BlendingFactorSrc . One , BlendEquationMode . FuncAdd , BlendingFactorDest . Zero , BlendingFactorSrc . One , BlendEquationMode . FuncAdd , BlendingFactorDest . Zero ) ;
_rsBlendNormal = new MyBlendState ( true ,
BlendingFactorSrc . SrcAlpha , BlendEquationMode . FuncAdd , BlendingFactorDest . OneMinusSrcAlpha ,
BlendingFactorSrc . One , BlendEquationMode . FuncAdd , BlendingFactorDest . Zero ) ;
2014-01-27 00:02:21 +00:00
}
MyBlendState _rsBlendNone , _rsBlendNormal ;
2014-01-30 04:54:02 +00:00
//state caches
int sActiveTexture ;
VertexLayout sStateCurrentVertexLayout ;
VertexLayout sStatePendingVertexLayout ;
HashSet < int > sVertexAttribEnables = new HashSet < int > ( ) ;
void PurgeStateCache ( )
{
sStateCurrentVertexLayout = null ;
sStatePendingVertexLayout = null ;
sVertexAttribEnables . Clear ( ) ;
sActiveTexture = - 1 ;
}
2014-01-27 00:02:21 +00:00
} //class IGL_TK
}