- keep track of vertex array state in GLRenderer.enableVertexArrays

- use static imports for GL functions
This commit is contained in:
Hannes Janetzek 2012-12-29 23:39:25 +01:00
parent a8b25d07ad
commit 45cf6620a9
4 changed files with 80 additions and 132 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 Hannes Janetzek * Copyright 2012 OpenScienceMap
* *
* This program is free software: you can redistribute it and/or modify it under the * This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General License as published by the Free Software * terms of the GNU Lesser General License as published by the Free Software
@ -14,6 +14,17 @@
*/ */
package org.oscim.renderer; package org.oscim.renderer;
import static android.opengl.GLES20.GL_SHORT;
import static android.opengl.GLES20.GL_TRIANGLE_STRIP;
import static android.opengl.GLES20.glDrawArrays;
import static android.opengl.GLES20.glGetAttribLocation;
import static android.opengl.GLES20.glGetUniformLocation;
import static android.opengl.GLES20.glUniform1f;
import static android.opengl.GLES20.glUniform1i;
import static android.opengl.GLES20.glUniformMatrix4fv;
import static android.opengl.GLES20.glUseProgram;
import static android.opengl.GLES20.glVertexAttribPointer;
import org.oscim.core.MapPosition; import org.oscim.core.MapPosition;
import org.oscim.renderer.layer.Layer; import org.oscim.renderer.layer.Layer;
import org.oscim.renderer.layer.LineLayer; import org.oscim.renderer.layer.LineLayer;
@ -21,16 +32,15 @@ import org.oscim.theme.renderinstruction.Line;
import org.oscim.utils.GlUtils; import org.oscim.utils.GlUtils;
import android.graphics.Paint.Cap; import android.graphics.Paint.Cap;
import android.opengl.GLES20;
import android.util.Log; import android.util.Log;
// FIXME make sure coordinates are in valid range for short /**
* @author Hannes Janetzek
*/
public final class LineRenderer { public final class LineRenderer {
private final static String TAG = "LineRenderer"; private final static String TAG = "LineRenderer";
// private static int NUM_VERTEX_SHORTS = 4;
private static final int LINE_VERTICES_DATA_POS_OFFSET = 0; private static final int LINE_VERTICES_DATA_POS_OFFSET = 0;
private static final int LINE_VERTICES_DATA_TEX_OFFSET = 4; private static final int LINE_VERTICES_DATA_TEX_OFFSET = 4;
@ -52,15 +62,6 @@ public final class LineRenderer {
return false; return false;
} }
hLineMatrix[0] = GLES20.glGetUniformLocation(lineProgram[0], "u_mvp");
hLineScale[0] = GLES20.glGetUniformLocation(lineProgram[0], "u_wscale");
hLineWidth[0] = GLES20.glGetUniformLocation(lineProgram[0], "u_width");
hLineColor[0] = GLES20.glGetUniformLocation(lineProgram[0], "u_color");
hLineMode[0] = GLES20.glGetUniformLocation(lineProgram[0], "u_mode");
hLineVertexPosition[0] = GLES20.glGetAttribLocation(lineProgram[0], "a_position");
hLineTexturePosition[0] = GLES20.glGetAttribLocation(lineProgram[0], "a_st");
lineProgram[1] = GlUtils.createProgram(Shaders.lineVertexShader, lineProgram[1] = GlUtils.createProgram(Shaders.lineVertexShader,
Shaders.lineSimpleFragmentShader); Shaders.lineSimpleFragmentShader);
if (lineProgram[1] == 0) { if (lineProgram[1] == 0) {
@ -68,15 +69,15 @@ public final class LineRenderer {
return false; return false;
} }
hLineMatrix[1] = GLES20.glGetUniformLocation(lineProgram[1], "u_mvp"); for (int i = 0; i < 2; i++) {
hLineScale[1] = GLES20.glGetUniformLocation(lineProgram[1], "u_wscale"); hLineMatrix[i] = glGetUniformLocation(lineProgram[i], "u_mvp");
hLineWidth[1] = GLES20.glGetUniformLocation(lineProgram[1], "u_width"); hLineScale[i] = glGetUniformLocation(lineProgram[i], "u_wscale");
hLineColor[1] = GLES20.glGetUniformLocation(lineProgram[1], "u_color"); hLineWidth[i] = glGetUniformLocation(lineProgram[i], "u_width");
hLineMode[1] = GLES20.glGetUniformLocation(lineProgram[1], "u_mode"); hLineColor[i] = glGetUniformLocation(lineProgram[i], "u_color");
hLineMode[i] = glGetUniformLocation(lineProgram[i], "u_mode");
hLineVertexPosition[1] = GLES20.glGetAttribLocation(lineProgram[1], "a_position"); hLineVertexPosition[i] = glGetAttribLocation(lineProgram[i], "a_position");
hLineTexturePosition[1] = GLES20.glGetAttribLocation(lineProgram[1], "a_st"); hLineTexturePosition[i] = glGetAttribLocation(lineProgram[i], "a_st");
}
return true; return true;
} }
@ -89,35 +90,22 @@ public final class LineRenderer {
if (layer == null) if (layer == null)
return null; return null;
GLES20.glUseProgram(lineProgram[mode]); glUseProgram(lineProgram[mode]);
int uLineScale = hLineScale[mode]; int uLineScale = hLineScale[mode];
int uLineMode = hLineMode[mode]; int uLineMode = hLineMode[mode];
int uLineColor = hLineColor[mode]; int uLineColor = hLineColor[mode];
int uLineWidth = hLineWidth[mode]; int uLineWidth = hLineWidth[mode];
// int va = hLineVertexPosition[mode]; GLRenderer.enableVertexArrays(hLineVertexPosition[mode], hLineTexturePosition[mode]);
// if (!GLRenderer.vertexArray[va]) {
// GLES20.glEnableVertexAttribArray(va);
// GLRenderer.vertexArray[va] = true;
// }
// va = hLineTexturePosition[mode]; glVertexAttribPointer(hLineVertexPosition[mode], 2, GL_SHORT,
// if (!GLRenderer.vertexArray[va]) {
// GLES20.glEnableVertexAttribArray(va);
// GLRenderer.vertexArray[va] = true;
// }
GLES20.glEnableVertexAttribArray(hLineVertexPosition[mode]);
GLES20.glEnableVertexAttribArray(hLineTexturePosition[mode]);
GLES20.glVertexAttribPointer(hLineVertexPosition[mode], 2, GLES20.GL_SHORT,
false, 8, bufferOffset + LINE_VERTICES_DATA_POS_OFFSET); false, 8, bufferOffset + LINE_VERTICES_DATA_POS_OFFSET);
GLES20.glVertexAttribPointer(hLineTexturePosition[mode], 2, GLES20.GL_SHORT, glVertexAttribPointer(hLineTexturePosition[mode], 2, GL_SHORT,
false, 8, bufferOffset + LINE_VERTICES_DATA_TEX_OFFSET); false, 8, bufferOffset + LINE_VERTICES_DATA_TEX_OFFSET);
GLES20.glUniformMatrix4fv(hLineMatrix[mode], 1, false, matrix, 0); glUniformMatrix4fv(hLineMatrix[mode], 1, false, matrix, 0);
// scale factor to map one pixel on tile to one pixel on screen: // scale factor to map one pixel on tile to one pixel on screen:
// only works with orthographic projection // only works with orthographic projection
@ -127,9 +115,9 @@ public final class LineRenderer {
if (mode == 1) if (mode == 1)
pixel = 1.5f / s; pixel = 1.5f / s;
GLES20.glUniform1f(uLineScale, pixel); glUniform1f(uLineScale, pixel);
int lineMode = 0; int lineMode = 0;
GLES20.glUniform1i(uLineMode, lineMode); glUniform1i(uLineMode, lineMode);
// line scale factor (for non fixed lines) // line scale factor (for non fixed lines)
float lineScale = (float) Math.sqrt(s); float lineScale = (float) Math.sqrt(s);
@ -155,11 +143,12 @@ public final class LineRenderer {
GlUtils.setColor(uLineColor, line.color, alpha); GlUtils.setColor(uLineColor, line.color, alpha);
if (blur && line.blur == 0) { if (blur && line.blur == 0) {
GLES20.glUniform1f(uLineScale, pixel); glUniform1f(uLineScale, pixel);
blur = false; blur = false;
} }
if (line.outline) { if (line.outline) {
// draw outline for linelayers references by this outline
for (LineLayer o = ll.outlines; o != null; o = o.outlines) { for (LineLayer o = ll.outlines; o != null; o = o.outlines) {
if (o.line.fixed || strokeMaxZoom) { if (o.line.fixed || strokeMaxZoom) {
@ -168,25 +157,25 @@ public final class LineRenderer {
width = ll.width / s + o.width / lineScale; width = ll.width / s + o.width / lineScale;
} }
GLES20.glUniform1f(uLineWidth, width); glUniform1f(uLineWidth, width);
if (line.blur != 0) { if (line.blur != 0) {
blurScale = (ll.width + o.width) / s - (line.blur / s); blurScale = (ll.width + o.width) / s - (line.blur / s);
GLES20.glUniform1f(uLineScale, blurScale); glUniform1f(uLineScale, blurScale);
blur = true; blur = true;
} }
if (o.line.cap == Cap.ROUND) { if (o.line.cap == Cap.ROUND) {
if (lineMode != 1) { if (lineMode != 1) {
lineMode = 1; lineMode = 1;
GLES20.glUniform1i(uLineMode, lineMode); glUniform1i(uLineMode, lineMode);
} }
} else if (lineMode != 0) { } else if (lineMode != 0) {
lineMode = 0; lineMode = 0;
GLES20.glUniform1i(uLineMode, lineMode); glUniform1i(uLineMode, lineMode);
} }
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, o.offset, o.verticesCnt); glDrawArrays(GL_TRIANGLE_STRIP, o.offset, o.verticesCnt);
} }
} else { } else {
@ -198,32 +187,28 @@ public final class LineRenderer {
width = ll.width / lineScale; width = ll.width / lineScale;
} }
GLES20.glUniform1f(uLineWidth, width); glUniform1f(uLineWidth, width);
if (line.blur != 0) { if (line.blur != 0) {
blurScale = (ll.width / lineScale) * line.blur; blurScale = (ll.width / lineScale) * line.blur;
GLES20.glUniform1f(uLineScale, blurScale); glUniform1f(uLineScale, blurScale);
blur = true; blur = true;
} }
if (line.cap == Cap.ROUND) { if (line.cap == Cap.ROUND) {
if (lineMode != 1) { if (lineMode != 1) {
lineMode = 1; lineMode = 1;
GLES20.glUniform1i(uLineMode, lineMode); glUniform1i(uLineMode, lineMode);
} }
} else if (lineMode != 0) { } else if (lineMode != 0) {
lineMode = 0; lineMode = 0;
GLES20.glUniform1i(uLineMode, lineMode); glUniform1i(uLineMode, lineMode);
} }
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, l.offset, l.verticesCnt); glDrawArrays(GL_TRIANGLE_STRIP, l.offset, l.verticesCnt);
} }
} }
GLES20.glDisableVertexAttribArray(hLineVertexPosition[mode]);
GLES20.glDisableVertexAttribArray(hLineTexturePosition[mode]);
return l; return l;
} }
} }

View File

@ -14,14 +14,20 @@
*/ */
package org.oscim.renderer; package org.oscim.renderer;
import static android.opengl.GLES20.GL_ALWAYS;
import static android.opengl.GLES20.GL_BLEND; import static android.opengl.GLES20.GL_BLEND;
import static android.opengl.GLES20.GL_DEPTH_TEST;
import static android.opengl.GLES20.GL_EQUAL; import static android.opengl.GLES20.GL_EQUAL;
import static android.opengl.GLES20.GL_INVERT; import static android.opengl.GLES20.GL_INVERT;
import static android.opengl.GLES20.GL_LESS;
import static android.opengl.GLES20.GL_SHORT;
import static android.opengl.GLES20.GL_STENCIL_TEST; import static android.opengl.GLES20.GL_STENCIL_TEST;
import static android.opengl.GLES20.GL_TRIANGLE_FAN; import static android.opengl.GLES20.GL_TRIANGLE_FAN;
import static android.opengl.GLES20.GL_TRIANGLE_STRIP; import static android.opengl.GLES20.GL_TRIANGLE_STRIP;
import static android.opengl.GLES20.GL_ZERO; import static android.opengl.GLES20.GL_ZERO;
import static android.opengl.GLES20.glColorMask; import static android.opengl.GLES20.glColorMask;
import static android.opengl.GLES20.glDepthFunc;
import static android.opengl.GLES20.glDepthMask;
import static android.opengl.GLES20.glDisable; import static android.opengl.GLES20.glDisable;
import static android.opengl.GLES20.glDrawArrays; import static android.opengl.GLES20.glDrawArrays;
import static android.opengl.GLES20.glEnable; import static android.opengl.GLES20.glEnable;
@ -162,27 +168,16 @@ public final class PolygonRenderer {
private static int mStart; private static int mStart;
public static Layer draw(MapPosition pos, Layer layer, public static Layer draw(MapPosition pos, Layer layer,
float[] matrix, boolean first, boolean clip) { float[] matrix, boolean first, boolean drawClip) {
int zoom = pos.zoomLevel; int zoom = pos.zoomLevel;
float scale = pos.scale; float scale = pos.scale;
glUseProgram(polygonProgram); glUseProgram(polygonProgram);
// int va = hPolygonVertexPosition; GLRenderer.enableVertexArrays(hPolygonVertexPosition, -1);
// if (!GLRenderer.vertexArray[va]) {
// GLES20.glEnableVertexAttribArray(va);
// GLRenderer.vertexArray[va] = true;
// }
// va = va == 0 ? 1 : 0;
// if (GLRenderer.vertexArray[va]) {
// GLES20.glDisableVertexAttribArray(va);
// GLRenderer.vertexArray[va] = false;
// }
GLES20.glEnableVertexAttribArray(hPolygonVertexPosition); glVertexAttribPointer(hPolygonVertexPosition, 2, GL_SHORT,
glVertexAttribPointer(hPolygonVertexPosition, 2, GLES20.GL_SHORT,
false, 0, POLYGON_VERTICES_DATA_POS_OFFSET); false, 0, POLYGON_VERTICES_DATA_POS_OFFSET);
glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0); glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0);
@ -212,41 +207,41 @@ public final class PolygonRenderer {
glColorMask(false, false, false, false); glColorMask(false, false, false, false);
// never pass the test: always apply fail op // never pass the test: always apply fail op
glStencilFunc(GLES20.GL_ALWAYS, 0, 0xFF); glStencilFunc(GL_ALWAYS, 0, 0xFF);
glStencilMask(0xFF); glStencilMask(0xFF);
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
if (clip) { if (drawClip) {
// draw clip-region into depth buffer: // draw clip-region into depth buffer:
// this is used for lines and polygons // this is used for lines and polygons
// write to depth buffer // write to depth buffer
GLES20.glDepthMask(true); glDepthMask(true);
// to prevent overdraw gl_less restricts // to prevent overdraw gl_less restricts
// the clip to the area where no other // the clip to the area where no other
// tile has drawn // tile has drawn
GLES20.glDepthFunc(GLES20.GL_LESS); glDepthFunc(GL_LESS);
} }
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if (clip) { if (drawClip) {
first = false; first = false;
clip = false; drawClip = false;
// dont modify depth buffer // dont modify depth buffer
GLES20.glDepthMask(false); glDepthMask(false);
// only draw to this tile // only draw to this tile
GLES20.glDepthFunc(GLES20.GL_EQUAL); glDepthFunc(GL_EQUAL);
} }
// stencil op for stencil method polygon drawing // stencil op for stencil method polygon drawing
glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT); glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
// no need for depth test while drawing stencil // no need for depth test while drawing stencil
if (clip) if (drawClip)
glDisable(GLES20.GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
} }
// else if (mCount == mStart) { // else if (mCount == mStart) {
@ -254,14 +249,14 @@ public final class PolygonRenderer {
// glColorMask(false, false, false, false); // glColorMask(false, false, false, false);
// //
// // never pass the test: always apply fail op // // never pass the test: always apply fail op
// glStencilFunc(GLES20.GL_ALWAYS, 0, 0xFF); // glStencilFunc(GL_ALWAYS, 0, 0xFF);
// //
// // stencil op for stencil method polygon drawing // // stencil op for stencil method polygon drawing
// glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT); // glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
// //
// // no need for depth test while drawing stencil // // no need for depth test while drawing stencil
// if (clip) // if (clip)
// glDisable(GLES20.GL_DEPTH_TEST); // glDisable(GL_DEPTH_TEST);
// } // }
mFillPolys[mCount] = pl; mFillPolys[mCount] = pl;
@ -274,8 +269,8 @@ public final class PolygonRenderer {
// draw up to 8 layers into stencil buffer // draw up to 8 layers into stencil buffer
if (mCount == STENCIL_BITS) { if (mCount == STENCIL_BITS) {
/* only draw where nothing was drawn yet */ /* only draw where nothing was drawn yet */
if (clip) if (drawClip)
glEnable(GLES20.GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
fillPolygons(zoom, scale); fillPolygons(zoom, scale);
mCount = 0; mCount = 0;
@ -285,8 +280,8 @@ public final class PolygonRenderer {
if (mCount > 0) { if (mCount > 0) {
/* only draw where nothing was drawn yet */ /* only draw where nothing was drawn yet */
if (clip) if (drawClip)
glEnable(GLES20.GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
fillPolygons(zoom, scale); fillPolygons(zoom, scale);
} }
@ -298,11 +293,9 @@ public final class PolygonRenderer {
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
if (clip && first) if (drawClip && first)
drawDepthClip(); drawDepthClip();
GLES20.glDisableVertexAttribArray(hPolygonVertexPosition);
return l; return l;
} }

View File

@ -24,7 +24,6 @@ import org.oscim.renderer.layer.TextureLayer;
import org.oscim.utils.GlUtils; import org.oscim.utils.GlUtils;
import android.opengl.GLES20; import android.opengl.GLES20;
import android.util.FloatMath;
import android.util.Log; import android.util.Log;
public final class TextureRenderer { public final class TextureRenderer {
@ -97,23 +96,13 @@ public final class TextureRenderer {
// GlUtils.checkGlError("draw texture >"); // GlUtils.checkGlError("draw texture >");
GLES20.glUseProgram(mTextureProgram); GLES20.glUseProgram(mTextureProgram);
int va = hTextureTexCoord; GLRenderer.enableVertexArrays(hTextureTexCoord, hTextureVertex);
//if (!GLRenderer.vertexArray[va]) {
GLES20.glEnableVertexAttribArray(va);
// GLRenderer.vertexArray[va] = true;
//}
va = hTextureVertex;
//if (!GLRenderer.vertexArray[va]) {
GLES20.glEnableVertexAttribArray(va);
// GLRenderer.vertexArray[va] = true;
//}
TextureLayer tl = (TextureLayer) layer; TextureLayer tl = (TextureLayer) layer;
if (tl.fixed) if (tl.fixed)
GLES20.glUniform1f(hTextureScale, FloatMath.sqrt(scale)); GLES20.glUniform1f(hTextureScale, (float) Math.sqrt(scale));
else else
GLES20.glUniform1f(hTextureScale, 1); GLES20.glUniform1f(hTextureScale, 1);
@ -155,9 +144,6 @@ public final class TextureRenderer {
// GlUtils.checkGlError("< draw texture"); // GlUtils.checkGlError("< draw texture");
GLES20.glDisableVertexAttribArray(hTextureVertex);
GLES20.glDisableVertexAttribArray(hTextureTexCoord);
return layer.next; return layer.next;
} }
} }

View File

@ -424,13 +424,9 @@ public final class LineLayer extends Layer {
// For rounded line edges // For rounded line edges
ddx = (int) ((ux - vx) * DIR_SCALE); ddx = (int) ((ux - vx) * DIR_SCALE);
ddy = (int) ((uy - vy) * DIR_SCALE); ddy = (int) ((uy - vy) * DIR_SCALE);
dx = (short) (0 | ddx & DIR_MASK);
dy = (short) (0 | ddy & DIR_MASK);
if (flip) { dx = (short) (0 | (flip ? -ddx : ddx) & DIR_MASK);
ddx *= -1; dy = (short) (0 | (flip ? -ddy : ddy) & DIR_MASK);
ddy *= -1;
}
v[opos++] = ox; v[opos++] = ox;
v[opos++] = oy; v[opos++] = oy;
@ -446,13 +442,8 @@ public final class LineLayer extends Layer {
// add last vertex twice // add last vertex twice
ddx = (int) (-(ux + vx) * DIR_SCALE); ddx = (int) (-(ux + vx) * DIR_SCALE);
ddy = (int) (-(uy + vy) * DIR_SCALE); ddy = (int) (-(uy + vy) * DIR_SCALE);
dx = (short) (2 | ddx & DIR_MASK); dx = (short) (2 | (flip ? -ddx : ddx) & DIR_MASK);
dy = (short) (0 | ddy & DIR_MASK); dy = (short) (0 | (flip ? -ddy : ddy) & DIR_MASK);
if (flip) {
ddx *= -1;
ddy *= -1;
}
v[opos++] = ox; v[opos++] = ox;
v[opos++] = oy; v[opos++] = oy;
@ -484,14 +475,11 @@ public final class LineLayer extends Layer {
ddx = (int) ((ux - vx) * DIR_SCALE); ddx = (int) ((ux - vx) * DIR_SCALE);
ddy = (int) ((uy - vy) * DIR_SCALE); ddy = (int) ((uy - vy) * DIR_SCALE);
if (flip) {
ddx *= -1;
ddy *= -1;
}
v[opos++] = ox; v[opos++] = ox;
v[opos++] = oy; v[opos++] = oy;
v[opos++] = (short) (0 | ddx & DIR_MASK); v[opos++] = (short) (0 | (flip ? -ddx : ddx) & DIR_MASK);
v[opos++] = (short) (1 | ddy & DIR_MASK); v[opos++] = (short) (1 | (flip ? -ddy : ddy) & DIR_MASK);
if (opos == VertexPoolItem.SIZE) { if (opos == VertexPoolItem.SIZE) {
si = si.next = VertexPool.get(); si = si.next = VertexPool.get();
@ -502,12 +490,8 @@ public final class LineLayer extends Layer {
// add last vertex twice // add last vertex twice
ddx = (int) (-(ux + vx) * DIR_SCALE); ddx = (int) (-(ux + vx) * DIR_SCALE);
ddy = (int) (-(uy + vy) * DIR_SCALE); ddy = (int) (-(uy + vy) * DIR_SCALE);
if (flip) { dx = (short) (2 | (flip ? -ddx : ddx) & DIR_MASK);
ddx *= -1; dy = (short) (1 | (flip ? -ddy : ddy) & DIR_MASK);
ddy *= -1;
}
dx = (short) (2 | ddx & DIR_MASK);
dy = (short) (1 | ddy & DIR_MASK);
v[opos++] = ox; v[opos++] = ox;
v[opos++] = oy; v[opos++] = oy;