Skip to content

Instantly share code, notes, and snippets.

@PtrMan
Created October 22, 2015 16:25
Show Gist options
  • Save PtrMan/7880dda96d050f053727 to your computer and use it in GitHub Desktop.
Save PtrMan/7880dda96d050f053727 to your computer and use it in GitHub Desktop.
module Client.OpenGlContext;
import Client.opengl.gl;
import Client.opengl.glExt;
const bool WINDOWS = true;
// just for debugging
import std.stdio : writeln;
static if( WINDOWS )
{
import core.sys.windows.windows;
import std.c.string : memset;
import std.string;
// WINAPI
extern (Windows)
{
int ChoosePixelFormat(HDC, PIXELFORMATDESCRIPTOR*);
BOOL SwapBuffers(HDC);
int DescribePixelFormat(
HDC hdc,
int iPixelFormat,
UINT nBytes,
PIXELFORMATDESCRIPTOR *ppfd
);
BOOL wglDeleteContext(HGLRC hglrc);
BOOL wglMakeCurrent(HDC hdc, HGLRC hglrc);
HDC wglGetCurrentDC();
HGLRC wglCreateContext(HDC);
void *wglGetProcAddress(LPCSTR);
}
// WINAPI WinGdi.h
const uint PFD_DRAW_TO_WINDOW = 0x00000004;
const uint PFD_SUPPORT_OPENGL = 0x00000020;
const uint PFD_DOUBLEBUFFER = 0x00000001;
const uint PFD_TYPE_RGBA = 0;
const uint PFD_MAIN_PLANE = 0;
}
class OpenGlContext
{
alias extern(Windows) void function(uint n, uint *framebuffers) TYPEGLGENFRAMEBUFFERSEXT;
alias extern(Windows) void function(uint n, uint *renderbuffers) TYPEGLGENRENDERBUFFERSEXT;
alias extern(Windows) void function(uint target, uint framebuffer) TYPEGLBINDFRAMEBUFFEREXT;
alias extern(Windows) void function(uint target, uint attachment, uint textarget, uint texture, int level) TYPEGLFRAMEBUFFERTEXTURE2DEXT;
alias extern(Windows) void function(uint target, uint renderbuffer) TYPEGLBINDRENDERBUFFEREXT;
alias extern(Windows) void function(uint target, uint internalformat, uint width, uint height) TYPEGLRENDERBUFFERSTORAGEEXT;
alias extern(Windows) void function(uint target, uint attachment, uint renderbuffertarget, uint renderbuffer) TYPEGLFRAMEBUFFERRENDERBUFFEREXT;
alias extern(Windows) uint function(uint target) TYPEGLCHECKFRAMEBUFFERSTATUSEXT;
public static TYPEGLGENFRAMEBUFFERSEXT glGenFramebuffersEXT;
public static TYPEGLGENRENDERBUFFERSEXT glGenRenderbuffersEXT;
public static TYPEGLBINDFRAMEBUFFEREXT glBindFramebufferEXT;
public static TYPEGLFRAMEBUFFERTEXTURE2DEXT glFramebufferTexture2DEXT;
public static TYPEGLBINDRENDERBUFFEREXT glBindRenderbufferEXT;
public static TYPEGLRENDERBUFFERSTORAGEEXT glRenderbufferStorageEXT;
public static TYPEGLFRAMEBUFFERRENDERBUFFEREXT glFramebufferRenderbufferEXT;
public static TYPEGLCHECKFRAMEBUFFERSTATUSEXT glCheckFramebufferStatusEXT;
/*
alias nothrow BOOL function(HGLRC hglrc) wglDeleteContextType;
alias nothrow BOOL function(HDC hdc, HGLRC hglrc) wglMakeCurrentType;
alias nothrow HDC function() wglGetCurrentDCType;
*/
static if( WINDOWS )
{
private HDC Hdc;
private HWND Hwnd;
private HGLRC Glrc;
private HMODULE ModuleOpenGl;
/*
private static wglDeleteContextType wglDeleteContext;
private static wglMakeCurrentType wglMakeCurrent;
private static wglGetCurrentDCType wglGetCurrentDC;
*/ }
static if( WINDOWS )
{
bool initForWindows(HWND Hwnd)
{
PIXELFORMATDESCRIPTOR PixelDescriptor;
int FormatInfo;
BOOL ReturnBOOL;
// get all addresses
string OpenGlDll = "opengl32.dll";
string wglCreateContextStr = "wglCreateContext";
string wglDeleteContextStr = "wglDeleteContext";
string wglMakeCurrentStr = "wglMakeCurrent";
string wglGetCurrentDCStr = "wglGetCurrentDC";
/*
this.ModuleOpenGl = LoadLibraryA(cast(LPCSTR)(OpenGlDll.toStringz));
if( this.ModuleOpenGl is null )
{
return false;
}
alias nothrow HGLRC function(HDC) wglCreateContextType;
wglCreateContextType wglCreateContext;
wglCreateContext = cast(wglCreateContextType)GetProcAddress(this.ModuleOpenGl, cast(LPCSTR)wglCreateContextStr.toStringz);
wglDeleteContext = cast(wglDeleteContextType)GetProcAddress(this.ModuleOpenGl, cast(LPCSTR)wglDeleteContextStr.toStringz);
wglMakeCurrent = cast(wglMakeCurrentType) GetProcAddress(this.ModuleOpenGl, cast(LPCSTR)wglMakeCurrentStr.toStringz);
wglGetCurrentDC = cast(wglGetCurrentDCType) GetProcAddress(this.ModuleOpenGl, cast(LPCSTR)wglGetCurrentDCStr.toStringz);
*/
this.Hwnd = Hwnd;
this.Hdc = GetDC(Hwnd);
if( this.Hdc is null )
{
return false;
}
// enumerate
/*
PixelDescriptor.nSize = PIXELFORMATDESCRIPTOR.sizeof;
uint NumFormats = DescribePixelFormat( this.Hdc, 1, 0, null);
for( int i = 1; i <= NumFormats; i++ )
{
DescribePixelFormat(this.Hdc, i, PixelDescriptor.nSize, &PixelDescriptor );
if ( (PixelDescriptor.dwFlags & ( PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER ) ) == (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER) &&
PixelDescriptor.iPixelType == PFD_TYPE_RGBA && PixelDescriptor.iLayerType == PFD_MAIN_PLANE)
{
writeln("found mode i=", i);
writeln("ColorBits", PixelDescriptor.cColorBits);
writeln("DephBits", PixelDescriptor.cDepthBits);
}
}*/
memset(&PixelDescriptor, 0, PIXELFORMATDESCRIPTOR.sizeof);
PixelDescriptor.nSize = PIXELFORMATDESCRIPTOR.sizeof;
PixelDescriptor.nVersion = 1;
PixelDescriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
PixelDescriptor.iPixelType = PFD_TYPE_RGBA;
PixelDescriptor.cColorBits = 32;
PixelDescriptor.cDepthBits = 24;
PixelDescriptor.cAlphaBits = 8;
PixelDescriptor.iLayerType = PFD_MAIN_PLANE;
FormatInfo = ChoosePixelFormat(this.Hdc, &PixelDescriptor);
writeln("FormatInfo", FormatInfo);
if( !FormatInfo )
{
return false;
}
int ReturnInt = DescribePixelFormat(
this.Hdc,
FormatInfo,
PIXELFORMATDESCRIPTOR.sizeof,
&PixelDescriptor
);
if( !ReturnInt )
{
return false;
}
ReturnBOOL = SetPixelFormat(this.Hdc, FormatInfo, &PixelDescriptor);
if( !ReturnBOOL )
{
return false;
}
writeln(this.Hdc);
//ReturnBOOL = wglMakeCurrent(this.Hdc, null);
//writeln("... ", ReturnBOOL);
//return false;
this.Glrc = wglCreateContext(this.Hdc);
if( this.Glrc is null )
{
return false;
}
ReturnBOOL = wglMakeCurrent(this.Hdc, this.Glrc);
if( !ReturnBOOL )
{
return false;
}
// check for extension
immutable(char) *StringPtr = glGetString(GL_EXTENSIONS);
char[] String;
uint i = 0;
for(;;)
{
if( StringPtr[i] == 0 )
{
break;
}
String ~= StringPtr[i];
i++;
}
// find substring in string
bool Found = false;
for( i = 0; i < String.length-25; i++ )
{
//writeln("GL_EXT_FRAMEBUFFER_OBJECT".length);
//writeln(String[i..i+25].length);
if( String[i..i+25] == "GL_EXT_framebuffer_object" )
{
Found = true;
break;
}
}
if( !Found )
{
// error, GL_EXT_framebuffer_object not supported
return false;
}
glGenFramebuffersEXT = cast(TYPEGLGENFRAMEBUFFERSEXT)wglGetProcAddress("glGenFramebuffersEXT");
glGenRenderbuffersEXT = cast(TYPEGLGENRENDERBUFFERSEXT)wglGetProcAddress("glGenRenderbuffersEXT");
glBindFramebufferEXT = cast(TYPEGLBINDFRAMEBUFFEREXT)wglGetProcAddress("glBindFramebufferEXT");
glFramebufferTexture2DEXT = cast(TYPEGLFRAMEBUFFERTEXTURE2DEXT)wglGetProcAddress("glFramebufferTexture2DEXT");
glBindRenderbufferEXT = cast(TYPEGLBINDRENDERBUFFEREXT)wglGetProcAddress("glBindRenderbufferEXT");
glRenderbufferStorageEXT = cast(TYPEGLRENDERBUFFERSTORAGEEXT)wglGetProcAddress("glRenderbufferStorageEXT");
glFramebufferRenderbufferEXT = cast(TYPEGLFRAMEBUFFERRENDERBUFFEREXT)wglGetProcAddress("glFramebufferRenderbufferEXT");
glCheckFramebufferStatusEXT = cast(TYPEGLCHECKFRAMEBUFFERSTATUSEXT)wglGetProcAddress("glCheckFramebufferStatusEXT");
// Shader
glExt.glCreateProgram = cast(glExt.TYPEGLCREATEPROGRAM)wglGetProcAddress("glCreateProgram");
glExt.glUseProgram = cast(glExt.TYPEGLUSEPROGRAM)wglGetProcAddress("glUseProgram");
glExt.glAttachShader = cast(glExt.TYPEGLATTACHSHADER)wglGetProcAddress("glAttachShader");
glExt.glLinkProgram = cast(glExt.TYPEGLLINKPROGRAM)wglGetProcAddress("glLinkProgram");
glExt.glBindAttribLocation = cast(glExt.TYPEGLBINDATTRIBLOCATION)wglGetProcAddress("glBindAttribLocation");
glExt.glBindFragDataLocation = cast(glExt.TYPEGLBINDFRAGDATALOCATION)wglGetProcAddress("glBindFragDataLocation");
glExt.glGetUniformLocation = cast(glExt.TYPEGLGETUNIFORMLOCATION)wglGetProcAddress("glGetUniformLocation");
glExt.glGetProgramiv = cast(glExt.TYPEGLUEIP)wglGetProcAddress("glGetProgramiv");
glExt.glGetShaderiv = cast(glExt.TYPEGLUEIP)wglGetProcAddress("glGetShaderiv");
glExt.glGetProgramInfoLog = cast(glExt.TYPEGLUSISIPCP)wglGetProcAddress("glGetProgramInfoLog");
glExt.glGetShaderInfoLog = cast(glExt.TYPEGLUSISIPCP)wglGetProcAddress("glGetShaderInfoLog");
glExt.glCreateShader = cast(glExt.TYPEGLCREATESHADER)wglGetProcAddress("glCreateShader");
glExt.glShaderSource = cast(glExt.TYPEGLSHADERSOURCE)wglGetProcAddress("glShaderSource");
glExt.glCompileShader = cast(glExt.TYPEGLU)wglGetProcAddress("glCompileShader");
glExt.glUniformMatrix4fv = cast(glExt.TYPEGLUNIFORMMATRIX4FV)wglGetProcAddress("glUniformMatrix4fv");
// Buffer
glExt.glGenVertexArrays = cast(glExt.TYPEGLGENVERTEXARRAYS)wglGetProcAddress("glGenVertexArrays");
glExt.glBindVertexArray = cast(glExt.TYPEGLU)wglGetProcAddress("glBindVertexArray");
glExt.glVertexAttribPointer = cast(glExt.TYPEGLVERTEXATTRIBPOINTER)wglGetProcAddress("glVertexAttribPointer");
glExt.glEnableVertexAttribArray = cast(glExt.TYPEGLU)wglGetProcAddress("glEnableVertexAttribArray");
glExt.glDeleteVertexArrays = cast(glExt.TYPEGLDELETEVERTEXARRAYS)wglGetProcAddress("glDeleteVertexArrays");
glExt.glBindBuffer = cast(glExt.TYPEGLBINDBUFFER)wglGetProcAddress("glBindBuffer");
glExt.glBufferData = cast(glExt.TYPEGLBUFFERDATA)wglGetProcAddress("glBufferData");
glExt.glGenBuffers = cast(glExt.TYPEGLGENBUFFERS)wglGetProcAddress("glGenBuffers");
glExt.glDeleteBuffers = cast(glExt.TYPEGLDELETEBUFFERS)wglGetProcAddress("glDeleteBuffers");
if(
glExt.glCreateProgram is null ||
glExt.glUseProgram is null ||
glExt.glAttachShader is null ||
glExt.glLinkProgram is null ||
glExt.glBindAttribLocation is null ||
glExt.glBindFragDataLocation is null ||
glExt.glGetUniformLocation is null ||
glExt.glGetProgramiv is null ||
glExt.glGetShaderiv is null ||
glExt.glGetProgramInfoLog is null ||
glExt.glGetShaderInfoLog is null ||
glExt.glCreateShader is null ||
glExt.glShaderSource is null ||
glExt.glCompileShader is null ||
glExt.glUniformMatrix4fv is null ||
glExt.glGenVertexArrays is null ||
glExt.glBindVertexArray is null ||
glExt.glVertexAttribPointer is null ||
glExt.glEnableVertexAttribArray is null ||
glExt.glDeleteVertexArrays is null ||
glExt.glBindBuffer is null ||
glExt.glBufferData is null ||
glExt.glGenBuffers is null ||
glExt.glDeleteBuffers is null
)
{
// error, couldn't find a symbol
return false;
}
return true;
}
}
void deinit()
{
static if( WINDOWS )
{
wglMakeCurrent(null, null);
wglDeleteContext(this.Glrc);
ReleaseDC(this.Hwnd, this.Hdc);
FreeLibrary(this.ModuleOpenGl);
}
}
void swapBuffers()
{
static if( WINDOWS )
{
SwapBuffers(this.Hdc);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment