fix OpenGL support in additional windows under pure win32 - issue #27

This commit is contained in:
Vadim Lopatin 2015-01-12 13:44:46 +03:00
parent 359ac8d0ba
commit 83b4e98390
6 changed files with 393 additions and 365 deletions

View File

@ -66,7 +66,7 @@
<debuglevel>0</debuglevel> <debuglevel>0</debuglevel>
<debugids>DebugFocus</debugids> <debugids>DebugFocus</debugids>
<versionlevel>0</versionlevel> <versionlevel>0</versionlevel>
<versionids>USE_OPENGL Unicode</versionids> <versionids>USE_OPENGL USE_SDL Unicode</versionids>
<dump_source>0</dump_source> <dump_source>0</dump_source>
<mapverbosity>0</mapverbosity> <mapverbosity>0</mapverbosity>
<createImplib>1</createImplib> <createImplib>1</createImplib>
@ -89,7 +89,6 @@
<resfile /> <resfile />
<exefile>$(OutDir)\$(ProjectName).lib</exefile> <exefile>$(OutDir)\$(ProjectName).lib</exefile>
<useStdLibPath>1</useStdLibPath> <useStdLibPath>1</useStdLibPath>
<cRuntime>2</cRuntime>
<additionalOptions /> <additionalOptions />
<preBuildCommand /> <preBuildCommand />
<postBuildCommand /> <postBuildCommand />
@ -184,7 +183,6 @@
<resfile /> <resfile />
<exefile>$(OutDir)\$(ProjectName).lib</exefile> <exefile>$(OutDir)\$(ProjectName).lib</exefile>
<useStdLibPath>1</useStdLibPath> <useStdLibPath>1</useStdLibPath>
<cRuntime>1</cRuntime>
<additionalOptions /> <additionalOptions />
<preBuildCommand /> <preBuildCommand />
<postBuildCommand /> <postBuildCommand />

View File

@ -66,7 +66,7 @@
<debuglevel>0</debuglevel> <debuglevel>0</debuglevel>
<debugids /> <debugids />
<versionlevel>0</versionlevel> <versionlevel>0</versionlevel>
<versionids>USE_OPENGL Unicode</versionids> <versionids>USE_OPENGL USE_SDL Unicode</versionids>
<dump_source>0</dump_source> <dump_source>0</dump_source>
<mapverbosity>3</mapverbosity> <mapverbosity>3</mapverbosity>
<createImplib>0</createImplib> <createImplib>0</createImplib>
@ -89,7 +89,6 @@
<resfile /> <resfile />
<exefile>$(OutDir)\$(ProjectName).exe</exefile> <exefile>$(OutDir)\$(ProjectName).exe</exefile>
<useStdLibPath>1</useStdLibPath> <useStdLibPath>1</useStdLibPath>
<cRuntime>2</cRuntime>
<additionalOptions>-profile</additionalOptions> <additionalOptions>-profile</additionalOptions>
<preBuildCommand /> <preBuildCommand />
<postBuildCommand /> <postBuildCommand />
@ -184,7 +183,6 @@
<resfile /> <resfile />
<exefile>$(OutDir)\$(ProjectName).exe</exefile> <exefile>$(OutDir)\$(ProjectName).exe</exefile>
<useStdLibPath>1</useStdLibPath> <useStdLibPath>1</useStdLibPath>
<cRuntime>1</cRuntime>
<additionalOptions /> <additionalOptions />
<preBuildCommand /> <preBuildCommand />
<postBuildCommand /> <postBuildCommand />

View File

@ -62,9 +62,9 @@ class GLDrawBuf : DrawBuf {
/// reserved for hardware-accelerated drawing - ends drawing batch /// reserved for hardware-accelerated drawing - ends drawing batch
override void afterDrawing() { override void afterDrawing() {
setOrthoProjection(_dx, _dy); glSupport.setOrthoProjection(_dx, _dy);
_scene.draw(); _scene.draw();
flushGL(); glSupport.flushGL();
destroy(_scene); destroy(_scene);
_scene = null; _scene = null;
} }
@ -244,7 +244,7 @@ private class GLImageCache {
_drawbuf = null; _drawbuf = null;
} }
if (_textureId != 0) { if (_textureId != 0) {
deleteTexture(_textureId); glSupport.deleteTexture(_textureId);
_textureId = 0; _textureId = 0;
} }
} }
@ -254,14 +254,14 @@ private class GLImageCache {
return; // no draw buffer!!! return; // no draw buffer!!!
if (_textureId == 0) { if (_textureId == 0) {
//CRLog::debug("updateTexture - new texture"); //CRLog::debug("updateTexture - new texture");
_textureId = genTexture(); _textureId = glSupport.genTexture();
if (!_textureId) if (!_textureId)
return; return;
} }
//CRLog::debug("updateTexture - setting image %dx%d", _drawbuf.width, _drawbuf.height); //CRLog::debug("updateTexture - setting image %dx%d", _drawbuf.width, _drawbuf.height);
uint * pixels = _drawbuf.scanLine(0); uint * pixels = _drawbuf.scanLine(0);
if (!setTextureImage(_textureId, _drawbuf.width, _drawbuf.height, cast(ubyte*)pixels)) { if (!glSupport.setTextureImage(_textureId, _drawbuf.width, _drawbuf.height, cast(ubyte*)pixels)) {
deleteTexture(_textureId); glSupport.deleteTexture(_textureId);
_textureId = 0; _textureId = 0;
return; return;
} }
@ -339,7 +339,7 @@ private class GLImageCache {
if (_needUpdateTexture) if (_needUpdateTexture)
updateTexture(); updateTexture();
if (_textureId != 0) { if (_textureId != 0) {
if (!isTexture(_textureId)) { if (!glSupport.isTexture(_textureId)) {
Log.e("Invalid texture ", _textureId); Log.e("Invalid texture ", _textureId);
return; return;
} }
@ -371,12 +371,12 @@ private class GLImageCache {
dstrc.bottom -= clip.bottom; dstrc.bottom -= clip.bottom;
} }
if (!dstrc.empty) if (!dstrc.empty)
drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, srcrc.width() != dstrc.width() || srcrc.height() != dstrc.height()); glSupport.drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, srcrc.width() != dstrc.width() || srcrc.height() != dstrc.height());
//drawColorAndTextureRect(vertices, texcoords, color, _textureId); //drawColorAndTextureRect(vertices, texcoords, color, _textureId);
if (rotationAngle) { if (rotationAngle) {
// unset rotation // unset rotation
setRotation(rx, ry, 0); glSupport.setRotation(rx, ry, 0);
// glMatrixMode(GL_PROJECTION); // glMatrixMode(GL_PROJECTION);
// glPopMatrix(); // glPopMatrix();
// checkError("pop matrix"); // checkError("pop matrix");
@ -576,7 +576,7 @@ private class GLGlyphCache {
_drawbuf = null; _drawbuf = null;
} }
if (_textureId != 0) { if (_textureId != 0) {
deleteTexture(_textureId); glSupport.deleteTexture(_textureId);
_textureId = 0; _textureId = 0;
} }
} }
@ -589,7 +589,7 @@ private class GLGlyphCache {
return; // no draw buffer!!! return; // no draw buffer!!!
if (_textureId == 0) { if (_textureId == 0) {
//CRLog::debug("updateTexture - new texture"); //CRLog::debug("updateTexture - new texture");
_textureId = genTexture(); _textureId = glSupport.genTexture();
if (!_textureId) if (!_textureId)
return; return;
} }
@ -600,8 +600,8 @@ private class GLGlyphCache {
_rgbaBuffer.length = len; _rgbaBuffer.length = len;
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
_rgbaBuffer[i] = ((cast(uint)pixels[i]) << 24) | 0x00FFFFFF; _rgbaBuffer[i] = ((cast(uint)pixels[i]) << 24) | 0x00FFFFFF;
if (!setTextureImage(_textureId, _drawbuf.width, _drawbuf.height, cast(ubyte*)_rgbaBuffer.ptr)) { if (!glSupport.setTextureImage(_textureId, _drawbuf.width, _drawbuf.height, cast(ubyte*)_rgbaBuffer.ptr)) {
deleteTexture(_textureId); glSupport.deleteTexture(_textureId);
_textureId = 0; _textureId = 0;
return; return;
} }
@ -667,7 +667,7 @@ private class GLGlyphCache {
if (_needUpdateTexture) if (_needUpdateTexture)
updateTexture(); updateTexture();
if (_textureId != 0) { if (_textureId != 0) {
if (!isTexture(_textureId)) { if (!glSupport.isTexture(_textureId)) {
Log.e("Invalid texture ", _textureId); Log.e("Invalid texture ", _textureId);
return; return;
} }
@ -693,7 +693,7 @@ private class GLGlyphCache {
} }
if (!dstrc.empty) { if (!dstrc.empty) {
//Log.d("drawing glyph with color ", color); //Log.d("drawing glyph with color ", color);
drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, false); glSupport.drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, false);
} }
} }
@ -818,7 +818,7 @@ class SolidRectSceneItem : SceneItem {
_color = color; _color = color;
} }
override void draw() { override void draw() {
drawSolidFillRect(_rc, _color, _color, _color, _color); glSupport.drawSolidFillRect(_rc, _color, _color, _color, _color);
} }
} }

View File

@ -53,7 +53,8 @@ static this() {
0x0505: "GL_OUT_OF_MEMORY" 0x0505: "GL_OUT_OF_MEMORY"
]; ];
} }
/* Convenient wrapper around glGetError() /**
* Convenient wrapper around glGetError()
* TODO use one of the DEBUG extensions instead * TODO use one of the DEBUG extensions instead
*/ */
bool checkError(string context="", string file=__FILE__, int line=__LINE__) bool checkError(string context="", string file=__FILE__, int line=__LINE__)
@ -67,7 +68,427 @@ bool checkError(string context="", string file=__FILE__, int line=__LINE__)
return false; return false;
} }
immutable float Z_2D = -2.0f;
class GLProgram {
@property abstract string vertexSource();
@property abstract string fragmentSource();
protected GLuint vertexShader;
protected GLuint fragmentShader;
protected GLuint program;
protected bool initialized;
protected bool error;
protected string glslversion;
this() {
}
private GLuint compileShader(string src, GLuint type) {
import core.stdc.stdlib;
import std.string;
Log.d("compileShader glsl=", glslversion, " code: ", src);
GLuint shader = glCreateShader(type);//GL_VERTEX_SHADER
const char * psrc = src.toStringz;
GLuint len = cast(uint)src.length;
glShaderSource(shader, 1, &psrc, cast(const(int)*)&len);
glCompileShader(shader);
GLint compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (compiled) {
// compiled successfully
return shader;
} else {
GLint blen = 0;
GLsizei slen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH , &blen);
if (blen > 1)
{
GLchar[] msg = new GLchar[blen + 1];
GLchar * pmsg = &msg[0];
glGetShaderInfoLog(shader, blen, &slen, pmsg);
Log.d("Shader compilation error: ", fromStringz(pmsg));
}
return 0;
}
}
bool compile() {
glslversion = cast(string)std.string.fromStringz(glGetString(GL_SHADING_LANGUAGE_VERSION));
vertexShader = compileShader(vertexSource, GL_VERTEX_SHADER);
fragmentShader = compileShader(fragmentSource, GL_FRAGMENT_SHADER);
if (!vertexShader || !fragmentShader) {
error = true;
return false;
}
program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
GLint isLinked = 0;
glGetProgramiv(program, GL_LINK_STATUS, &isLinked);
if (!isLinked) {
GLint maxLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
GLchar[] msg = new GLchar[maxLength + 1];
GLchar * pmsg = &msg[0];
glGetProgramInfoLog(program, maxLength, &maxLength, pmsg);
Log.e("Error while linking program: ", fromStringz(pmsg));
error = true;
return false;
}
Log.d("Program compiled successfully");
//glDetachShader(program, vertexShader);
//glDetachShader(program, fragmentShader);
glUseProgram(program);
checkError("glUseProgram " ~ to!string(program));
if (!initLocations()) {
Log.e("some of locations were not found");
error = true;
}
initialized = true;
return true;
}
bool initLocations() {
return true;
}
bool bind() {
if (!initialized)
return false;
if (!glIsProgram(program))
Log.e("!glIsProgram(program)");
glUseProgram(program);
checkError("glUseProgram " ~ to!string(program));
return true;
}
void release() {
glUseProgram(0);
checkError("glUseProgram(0)");
}
~this() {
clear();
}
void clear() {
// TODO: cleanup
if (program)
glDeleteProgram(program);
if (vertexShader)
glDeleteShader(vertexShader);
if (fragmentShader)
glDeleteShader(fragmentShader);
program = vertexShader = fragmentShader = 0;
initialized = false;
}
}
immutable string HIGHP = "";
immutable string LOWP = "";
immutable string MEDIUMP = "";
class SolidFillProgram : GLProgram {
@property override string vertexSource() {
return
"attribute " ~ HIGHP ~ " vec4 vertex;\n"
"attribute " ~ LOWP ~ " vec4 colAttr;\n"
"varying " ~ LOWP ~ " vec4 col;\n"
"uniform " ~ MEDIUMP ~ " mat4 matrix;\n"
"void main(void)\n"
"{\n"
" gl_Position = matrix * vertex;\n"
" col = colAttr;\n"
"}\n";
}
@property override string fragmentSource() {
return
"varying " ~ LOWP ~ " vec4 col;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = col;\n"
"}\n";
}
void beforeExecute() {
glEnable(GL_BLEND);
glDisable(GL_CULL_FACE);
checkError("glDisable(GL_CULL_FACE)");
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
checkError("glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)");
bind();
//glUniformMatrix4fv(matrixLocation, 1, false, m.value_ptr);
//glUniformMatrix4fv(matrixLocation, 1, false, matrix.ptr);
glUniformMatrix4fv(matrixLocation, 1, false, glSupport.qtmatrix.ptr);
checkError("glUniformMatrix4fv");
}
void afterExecute() {
release();
}
protected GLint matrixLocation;
protected GLint vertexLocation;
protected GLint colAttrLocation;
protected GLuint vertexBuffer;
protected GLuint colAttrBuffer;
override bool initLocations() {
bool res = super.initLocations();
//glGenBuffers(1, &vertexBuffer);
//glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
//glBufferData(GL_ARRAY_BUFFER, float.sizeof * 3 * 6, null, GL_DYNAMIC_DRAW);
//glGenBuffers(1, &colAttrBuffer);
//glBindBuffer(GL_ARRAY_BUFFER, colAttrBuffer);
//glBufferData(GL_ARRAY_BUFFER, float.sizeof * 4 * 6, null, GL_DYNAMIC_DRAW);
matrixLocation = glGetUniformLocation(program, "matrix");
checkError("glGetUniformLocation matrix");
vertexLocation = glGetAttribLocation(program, "vertex");
checkError("glGetAttribLocation vertex");
colAttrLocation = glGetAttribLocation(program, "colAttr");
checkError("glGetAttribLocation colAttr");
return res && matrixLocation >= 0 && vertexLocation >= 0 && colAttrLocation >= 0;
}
bool execute(float[] vertices, float[] colors) {
if (error)
return false;
if (!initialized)
if (!compile())
return false;
beforeExecute();
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(
GL_ARRAY_BUFFER,
vertices.length * vertices[0].sizeof + colors.length * colors[0].sizeof,
null,
GL_STREAM_DRAW);
glBufferSubData(
GL_ARRAY_BUFFER,
0,
vertices.length * vertices[0].sizeof,
vertices.ptr);
glBufferSubData(
GL_ARRAY_BUFFER,
vertices.length * vertices[0].sizeof,
colors.length * colors[0].sizeof, colors.ptr);
glEnableVertexAttribArray(vertexLocation);
checkError("glEnableVertexAttribArray");
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, cast(void*) 0);
checkError("glVertexAttribPointer");
glEnableVertexAttribArray(colAttrLocation);
checkError("glEnableVertexAttribArray");
glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (float.sizeof*3*6));
checkError("glVertexAttribPointer");
glDrawArrays(GL_TRIANGLES, 0, 6);
checkError("glDrawArrays");
glDisableVertexAttribArray(vertexLocation);
checkError("glDisableVertexAttribArray");
glDisableVertexAttribArray(colAttrLocation);
checkError("glDisableVertexAttribArray");
afterExecute();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &vbo);
glBindVertexArray(0);
glDeleteVertexArrays(1, &vao);
return true;
}
}
class TextureProgram : SolidFillProgram {
@property override string vertexSource() {
return
"attribute " ~ HIGHP ~ " vec4 vertex;\n"
"attribute " ~ LOWP ~ " vec4 colAttr;\n"
"attribute " ~ MEDIUMP ~ " vec4 texCoord;\n"
"varying " ~ LOWP ~ " vec4 col;\n"
"varying " ~ MEDIUMP ~ " vec4 texc;\n"
"uniform " ~ MEDIUMP ~ " mat4 matrix;\n"
"void main(void)\n"
"{\n"
" gl_Position = matrix * vertex;\n"
" col = colAttr;\n"
" texc = texCoord;\n"
"}\n";
}
@property override string fragmentSource() {
return
"uniform sampler2D texture;\n"
"varying " ~ LOWP ~ " vec4 col;\n"
"varying " ~ MEDIUMP ~ " vec4 texc;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = texture2D(texture, texc.st) * col;\n"
"}\n";
}
GLint texCoordLocation;
override bool initLocations() {
bool res = super.initLocations();
texCoordLocation = glGetAttribLocation(program, "texCoord");
return res && texCoordLocation >= 0;
}
bool execute(float[] vertices, float[] texcoords, float[] colors, uint textureId, bool linear) {
if (error)
return false;
if (!initialized)
if (!compile())
return false;
beforeExecute();
glActiveTexture(GL_TEXTURE0);
checkError("glActiveTexture GL_TEXTURE0");
glBindTexture(GL_TEXTURE_2D, textureId);
checkError("glBindTexture");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST);
checkError("drawColorAndTextureRect - glTexParameteri");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST);
checkError("drawColorAndTextureRect - glTexParameteri");
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(
GL_ARRAY_BUFFER,
vertices.length * vertices[0].sizeof +
colors.length * colors[0].sizeof +
texcoords.length * texcoords[0].sizeof,
null,
GL_STREAM_DRAW);
glBufferSubData(
GL_ARRAY_BUFFER,
0,
vertices.length * vertices[0].sizeof,
vertices.ptr);
glBufferSubData(
GL_ARRAY_BUFFER,
vertices.length * vertices[0].sizeof,
colors.length * colors[0].sizeof,
colors.ptr);
glBufferSubData(
GL_ARRAY_BUFFER,
vertices.length * vertices[0].sizeof + colors.length * colors[0].sizeof,
texcoords.length * texcoords[0].sizeof,
texcoords.ptr);
glEnableVertexAttribArray(vertexLocation);
glEnableVertexAttribArray(colAttrLocation);
glEnableVertexAttribArray(texCoordLocation);
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, cast(void*) 0);
glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (vertices.length * vertices[0].sizeof));
glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, cast(void*) (vertices.length * vertices[0].sizeof + colors.length * colors[0].sizeof));
glDrawArrays(GL_TRIANGLES, 0, 6);
checkError("glDrawArrays");
glDisableVertexAttribArray(vertexLocation);
glDisableVertexAttribArray(colAttrLocation);
glDisableVertexAttribArray(texCoordLocation);
afterExecute();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &vbo);
glBindVertexArray(0);
glDeleteVertexArrays(1, &vao);
glBindTexture(GL_TEXTURE_2D, 0);
checkError("glBindTexture");
return true;
}
}
__gshared GLSupport _glSupport;
@property GLSupport glSupport() {
if (!_glSupport) {
Log.f("GLSupport is not initialized");
assert(false, "GLSupport is not initialized");
}
if (!_glSupport.valid) {
Log.e("GLSupport programs are not initialized");
}
return _glSupport;
}
class GLSupport {
TextureProgram _textureProgram;
SolidFillProgram _solidFillProgram;
@property bool valid() {
return _textureProgram && _solidFillProgram;
}
bool initShaders() {
if (_textureProgram is null) {
_textureProgram = new TextureProgram();
if (!_textureProgram.compile())
return false;
}
if (_solidFillProgram is null) {
_solidFillProgram = new SolidFillProgram();
if (!_solidFillProgram.compile())
return false;
}
Log.d("Shaders compiled successfully");
return true;
}
bool uninitShaders() {
Log.d("Uniniting shaders");
if (_textureProgram !is null) {
destroy(_textureProgram);
_textureProgram = null;
}
if (_solidFillProgram !is null) {
destroy(_solidFillProgram);
_solidFillProgram = null;
}
return true;
}
bool isTexture(uint textureId) {
return glIsTexture(textureId) == GL_TRUE;
}
void setRotation(int x, int y, int rotationAngle) {
/*
this->rotationAngle = rotationAngle;
rotationX = x;
rotationY = y;
if (!currentFramebufferId) {
rotationY = bufferDy - rotationY;
}
QMatrix4x4 matrix2;
matrix2.ortho(0, bufferDx, 0, bufferDy, 0.5f, 5.0f);
if (rotationAngle) {
matrix2.translate(rotationX, rotationY, 0);
matrix2.rotate(rotationAngle, 0, 0, 1);
matrix2.translate(-rotationX, -rotationY, 0);
}
matrix2.copyDataTo(m);
*/
}
static immutable float Z_2D = -2.0f;
void drawSolidFillRect(Rect rc, uint color1, uint color2, uint color3, uint color4) { void drawSolidFillRect(Rect rc, uint color1, uint color2, uint color3, uint color4) {
float[6 * 4] colors; float[6 * 4] colors;
LVGLFillColor(color1, colors.ptr + 4*0, 1); LVGLFillColor(color1, colors.ptr + 4*0, 1);
@ -313,7 +734,6 @@ bool bindFramebuffer(uint framebufferId) {
private int bufferDx; private int bufferDx;
/// current gl buffer height /// current gl buffer height
private int bufferDy; private int bufferDy;
//private float[16] matrix; //private float[16] matrix;
private float[16] qtmatrix; private float[16] qtmatrix;
@ -357,404 +777,5 @@ void setOrthoProjection(int dx, int dy) {
checkError("glViewport"); checkError("glViewport");
} }
class GLProgram {
@property abstract string vertexSource();
@property abstract string fragmentSource();
protected GLuint vertexShader;
protected GLuint fragmentShader;
protected GLuint program;
protected bool initialized;
protected bool error;
protected string glslversion;
this() {
}
private GLuint compileShader(string src, GLuint type) {
import core.stdc.stdlib;
import std.string;
Log.d("compileShader glsl=", glslversion, " code: ", src);
GLuint shader = glCreateShader(type);//GL_VERTEX_SHADER
const char * psrc = src.toStringz;
GLuint len = cast(uint)src.length;
glShaderSource(shader, 1, &psrc, cast(const(int)*)&len);
glCompileShader(shader);
GLint compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (compiled) {
// compiled successfully
return shader;
} else {
GLint blen = 0;
GLsizei slen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH , &blen);
if (blen > 1)
{
GLchar[] msg = new GLchar[blen + 1];
GLchar * pmsg = &msg[0];
glGetShaderInfoLog(shader, blen, &slen, pmsg);
Log.d("Shader compilation error: ", fromStringz(pmsg));
}
return 0;
}
}
bool compile() {
glslversion = cast(string)std.string.fromStringz(glGetString(GL_SHADING_LANGUAGE_VERSION));
vertexShader = compileShader(vertexSource, GL_VERTEX_SHADER);
fragmentShader = compileShader(fragmentSource, GL_FRAGMENT_SHADER);
if (!vertexShader || !fragmentShader) {
error = true;
return false;
}
program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
GLint isLinked = 0;
glGetProgramiv(program, GL_LINK_STATUS, &isLinked);
if (!isLinked) {
GLint maxLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
GLchar[] msg = new GLchar[maxLength + 1];
GLchar * pmsg = &msg[0];
glGetProgramInfoLog(program, maxLength, &maxLength, pmsg);
Log.e("Error while linking program: ", fromStringz(pmsg));
error = true;
return false;
}
Log.d("Program compiled successfully");
//glDetachShader(program, vertexShader);
//glDetachShader(program, fragmentShader);
glUseProgram(program);
checkError("glUseProgram " ~ to!string(program));
if (!initLocations()) {
Log.e("some of locations were not found");
error = true;
}
initialized = true;
return true;
}
bool initLocations() {
return true;
}
bool bind() {
if (!initialized)
return false;
if (!glIsProgram(program))
Log.e("!glIsProgram(program)");
glUseProgram(program);
checkError("glUseProgram " ~ to!string(program));
return true;
}
void release() {
glUseProgram(0);
checkError("glUseProgram(0)");
}
~this() {
clear();
}
void clear() {
// TODO: cleanup
if (program)
glDeleteProgram(program);
if (vertexShader)
glDeleteShader(vertexShader);
if (fragmentShader)
glDeleteShader(fragmentShader);
program = vertexShader = fragmentShader = 0;
initialized = false;
}
} }
immutable string HIGHP = "";
immutable string LOWP = "";
immutable string MEDIUMP = "";
class SolidFillProgram : GLProgram {
@property override string vertexSource() {
return
"attribute " ~ HIGHP ~ " vec4 vertex;\n"
"attribute " ~ LOWP ~ " vec4 colAttr;\n"
"varying " ~ LOWP ~ " vec4 col;\n"
"uniform " ~ MEDIUMP ~ " mat4 matrix;\n"
"void main(void)\n"
"{\n"
" gl_Position = matrix * vertex;\n"
" col = colAttr;\n"
"}\n";
}
@property override string fragmentSource() {
return
"varying " ~ LOWP ~ " vec4 col;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = col;\n"
"}\n";
}
void beforeExecute() {
glEnable(GL_BLEND);
glDisable(GL_CULL_FACE);
checkError("glDisable(GL_CULL_FACE)");
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
checkError("glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)");
bind();
//glUniformMatrix4fv(matrixLocation, 1, false, m.value_ptr);
//glUniformMatrix4fv(matrixLocation, 1, false, matrix.ptr);
glUniformMatrix4fv(matrixLocation, 1, false, qtmatrix.ptr);
checkError("glUniformMatrix4fv");
}
void afterExecute() {
release();
}
protected GLint matrixLocation;
protected GLint vertexLocation;
protected GLint colAttrLocation;
protected GLuint vertexBuffer;
protected GLuint colAttrBuffer;
override bool initLocations() {
bool res = super.initLocations();
//glGenBuffers(1, &vertexBuffer);
//glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
//glBufferData(GL_ARRAY_BUFFER, float.sizeof * 3 * 6, null, GL_DYNAMIC_DRAW);
//glGenBuffers(1, &colAttrBuffer);
//glBindBuffer(GL_ARRAY_BUFFER, colAttrBuffer);
//glBufferData(GL_ARRAY_BUFFER, float.sizeof * 4 * 6, null, GL_DYNAMIC_DRAW);
matrixLocation = glGetUniformLocation(program, "matrix");
checkError("glGetUniformLocation matrix");
vertexLocation = glGetAttribLocation(program, "vertex");
checkError("glGetAttribLocation vertex");
colAttrLocation = glGetAttribLocation(program, "colAttr");
checkError("glGetAttribLocation colAttr");
return res && matrixLocation >= 0 && vertexLocation >= 0 && colAttrLocation >= 0;
}
bool execute(float[] vertices, float[] colors) {
if (error)
return false;
if (!initialized)
if (!compile())
return false;
beforeExecute();
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(
GL_ARRAY_BUFFER,
vertices.length * vertices[0].sizeof + colors.length * colors[0].sizeof,
null,
GL_STREAM_DRAW);
glBufferSubData(
GL_ARRAY_BUFFER,
0,
vertices.length * vertices[0].sizeof,
vertices.ptr);
glBufferSubData(
GL_ARRAY_BUFFER,
vertices.length * vertices[0].sizeof,
colors.length * colors[0].sizeof, colors.ptr);
glEnableVertexAttribArray(vertexLocation);
checkError("glEnableVertexAttribArray");
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, cast(void*) 0);
checkError("glVertexAttribPointer");
glEnableVertexAttribArray(colAttrLocation);
checkError("glEnableVertexAttribArray");
glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (float.sizeof*3*6));
checkError("glVertexAttribPointer");
glDrawArrays(GL_TRIANGLES, 0, 6);
checkError("glDrawArrays");
glDisableVertexAttribArray(vertexLocation);
checkError("glDisableVertexAttribArray");
glDisableVertexAttribArray(colAttrLocation);
checkError("glDisableVertexAttribArray");
afterExecute();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &vbo);
glBindVertexArray(0);
glDeleteVertexArrays(1, &vao);
return true;
}
}
class TextureProgram : SolidFillProgram {
@property override string vertexSource() {
return
"attribute " ~ HIGHP ~ " vec4 vertex;\n"
"attribute " ~ LOWP ~ " vec4 colAttr;\n"
"attribute " ~ MEDIUMP ~ " vec4 texCoord;\n"
"varying " ~ LOWP ~ " vec4 col;\n"
"varying " ~ MEDIUMP ~ " vec4 texc;\n"
"uniform " ~ MEDIUMP ~ " mat4 matrix;\n"
"void main(void)\n"
"{\n"
" gl_Position = matrix * vertex;\n"
" col = colAttr;\n"
" texc = texCoord;\n"
"}\n";
}
@property override string fragmentSource() {
return
"uniform sampler2D texture;\n"
"varying " ~ LOWP ~ " vec4 col;\n"
"varying " ~ MEDIUMP ~ " vec4 texc;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = texture2D(texture, texc.st) * col;\n"
"}\n";
}
GLint texCoordLocation;
override bool initLocations() {
bool res = super.initLocations();
texCoordLocation = glGetAttribLocation(program, "texCoord");
return res && texCoordLocation >= 0;
}
bool execute(float[] vertices, float[] texcoords, float[] colors, uint textureId, bool linear) {
if (error)
return false;
if (!initialized)
if (!compile())
return false;
beforeExecute();
glActiveTexture(GL_TEXTURE0);
checkError("glActiveTexture GL_TEXTURE0");
glBindTexture(GL_TEXTURE_2D, textureId);
checkError("glBindTexture");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST);
checkError("drawColorAndTextureRect - glTexParameteri");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST);
checkError("drawColorAndTextureRect - glTexParameteri");
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(
GL_ARRAY_BUFFER,
vertices.length * vertices[0].sizeof +
colors.length * colors[0].sizeof +
texcoords.length * texcoords[0].sizeof,
null,
GL_STREAM_DRAW);
glBufferSubData(
GL_ARRAY_BUFFER,
0,
vertices.length * vertices[0].sizeof,
vertices.ptr);
glBufferSubData(
GL_ARRAY_BUFFER,
vertices.length * vertices[0].sizeof,
colors.length * colors[0].sizeof,
colors.ptr);
glBufferSubData(
GL_ARRAY_BUFFER,
vertices.length * vertices[0].sizeof + colors.length * colors[0].sizeof,
texcoords.length * texcoords[0].sizeof,
texcoords.ptr);
glEnableVertexAttribArray(vertexLocation);
glEnableVertexAttribArray(colAttrLocation);
glEnableVertexAttribArray(texCoordLocation);
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, cast(void*) 0);
glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (vertices.length * vertices[0].sizeof));
glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, cast(void*) (vertices.length * vertices[0].sizeof + colors.length * colors[0].sizeof));
glDrawArrays(GL_TRIANGLES, 0, 6);
checkError("glDrawArrays");
glDisableVertexAttribArray(vertexLocation);
glDisableVertexAttribArray(colAttrLocation);
glDisableVertexAttribArray(texCoordLocation);
afterExecute();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &vbo);
glBindVertexArray(0);
glDeleteVertexArrays(1, &vao);
glBindTexture(GL_TEXTURE_2D, 0);
checkError("glBindTexture");
return true;
}
}
__gshared TextureProgram _textureProgram;
__gshared SolidFillProgram _solidFillProgram;
bool initShaders() {
if (_textureProgram is null) {
_textureProgram = new TextureProgram();
if (!_textureProgram.compile())
return false;
}
if (_solidFillProgram is null) {
_solidFillProgram = new SolidFillProgram();
if (!_solidFillProgram.compile())
return false;
}
Log.d("Shaders compiled successfully");
return true;
}
bool uninitShaders() {
Log.d("Uniniting shaders");
if (_textureProgram !is null) {
destroy(_textureProgram);
_textureProgram = null;
}
if (_solidFillProgram !is null) {
destroy(_solidFillProgram);
_solidFillProgram = null;
}
return true;
}
bool isTexture(uint textureId) {
return glIsTexture(textureId) == GL_TRUE;
}
void setRotation(int x, int y, int rotationAngle) {
/*
this->rotationAngle = rotationAngle;
rotationX = x;
rotationY = y;
if (!currentFramebufferId) {
rotationY = bufferDy - rotationY;
}
QMatrix4x4 matrix2;
matrix2.ortho(0, bufferDx, 0, bufferDy, 0.5f, 5.0f);
if (rotationAngle) {
matrix2.translate(rotationX, rotationY, 0);
matrix2.rotate(rotationAngle, 0, 0, 1);
matrix2.translate(-rotationX, -rotationY, 0);
}
matrix2.copyDataTo(m);
*/
}

View File

@ -97,6 +97,8 @@ class SDLWindow : Window {
version(USE_OPENGL) { version(USE_OPENGL) {
if (_enableOpengl) if (_enableOpengl)
windowFlags |= SDL_WINDOW_OPENGL; windowFlags |= SDL_WINDOW_OPENGL;
if (!_glSupport)
_glSupport = new GLSupport();
} }
_win = SDL_CreateWindow(toUTF8(_caption).toStringz, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, _win = SDL_CreateWindow(toUTF8(_caption).toStringz, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
700, 500, 700, 500,
@ -127,7 +129,7 @@ class SDLWindow : Window {
} else if (!_gl3Reloaded) { } else if (!_gl3Reloaded) {
DerelictGL3.reload(); DerelictGL3.reload();
_gl3Reloaded = true; _gl3Reloaded = true;
if (!initShaders()) if (!glSupport.valid && !glSupport.initShaders())
_enableOpengl = false; _enableOpengl = false;
} }
} }

View File

@ -154,10 +154,12 @@ version (USE_OPENGL) {
class Win32Window : Window { class Win32Window : Window {
Win32Platform _platform; Win32Platform _platform;
HWND _hwnd; HWND _hwnd;
version (USE_OPENGL) { version (USE_OPENGL) {
HGLRC _hGLRC; // opengl context HGLRC _hGLRC; // opengl context
HPALETTE _hPalette; HPALETTE _hPalette;
GLSupport _gl;
} }
dstring _caption; dstring _caption;
Win32ColorDrawBuf _drawbuf; Win32ColorDrawBuf _drawbuf;
@ -167,6 +169,7 @@ class Win32Window : Window {
Win32Window w32parent = cast(Win32Window)parent; Win32Window w32parent = cast(Win32Window)parent;
HWND parenthwnd = w32parent ? w32parent._hwnd : null; HWND parenthwnd = w32parent ? w32parent._hwnd : null;
_platform = platform; _platform = platform;
_gl = new GLSupport();
_caption = windowCaption; _caption = windowCaption;
_flags = flags; _flags = flags;
uint ws = WS_CLIPCHILDREN | WS_CLIPSIBLINGS; uint ws = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
@ -199,7 +202,9 @@ class Win32Window : Window {
_hPalette = setupPalette(hDC); _hPalette = setupPalette(hDC);
_hGLRC = wglCreateContext(hDC); _hGLRC = wglCreateContext(hDC);
if (_hGLRC) { if (_hGLRC) {
wglMakeCurrent(hDC, _hGLRC); wglMakeCurrent(hDC, _hGLRC);
_glSupport = _gl;
if (!DERELICT_GL3_RELOADED) { if (!DERELICT_GL3_RELOADED) {
// run this code only once // run this code only once
@ -208,7 +213,7 @@ class Win32Window : Window {
import derelict.opengl3.gl3; import derelict.opengl3.gl3;
DerelictGL3.reload(); DerelictGL3.reload();
// successful // successful
if (initShaders()) { if (glSupport.initShaders()) {
setOpenglEnabled(); setOpenglEnabled();
useOpengl = true; useOpengl = true;
} else { } else {
@ -218,7 +223,7 @@ class Win32Window : Window {
Log.e("Derelict exception", e); Log.e("Derelict exception", e);
} }
} else { } else {
if (initShaders()) { if (glSupport.initShaders()) {
setOpenglEnabled(); setOpenglEnabled();
useOpengl = true; useOpengl = true;
} else { } else {
@ -252,6 +257,7 @@ class Win32Window : Window {
//scope(exit) EndPaint(_hwnd, &ps); //scope(exit) EndPaint(_hwnd, &ps);
HDC hdc = GetDC(_hwnd); HDC hdc = GetDC(_hwnd);
wglMakeCurrent(hdc, _hGLRC); wglMakeCurrent(hdc, _hGLRC);
_glSupport = _gl;
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glViewport(0, 0, _dx, _dy); glViewport(0, 0, _dx, _dy);
float a = 1.0f; float a = 1.0f;
@ -288,7 +294,10 @@ class Win32Window : Window {
version (USE_OPENGL) { version (USE_OPENGL) {
import derelict.opengl3.wgl; import derelict.opengl3.wgl;
if (_hGLRC) { if (_hGLRC) {
uninitShaders(); glSupport.uninitShaders();
delete _glSupport;
_glSupport = null;
_gl = null;
wglMakeCurrent (null, null) ; wglMakeCurrent (null, null) ;
wglDeleteContext(_hGLRC); wglDeleteContext(_hGLRC);
_hGLRC = null; _hGLRC = null;
@ -470,7 +479,7 @@ class Win32Window : Window {
} }
void onPaint() { void onPaint() {
Log.d("onPaint()"); debug(DebugRedraw) Log.d("onPaint()");
long paintStart = currentTimeMillis; long paintStart = currentTimeMillis;
version (USE_OPENGL) { version (USE_OPENGL) {
if (useOpengl && _hGLRC) { if (useOpengl && _hGLRC) {
@ -482,7 +491,7 @@ class Win32Window : Window {
paintUsingGDI(); paintUsingGDI();
} }
long paintEnd = currentTimeMillis; long paintEnd = currentTimeMillis;
Log.d("WM_PAINT handling took ", paintEnd - paintStart, " ms"); debug(DebugRedraw) Log.d("WM_PAINT handling took ", paintEnd - paintStart, " ms");
} }
protected ButtonDetails _lbutton; protected ButtonDetails _lbutton;