getting legacy GL to work

This commit is contained in:
gazer 2017-06-07 21:53:17 +03:00
parent 167e129f00
commit 4b7fa25579
5 changed files with 115 additions and 129 deletions

View File

@ -1217,12 +1217,12 @@ static if (ENABLE_OPENGL) {
/// this is OpenGLDrawableDelegate implementation
private void doDraw(Rect windowRect, Rect rc) {
Log.v("GlGears: MyOpenglWidget.doDraw() draw gears");
if (!openglEnabled) {
Log.v("GlGears: OpenGL is disabled");
return;
}
_oldApi = !!glLightfv;
import dlangui.graphics.glsupport : glSupport;
_oldApi = glSupport.legacyMode;
if (_oldApi) {
drawUsingOldAPI(rc);
} else {
@ -1238,9 +1238,7 @@ static if (ENABLE_OPENGL) {
_initCalled = true;
glxgears_init();
}
Log.v("GlGears: calling reshape()");
glxgears_reshape(rc);
Log.v("GlGears: calling draw()");
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
@ -1469,14 +1467,12 @@ static if (ENABLE_OPENGL) {
static GLfloat[4] green = [ 0.0, 0.8, 0.2, 1.0 ];
static GLfloat[4] blue = [ 0.2, 0.2, 1.0, 1.0 ];
Log.d("GlGears: init - calling glLightfv");
glLightfv(GL_LIGHT0, GL_POSITION, pos.ptr);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
Log.d("GlGears: init - calling genlists");
/* make the gears */
gear1 = glGenLists(1);
glNewList(gear1, GL_COMPILE);

View File

@ -9,11 +9,15 @@ extern (C) int UIAppMain(string[] args) {
// embed resources listed in views/resources.list into executable
embeddedResourceList.addResources(embedResourcesFromList!("resources.list")());
// the old API example works on old context because of OpenGL deprecation model
// otherwise there will be GL_INVALID_OPERATION error
// new API functions on a modern graphics card will work even if you set context version to 1.0
Platform.instance.GLVersionMajor = 2;
Platform.instance.GLVersionMinor = 1;
// create window
Window window = Platform.instance.createWindow("DlangUI OpenGL Example", null, WindowFlag.Resizable, 800, 700);
VerticalLayout contentLayout = new VerticalLayout();
static if (ENABLE_OPENGL) {
window.mainWidget = new MyOpenglWidget();
} else {
@ -147,9 +151,7 @@ class MyOpenglWidget : VerticalLayout {
_initCalled = true;
glxgears_init();
}
Log.v("GlGears: calling reshape()");
glxgears_reshape(rc);
Log.v("GlGears: calling draw()");
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
@ -162,22 +164,31 @@ class MyOpenglWidget : VerticalLayout {
~this() {
if (_program)
destroy(_program);
if (_vao)
destroy(_vao);
if (_vbo)
destroy(_vbo);
if (_tx)
destroy(_tx);
}
MyGLProgram _program;
GLTexture _tx;
VAO _vao;
VBO _vbo;
/// New API example (OpenGL3+, shaders)
void drawUsingNewAPI(Rect windowRect, Rect rc) {
if (!_program) {
_program = new MyGLProgram();
_program = new MyGLProgram;
_program.compile();
createMesh();
auto buf = _program.createBuffers(vertices, colors, texcoords);
_vao = buf[0];
_vbo = buf[1];
}
if (!_program.check())
return;
if (!_tx.isValid) {
Log.e("Invalid texture");
return;
@ -208,7 +219,7 @@ class MyOpenglWidget : VerticalLayout {
// ======= PMV matrix =====================
mat4 projectionViewModelMatrix = projectionMatrix * viewMatrix * modelMatrix;
_program.execute(vertices, colors, texcoords, _tx.texture, true, projectionViewModelMatrix.m);
_program.execute(_vao, cast(int)vertices.length / 3, _tx.texture, true, projectionViewModelMatrix.m);
checkgl!glDisable(GL_CULL_FACE);
checkgl!glDisable(GL_DEPTH_TEST);
@ -306,23 +317,13 @@ class MyGLProgram : GLProgram {
return matrixLocation >= 0 && vertexLocation >= 0 && colAttrLocation >= 0 && texCoordLocation >= 0;
}
bool execute(float[] vertices, float[] colors, float[] texcoords, Tex2D texture, bool linear, float[16] matrix) {
if(!check())
return false;
import std.typecons : Tuple, tuple;
Tuple!(VAO, VBO) createBuffers(float[] vertices, float[] colors, float[] texcoords) {
glEnable(GL_BLEND);
checkgl!glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
bind();
checkgl!glUniformMatrix4fv(matrixLocation, 1, false, matrix.ptr);
texture.setup();
texture.setSamplerParams(linear);
VAO vao = new VAO();
VBO vbo = new VBO();
VBO vbo = new VBO;
vbo.fill([vertices, colors, texcoords]);
VAO vao = new VAO;
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));
@ -331,19 +332,22 @@ class MyGLProgram : GLProgram {
glEnableVertexAttribArray(colAttrLocation);
glEnableVertexAttribArray(texCoordLocation);
checkgl!glDrawArrays(GL_TRIANGLES, 0, cast(int)vertices.length / 3);
return tuple(vao, vbo);
}
glDisableVertexAttribArray(vertexLocation);
glDisableVertexAttribArray(colAttrLocation);
glDisableVertexAttribArray(texCoordLocation);
void execute(VAO vao, int vertsCount, Tex2D texture, bool linear, float[16] matrix) {
unbind();
bind();
checkgl!glUniformMatrix4fv(matrixLocation, 1, false, matrix.ptr);
destroy(vbo);
destroy(vao);
texture.setup();
texture.setSamplerParams(linear);
vao.bind();
checkgl!glDrawArrays(GL_TRIANGLES, 0, vertsCount);
texture.unbind();
return true;
unbind();
}
}
@ -550,14 +554,12 @@ static void glxgears_init()
static GLfloat[4] green = [ 0.0, 0.8, 0.2, 1.0 ];
static GLfloat[4] blue = [ 0.2, 0.2, 1.0, 1.0 ];
Log.d("GlGears: init - calling glLightfv");
glLightfv(GL_LIGHT0, GL_POSITION, pos.ptr);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
Log.d("GlGears: init - calling genlists");
/* make the gears */
gear1 = glGenLists(1);
glNewList(gear1, GL_COMPILE);

View File

@ -80,8 +80,6 @@ class GLDrawBuf : DrawBuf, GLConfigCallback {
glSupport.beforeRenderGUI();
_scene.draw();
glSupport.queue.flush();
GLProgram.unbind();
glSupport.destroyBuffers();
glSupport.flushGL();
destroy(_scene);
_scene = null;
@ -836,8 +834,6 @@ public:
glSupport.queue.flush();
glSupport.setOrthoProjection(_windowRect, _rc);
glSupport.clearDepthBuffer();
//glEnable(GL_BLEND);
//checkgl!glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
_handler(_windowRect, _rc);
glSupport.setOrthoProjection(_windowRect, _windowRect);
}

View File

@ -281,15 +281,9 @@ class GLProgram : dlangui.graphics.scene.mesh.GraphicsEffect {
initialized = false;
}
/// returns true if program is ready for use (compiles program if not yet compiled)
bool check()
{
if (error)
return false;
if (!initialized)
if (!compile())
return false;
return true;
/// returns true if program is ready for use
bool check() {
return !error && initialized;
}
static GLuint currentProgram;
@ -645,7 +639,7 @@ private float[] convertColors(uint[] cols) pure nothrow {
return colors;
}
__gshared GLSupport _glSupport;
private __gshared GLSupport _glSupport;
@property GLSupport glSupport() {
if (!_glSupport) {
Log.f("GLSupport is not initialized");
@ -657,7 +651,7 @@ __gshared GLSupport _glSupport;
return _glSupport;
}
/// initialize OpenGL suport helper (call when current OpenGL context is initialized)
/// initialize OpenGL support helper (call when current OpenGL context is initialized)
bool initGLSupport(bool legacy = false) {
import dlangui.platforms.common.platform : setOpenglEnabled;
if (_glSupport && _glSupport.valid)
@ -701,12 +695,7 @@ bool initGLSupport(bool legacy = false) {
if (!_glSupport) {
Log.d("glSupport not initialized: trying to create");
_glSupport = new GLSupport(legacy);
if (_glSupport.valid || _glSupport.initShaders()) {
Log.v("shaders are ok");
setOpenglEnabled();
Log.v("OpenGL is initialized ok");
return true;
} else {
if (!_glSupport.valid) {
Log.e("Failed to compile shaders");
version (Android) {
// do not recreate legacy mode
@ -715,19 +704,21 @@ bool initGLSupport(bool legacy = false) {
if (_glSupport.legacyMode == legacy) {
Log.i("Trying to reinit GLSupport with legacy flag ", !legacy);
_glSupport = new GLSupport(!legacy);
if (_glSupport.valid || _glSupport.initShaders()) {
Log.v("shaders are ok");
setOpenglEnabled();
Log.v("OpenGL is initialized ok");
return true;
}
// Situation when opposite legacy flag is true and context version is 3.1+
if (_glSupport.legacyMode) {
int major = to!int(glGetString(GL_VERSION)[0]);
if (major >= 3) {
Log.e("Try to create OpenGL context with <= 3.1 version");
return false;
}
}
}
}
return false;
}
if (_glSupport.valid || _glSupport.initShaders()) {
if (_glSupport.valid) {
setOpenglEnabled();
Log.v("OpenGL is initialized ok");
return true;
} else {
Log.e("Failed to compile shaders");
@ -742,6 +733,10 @@ final class GLSupport {
@property bool legacyMode() { return _legacyMode; }
@property queue() { return _queue; }
@property bool valid() {
return _legacyMode || _shadersAreInitialized;
}
this(bool legacy = false) {
_queue = new OpenGLQueue;
version (Android) {
@ -753,36 +748,40 @@ final class GLSupport {
}
}
_legacyMode = legacy;
if (!_legacyMode)
_shadersAreInitialized = initShaders();
}
OpenGLQueue _queue;
SolidFillProgram _solidFillProgram;
TextureProgram _textureProgram;
@property bool valid() {
return _legacyMode || _textureProgram && _solidFillProgram;
~this() {
uninitShaders();
}
bool initShaders() {
Log.i("initShaders() is called");
private OpenGLQueue _queue;
private SolidFillProgram _solidFillProgram;
private TextureProgram _textureProgram;
private bool _shadersAreInitialized;
private bool initShaders() {
if (_solidFillProgram is null) {
Log.v("Compiling solid fill program");
_solidFillProgram = new SolidFillProgram();
if (!_solidFillProgram.compile())
_solidFillProgram.compile();
if (!_solidFillProgram.check())
return false;
}
if (_textureProgram is null) {
Log.v("Compiling texture program");
_textureProgram = new TextureProgram();
if (!_textureProgram.compile())
_textureProgram.compile();
if (!_textureProgram.check())
return false;
}
Log.d("Shaders compiled successfully");
return true;
}
bool uninitShaders() {
private void uninitShaders() {
Log.d("Uniniting shaders");
if (_solidFillProgram !is null) {
destroy(_solidFillProgram);
@ -792,7 +791,6 @@ final class GLSupport {
destroy(_textureProgram);
_textureProgram = null;
}
return true;
}
void beforeRenderGUI() {
@ -801,10 +799,15 @@ final class GLSupport {
checkgl!glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
VBO vbo;
EBO ebo;
private VBO vbo;
private EBO ebo;
private void fillBuffers(float[] vertices, float[] colors, float[] texcoords, int[] indices) {
resetBindings();
if(_legacyMode)
return;
void fillBuffers(float[] vertices, float[] colors, float[] texcoords, int[] indices) {
vbo = new VBO;
ebo = new EBO;
@ -823,7 +826,20 @@ final class GLSupport {
ebo.bind();
}
void destroyBuffers() {
/// This function is needed to draw custom OpenGL scene correctly (especially on legacy API)
private void resetBindings() {
// TODO: check if there is a very old driver with no such functions
GLProgram.unbind();
VAO.unbind();
VBO.unbind();
}
private void destroyBuffers() {
resetBindings();
if(_legacyMode)
return;
if (_solidFillProgram)
_solidFillProgram.destroyBuffers();
if (_textureProgram)
@ -835,26 +851,18 @@ final class GLSupport {
ebo = null;
}
void drawLines(int length, int start) {
private void drawLines(int length, int start) {
if (_legacyMode) {
static if (SUPPORT_LEGACY_OPENGL) {
glColor4f(1,1,1,1);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
checkgl!glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
checkgl!glEnableClientState(GL_VERTEX_ARRAY);
checkgl!glEnableClientState(GL_COLOR_ARRAY);
checkgl!glVertexPointer(3, GL_FLOAT, 0, cast(void*)_queue._vertices.ptr);
checkgl!glColorPointer(4, GL_FLOAT, 0, cast(void*)_queue._colors.ptr);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, cast(void*)_queue._vertices.ptr);
glColorPointer(4, GL_FLOAT, 0, cast(void*)_queue._colors.ptr);
checkgl!glDrawElements(GL_LINES, cast(int)length, GL_UNSIGNED_INT, cast(void*)(_queue._indices.ptr + start * 4));
checkgl!glDrawElements(GL_LINES, cast(int)length, GL_UNSIGNED_INT, cast(void*)(_queue._indices[start .. start + length].ptr));
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
}
} else {
if (_solidFillProgram !is null) {
@ -864,26 +872,18 @@ final class GLSupport {
}
}
void drawSolidFillTriangles(int length, int start) {
private void drawSolidFillTriangles(int length, int start) {
if (_legacyMode) {
static if (SUPPORT_LEGACY_OPENGL) {
glColor4f(1,1,1,1);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
checkgl!glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
checkgl!glEnableClientState(GL_VERTEX_ARRAY);
checkgl!glEnableClientState(GL_COLOR_ARRAY);
checkgl!glVertexPointer(3, GL_FLOAT, 0, cast(void*)_queue._vertices.ptr);
checkgl!glColorPointer(4, GL_FLOAT, 0, cast(void*)_queue._colors.ptr);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, cast(void*)_queue._vertices.ptr);
glColorPointer(4, GL_FLOAT, 0, cast(void*)_queue._colors.ptr);
checkgl!glDrawElements(GL_TRIANGLES, cast(int)length, GL_UNSIGNED_INT, cast(void*)(_queue._indices.ptr + start * 4));
checkgl!glDrawElements(GL_TRIANGLES, cast(int)length, GL_UNSIGNED_INT, cast(void*)(_queue._indices[start .. start + length].ptr));
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
}
} else {
if (_solidFillProgram !is null) {
@ -893,35 +893,25 @@ final class GLSupport {
}
}
void drawColorAndTextureTriangles(Tex2D texture, bool linear, int length, int start) {
private void drawColorAndTextureTriangles(Tex2D texture, bool linear, int length, int start) {
if (_legacyMode) {
static if (SUPPORT_LEGACY_OPENGL) {
glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
texture.setup();
texture.setSamplerParams(linear);
glColor4f(1,1,1,1);
glDisable(GL_ALPHA_TEST);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, cast(void*)_queue._vertices.ptr);
glTexCoordPointer(2, GL_FLOAT, 0, cast(void*)_queue._texCoords.ptr);
glColorPointer(4, GL_FLOAT, 0, cast(void*)_queue._colors.ptr);
glEnable(GL_BLEND);
checkgl!glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
checkgl!glEnableClientState(GL_COLOR_ARRAY);
checkgl!glEnableClientState(GL_VERTEX_ARRAY);
checkgl!glEnableClientState(GL_TEXTURE_COORD_ARRAY);
checkgl!glVertexPointer(3, GL_FLOAT, 0, cast(void*)_queue._vertices.ptr);
checkgl!glTexCoordPointer(2, GL_FLOAT, 0, cast(void*)_queue._texCoords.ptr);
checkgl!glColorPointer(4, GL_FLOAT, 0, cast(void*)_queue._colors.ptr);
checkgl!glDrawElements(GL_TRIANGLES, cast(int)length, GL_UNSIGNED_INT, cast(void*)(_queue._indices.ptr + start * 4));
checkgl!glDrawElements(GL_TRIANGLES, cast(int)length, GL_UNSIGNED_INT, cast(void*)(_queue._indices[start .. start + length].ptr));
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glDisable(GL_TEXTURE_2D);
}
} else {
@ -1459,6 +1449,7 @@ private final class OpenGLQueue {
}
}
//Log.d(batches.length, " ", _vertices.length, " ", _colors.length, " ", _texCoords.length, " ", _indices.length);
glSupport.destroyBuffers();
destroy(batches);
destroy(_vertices);
destroy(_colors);

View File

@ -18,7 +18,7 @@ class Effect : GLProgram {
EffectId _id;
string[string] _defs;
string _defText;
@property ref const(EffectId) id() const { return _id; }
this(EffectId id) {
_id = id;
@ -53,6 +53,7 @@ class Effect : GLProgram {
}
_defText = buf.dup;
// compile shaders
compile();
if (!check()) {
Log.e("Failed to compile shaders ", _id.vertexShaderName, " ", _id.fragmentShaderName, " ", _id.definitions);
assert(false);