diff --git a/vtm-playground/src/org/oscim/test/renderer/CustomRenderer.java b/vtm-playground/src/org/oscim/test/renderer/CustomRenderer.java index f9e0c915..f1e96c94 100644 --- a/vtm-playground/src/org/oscim/test/renderer/CustomRenderer.java +++ b/vtm-playground/src/org/oscim/test/renderer/CustomRenderer.java @@ -120,7 +120,7 @@ public class CustomRenderer extends LayerRenderer { // Draw the triangle gl.drawArrays(GL.TRIANGLE_STRIP, 0, 4); - GLUtils.checkGlError("..."); + GLUtils.checkGlError(getClass().getName() + ": render() end"); } private boolean init() { diff --git a/vtm-playground/src/org/oscim/test/renderer/HexagonRenderTest.java b/vtm-playground/src/org/oscim/test/renderer/HexagonRenderTest.java index 2791db65..d7661c96 100644 --- a/vtm-playground/src/org/oscim/test/renderer/HexagonRenderTest.java +++ b/vtm-playground/src/org/oscim/test/renderer/HexagonRenderTest.java @@ -175,7 +175,7 @@ public class HexagonRenderTest extends GdxMapApp { } } - GLUtils.checkGlError("..."); + GLUtils.checkGlError(getClass().getName() + ": render() end"); } private boolean init() { diff --git a/vtm/src/org/oscim/backend/GL.java b/vtm/src/org/oscim/backend/GL.java index 9766d767..60d36753 100644 --- a/vtm/src/org/oscim/backend/GL.java +++ b/vtm/src/org/oscim/backend/GL.java @@ -106,7 +106,7 @@ public interface GL { public static final int POLYGON_OFFSET_FILL = 0x8037; public static final int SAMPLE_ALPHA_TO_COVERAGE = 0x809E; public static final int SAMPLE_COVERAGE = 0x80A0; - //public static final int NO_ERROR = 0; + public static final int NO_ERROR = 0; public static final int INVALID_ENUM = 0x0500; public static final int INVALID_VALUE = 0x0501; public static final int INVALID_OPERATION = 0x0502; diff --git a/vtm/src/org/oscim/renderer/GLShader.java b/vtm/src/org/oscim/renderer/GLShader.java index cb76fd05..83c73cf3 100644 --- a/vtm/src/org/oscim/renderer/GLShader.java +++ b/vtm/src/org/oscim/renderer/GLShader.java @@ -139,11 +139,11 @@ public abstract class GLShader { int program = gl.createProgram(); if (program != 0) { - GLUtils.checkGlError("glCreateProgram"); + GLUtils.checkGlError(GLShader.class.getName() + ": glCreateProgram"); gl.attachShader(program, vertexShader); - GLUtils.checkGlError("glAttachShader"); + GLUtils.checkGlError(GLShader.class.getName() + ": glAttachShader"); gl.attachShader(program, pixelShader); - GLUtils.checkGlError("glAttachShader"); + GLUtils.checkGlError(GLShader.class.getName() + ": glAttachShader"); gl.linkProgram(program); IntBuffer linkStatus = MapRenderer.getIntBuffer(1); gl.getProgramiv(program, GL.LINK_STATUS, linkStatus); diff --git a/vtm/src/org/oscim/renderer/GLUtils.java b/vtm/src/org/oscim/renderer/GLUtils.java index 4527692c..5eb0c2bc 100644 --- a/vtm/src/org/oscim/renderer/GLUtils.java +++ b/vtm/src/org/oscim/renderer/GLUtils.java @@ -1,6 +1,7 @@ /* * Copyright 2013 Hannes Janetzek - * Copyright 2016 devemux86 + * Copyright 2016-2019 devemux86 + * Copyright 2019 Gustl22 * * This file is part of the OpenScienceMap project (http://www.opensciencemap.org). * @@ -27,6 +28,8 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.List; import static org.oscim.backend.GLAdapter.gl; @@ -107,26 +110,102 @@ public class GLUtils { return textureIds[0]; } - public static void checkGlError(String op) { - //GL = GLAdapter.get(); + /** + * Check the status of current framebuffer. + * See: https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glCheckFramebufferStatus.xml + * + * @param op the operation which should be debugged + * @return the status code + */ + public static int checkFramebufferStatus(String op) { + int status = gl.checkFramebufferStatus(GL.FRAMEBUFFER); + if (status != GL.FRAMEBUFFER_COMPLETE) + log.error(op + ": \tglFramebuffer " + getFramebufferStatusString(status) + " (" + status + ")"); + return status; + } - int error; - while ((error = gl.getError()) != 0) { // GL20.NO_ERROR) { - log.error(op + ": glError " + error); + /** + * @param status the status code of a framebuffer + * @return the status code as string + */ + public static String getFramebufferStatusString(int status) { + switch (status) { + case GL.FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; + case GL.FRAMEBUFFER_INCOMPLETE_DIMENSIONS: + return "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"; + case GL.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; + case GL.FRAMEBUFFER_UNSUPPORTED: + return "GL_FRAMEBUFFER_UNSUPPORTED"; + case GL.FRAMEBUFFER_COMPLETE: + return "GL_FRAMEBUFFER_COMPLETE"; + default: + return String.valueOf(status); + } + } + + /** + * Check GL error. + * See: https://www.khronos.org/opengl/wiki/OpenGL_Error + * + * @param op the operation which should be debugged + */ + public static void checkGlError(String op) { + int error; // GL.NO_ERROR + while ((error = gl.getError()) != GL.NO_ERROR) { + log.error(op + ": \tglError " + getGlErrorString(error) + " (" + error + ")"); // throw new RuntimeException(op + ": glError " + error); } } - public static boolean checkGlOutOfMemory(String op) { - int error; - boolean oom = false; - while ((error = gl.getError()) != 0) {// GL20.NO_ERROR) { - log.error(op + ": glError " + error); + /** + * Check GL errors. + * See: https://www.khronos.org/opengl/wiki/OpenGL_Error + * + * @param op the operation which should be debugged + * @return the OpenGL error codes + */ + public static List checkGlErrors(String op) { + int error; // GL.NO_ERROR + List errors = new ArrayList<>(); + while ((error = gl.getError()) != GL.NO_ERROR) { + log.error(op + ": \tglError " + getGlErrorString(error) + " (" + error + ")"); + errors.add(error); // throw new RuntimeException(op + ": glError " + error); - if (error == 1285) - oom = true; } - return oom; + return errors; + } + + /** + * @param error the error code of OpenGL + * @return the error code as string + */ + public static String getGlErrorString(int error) { + switch (error) { + case GL.INVALID_ENUM: + return "GL_INVALID_ENUM"; + case GL.INVALID_VALUE: + return "GL_INVALID_VALUE"; + case GL.INVALID_OPERATION: + return "GL_INVALID_OPERATION"; + case 0x0503: // GL.STACK_OVERFLOW + return "GL_STACK_OVERFLOW"; + case 0x0504: // GL.STACK_UNDERFLOW + return "GL_STACK_UNDERFLOW"; + case GL.OUT_OF_MEMORY: + return "GL_OUT_OF_MEMORY"; + case GL.INVALID_FRAMEBUFFER_OPERATION: + return "GL_INVALID_FRAMEBUFFER_OPERATION"; + case 0x0507: // GL.CONTEXT_LOST (with OpenGL 4.5) + return "GL_CONTEXT_LOST"; + case 0x8031: // GL.TABLE_TOO_LARGE (deprecated in OpenGL 3.0) + return "GL_TABLE_TOO_LARGE"; + case GL.NO_ERROR: + return "GL_NO_ERROR"; + default: + return String.valueOf(error); + } } public static void setColor(int handle, float[] c, float alpha) { diff --git a/vtm/src/org/oscim/renderer/MapRenderer.java b/vtm/src/org/oscim/renderer/MapRenderer.java index 749af542..eea59fb9 100644 --- a/vtm/src/org/oscim/renderer/MapRenderer.java +++ b/vtm/src/org/oscim/renderer/MapRenderer.java @@ -160,7 +160,7 @@ public class MapRenderer { GLUtils.checkGlError(renderer.getClass().getName()); } - if (GLUtils.checkGlOutOfMemory("finish")) { + if (GLUtils.checkGlErrors(getClass().getName() + ": finish").contains(GL.OUT_OF_MEMORY)) { BufferObject.checkBufferUsage(true); // FIXME also throw out some textures etc } diff --git a/vtm/src/org/oscim/renderer/OffscreenRenderer.java b/vtm/src/org/oscim/renderer/OffscreenRenderer.java index dd3f4a0f..069bea55 100644 --- a/vtm/src/org/oscim/renderer/OffscreenRenderer.java +++ b/vtm/src/org/oscim/renderer/OffscreenRenderer.java @@ -66,7 +66,7 @@ public class OffscreenRenderer extends LayerRenderer { gl.genTextures(1, buf); renderTex = buf.get(0); - GLUtils.checkGlError("0"); + GLUtils.checkGlError(getClass().getName() + ": 0"); gl.bindFramebuffer(GL.FRAMEBUFFER, fb); @@ -89,7 +89,7 @@ public class OffscreenRenderer extends LayerRenderer { GL.COLOR_ATTACHMENT0, GL.TEXTURE_2D, renderTex, 0); - GLUtils.checkGlError("1"); + GLUtils.checkGlError(getClass().getName() + ": 1"); if (useDepthTexture) { buf.clear(); @@ -128,17 +128,13 @@ public class OffscreenRenderer extends LayerRenderer { depthRenderbuffer); } - GLUtils.checkGlError("2"); + GLUtils.checkGlError(getClass().getName() + ": 2"); - int status = gl.checkFramebufferStatus(GL.FRAMEBUFFER); + int status = GLUtils.checkFramebufferStatus(getClass().getName()); gl.bindFramebuffer(GL.FRAMEBUFFER, 0); gl.bindTexture(GL.TEXTURE_2D, 0); - if (status != GL.FRAMEBUFFER_COMPLETE) { - log.debug("invalid framebuffer! " + status); - return false; - } - return true; + return status == GL.FRAMEBUFFER_COMPLETE; } public void enable(boolean on) { @@ -223,6 +219,6 @@ public class OffscreenRenderer extends LayerRenderer { GLState.test(false, false); GLState.blend(true); gl.drawArrays(GL.TRIANGLE_STRIP, 0, 4); - GLUtils.checkGlError("...."); + GLUtils.checkGlError(getClass().getName() + ": render() end"); } } diff --git a/vtm/src/org/oscim/renderer/bucket/TextureItem.java b/vtm/src/org/oscim/renderer/bucket/TextureItem.java index 55d43966..0a3bd8dd 100755 --- a/vtm/src/org/oscim/renderer/bucket/TextureItem.java +++ b/vtm/src/org/oscim/renderer/bucket/TextureItem.java @@ -305,7 +305,7 @@ public class TextureItem extends Inlist { gl.generateMipmap(GL.TEXTURE_2D); if (dbg) - GLUtils.checkGlError(TextureItem.class.getName()); + GLUtils.checkGlError(getClass().getName()); if (mUseBitmapPool) releaseBitmap(t);