fix #168 - share OpenGL context between windows under Win32/OpenGL

This commit is contained in:
Vadim Lopatin 2016-01-29 14:58:19 +03:00
parent 3c5573aba0
commit f9780e268e
4 changed files with 156 additions and 22 deletions

View File

@ -102,7 +102,10 @@ extern (C) int UIAppMain(string[] args) {
cam.translation = vec3(0, 0, -5);
scene.activeCamera = cam;
mat4 camMatrix = scene.viewProjectionMatrix;
MeshPart part = new MeshPart();
VertexFormat vfmt = VertexFormat(VertexElementType.POSITION, VertexElementType.COLOR, VertexElementType.TEXCOORD0);
Mesh2 mesh = new Mesh2(vfmt);
mesh.addVertex([1,2,3, 1,1,1,1, 0,0]);
//MeshPart part = new MeshPart();
// show window
window.show();

View File

@ -86,7 +86,11 @@ struct FileFilterEntry {
}
version (Windows) {
__gshared bool SHOW_FILE_DIALOG_IN_POPUP = true;
static if (BACKEND_SDL) {
__gshared bool SHOW_FILE_DIALOG_IN_POPUP = false;
} else {
__gshared bool SHOW_FILE_DIALOG_IN_POPUP = false;
}
} else {
__gshared bool SHOW_FILE_DIALOG_IN_POPUP = false;
}

View File

@ -22,7 +22,21 @@ struct VertexElement {
private ubyte _size;
@property VertexElementType type() const { return _type; }
@property ubyte size() const { return _size; }
this(VertexElementType type, ubyte size) {
this(VertexElementType type, ubyte size = 0) {
if (size == 0) {
switch(type) with (VertexElementType) {
case POSITION:
case NORMAL:
size = 3;
break;
case COLOR:
size = 4;
break;
default:
size = 2;
break;
}
}
_type = type;
_size = size;
}
@ -38,6 +52,14 @@ struct VertexFormat {
foreach(elem; elems)
_vertexSize += elem.size * float.sizeof;
}
/// init from vertex element types, using default sizes for types
this(inout VertexElementType[] types...) {
foreach(t; types) {
VertexElement elem = VertexElement(t);
_elements ~= elem;
_vertexSize += elem.size;
}
}
/// get number of elements
@property int length() const {
return cast(int)_elements.length;
@ -46,10 +68,24 @@ struct VertexFormat {
VertexElement opIndex(int index) const {
return _elements[index];
}
/// returns vertex size in bytes for format
/// returns vertex size in bytes
@property int vertexSize() const {
return _vertexSize * float.sizeof;
}
/// returns vertex size in floats
@property int vertexFloats() const {
return _vertexSize;
}
/// returns true if it's valid vertex format
@property bool isValid() const {
if (!_vertexSize)
return false;
foreach(elem; _elements) {
if (elem.type == VertexElementType.POSITION)
return true;
}
return false;
}
/// compare
bool opEquals(immutable ref VertexFormat fmt) {
if (_vertexSize != fmt._vertexSize)
@ -61,6 +97,46 @@ struct VertexFormat {
}
}
class Mesh2 {
protected VertexFormat _vertexFormat;
protected int _vertexCount;
protected float[] _vertexData;
@property ref const(VertexFormat) vertexFormat() const { return _vertexFormat; }
@property void vertexFormat(VertexFormat format) {
assert(_vertexCount == 0);
_vertexFormat = format;
}
@property int vertexCount() const { return _vertexCount; }
/// adds single vertex
int addVertex(float[] data) {
assert(_vertexFormat.isValid && data.length == _vertexFormat.vertexFloats);
int res = _vertexCount;
_vertexData.assumeSafeAppend();
_vertexData ~= data;
_vertexCount++;
return res;
}
/// adds one or more vertexes
int addVertexes(float[] data) {
assert(_vertexFormat.isValid && (data.length > 0) && (data.length % _vertexFormat.vertexFloats == 0));
int res = _vertexCount;
_vertexData.assumeSafeAppend();
_vertexData ~= data;
_vertexCount += cast(int)(data.length / _vertexFormat.vertexFloats);
return res;
}
this() {
}
this(VertexFormat vertexFormat) {
_vertexFormat = vertexFormat;
}
}
class Mesh {
protected MeshPart[] _parts;
protected int _vertexCount;

View File

@ -156,6 +156,69 @@ static if (ENABLE_OPENGL) {
const uint CUSTOM_MESSAGE_ID = WM_USER + 1;
static if (ENABLE_OPENGL) {
/// Shared opengl context helper
struct SharedGLContext {
import derelict.opengl3.wgl;
HGLRC _hGLRC; // opengl context
HPALETTE _hPalette;
bool _error;
/// Init OpenGL context, if not yet initialized
bool init(HDC hDC) {
if (_hGLRC)
return true;
if (_error)
return false;
if (setupPixelFormat(hDC)) {
_hPalette = setupPalette(hDC);
_hGLRC = wglCreateContext(hDC);
if (_hGLRC) {
bind(hDC);
bool initialized = initGLSupport(false);
unbind(hDC);
if (!initialized) {
uninit();
Log.e("Failed to init OpenGL shaders");
_error = true;
return false;
}
return true;
} else {
_error = true;
return false;
}
} else {
Log.e("Cannot setup pixel format");
_error = true;
return false;
}
}
void uninit() {
if (_hGLRC) {
wglDeleteContext(_hGLRC);
_hGLRC = null;
}
}
/// make this context current for DC
void bind(HDC hDC) {
wglMakeCurrent(hDC, _hGLRC);
}
/// make null context current for DC
void unbind(HDC hDC) {
wglMakeCurrent(hDC, null);
}
void swapBuffers(HDC hDC) {
SwapBuffers(hDC);
}
}
/// OpenGL context to share between windows
__gshared SharedGLContext sharedGLContext;
}
class Win32Window : Window {
Win32Platform _platform;
@ -200,25 +263,11 @@ class Win32Window : Window {
_hInstance, // program instance handle
cast(void*)this); // creation parameters
static if (ENABLE_OPENGL) {
import derelict.opengl3.wgl;
/* initialize OpenGL rendering */
HDC hDC = GetDC(_hwnd);
if (openglEnabled || !_glSupport) {
if (setupPixelFormat(hDC)) {
_hPalette = setupPalette(hDC);
_hGLRC = wglCreateContext(hDC);
if (_hGLRC) {
wglMakeCurrent(hDC, _hGLRC);
useOpengl = initGLSupport(false);
wglMakeCurrent(hDC, null);
}
} else {
Log.e("Pixelformat failed");
// disable GL
useOpengl = false;
}
useOpengl = sharedGLContext.init(hDC);
}
}
}
@ -239,7 +288,7 @@ class Win32Window : Window {
//HDC hdc = BeginPaint(_hwnd, &ps);
//scope(exit) EndPaint(_hwnd, &ps);
HDC hdc = GetDC(_hwnd);
wglMakeCurrent(hdc, _hGLRC);
sharedGLContext.bind(hdc);
//_glSupport = _gl;
glDisable(GL_DEPTH_TEST);
glViewport(0, 0, _dx, _dy);
@ -267,14 +316,15 @@ class Win32Window : Window {
onDraw(buf);
}
buf.afterDrawing();
SwapBuffers(hdc);
wglMakeCurrent(hdc, null);
sharedGLContext.swapBuffers(hdc);
sharedGLContext.unbind(hdc);
destroy(buf);
}
}
~this() {
debug Log.d("Window destructor");
/*
static if (ENABLE_OPENGL) {
import derelict.opengl3.wgl;
if (_hGLRC) {
@ -287,6 +337,7 @@ class Win32Window : Window {
_hGLRC = null;
}
}
*/
if (_hwnd)
DestroyWindow(_hwnd);
_hwnd = null;