@Override void drawImpl(GLShader shader, InternalTransform xform, int tex, int tint, float dx, float dy, float dw, float dh, float sl, float st, float sr, float sb) { if (tex > 0) { // we have to invert y here due to GL origin shenanigans ctx.quadShader(shader).prepareTexture(tex, tint).addQuad( xform, dx, dy, dx + dw, dy + dh, sl, 1-st, sr, 1-sb); } }
/** * Notes that this shader is no longer in use by a layer. This is used for reference counted * resource management. When all layers release a shader, it can destroy its shader programs and * release the GL resources it uses. */ public void release() { assert refs > 0 : "Released an shader with no references!"; if (--refs == 0) { clearProgram(); } }
/** * Forces the creation of our shader core. Used during GLContext.init to determine whether we * need to fall back to a less sophisticated quad shader. */ void createCore() { this.texEpoch = ctx.epoch(); this.texCore = createTextureCore(); }
public void flush(boolean deactivate) { if (curShader != null) { checkGLError("flush()"); curShader.flush(); if (deactivate) { curShader.deactivate(); curShader = null; } } }
protected static int convertToRepTex(GLContext ctx, int tex, int width, int height, boolean repeatX, boolean repeatY, boolean mipmapped) { int reptex = ctx.createTexture(width, height, repeatX, repeatY, mipmapped); int fbuf = ctx.createFramebuffer(reptex); ctx.pushFramebuffer(fbuf, width, height); try { // render the non-repeated texture into the framebuffer properly scaled ctx.clear(0, 0, 0, 0); GLShader shader = ctx.quadShader(null).prepareTexture(tex, Tint.NOOP_TINT); shader.addQuad(ctx.createTransform(), 0, height, width, 0, 0, 0, 1, 1); shader.flush(); // if we're mipmapped, we can now generate our mipmaps if (mipmapped) ctx.generateMipmap(reptex); return reptex; } finally { // we no longer need this framebuffer; rebind the previous framebuffer and delete ours ctx.popFramebuffer(); ctx.deleteFramebuffer(fbuf); } } }
@Override public Surface fillTriangles(float[] xys, float[] sxys, int xysOffset, int xysLen, int[] indices, int indicesOffset, int indicesLen, int indexBase) { bindFramebuffer(); if (fillPattern == null) throw new IllegalStateException("No fill pattern currently set"); int tex = fillPattern.ensureTexture(); if (tex > 0) { GLShader shader = ctx.trisShader(this.shader).prepareTexture(tex, tint); shader.addTriangles(topTransform(), xys, sxys, xysOffset, xysLen, indices, indicesOffset, indicesLen, indexBase); } return this; }
protected GLShader createQuadShader() { if (shouldTryQuadShader()) { try { GLShader quadShader = new QuadShader(this); quadShader.createCore(); // force core creation to test whether it fails return quadShader; } catch (Throwable t) { platform.reportError("Failed to create QuadShader", t); } } return new IndexedTrisShader(this); }
/** Called before each primitive to update the current color. */ public void prepare(int tex, int tint, boolean justActivated) { ctx.checkGLError("textureShader.prepare start"); boolean stateChanged = (tex != lastTex); if (!justActivated && stateChanged) { GLShader.this.flush(); ctx.checkGLError("textureShader.prepare flush"); } if (stateChanged) { lastTex = tex; ctx.checkGLError("textureShader.prepare end"); } if (justActivated) { ctx.activeTexture(GL20.GL_TEXTURE0); uTexture.bind(0); } }
float tw = parent.width(), th = parent.height(); float sl = this.x, st = this.y, sr = sl + this.width, sb = st + this.height; GLShader shader = ctx.quadShader(null).prepareTexture(tex, Tint.NOOP_TINT); shader.addQuad(ctx.createTransform(), 0, height, width, 0, sl / tw, st / th, sr / tw, sb / th); shader.flush();
@Override public Surface fillTriangles(float[] xys, int xysOffset, int xysLen, int[] indices, int indicesOffset, int indicesLen, int indexBase) { bindFramebuffer(); GLShader shader = ctx.trisShader(this.shader); if (fillPattern != null) { int tex = fillPattern.ensureTexture(); if (tex > 0) { shader.prepareTexture(tex, tint); shader.addTriangles(topTransform(), xys, xysOffset, xysLen, fillPattern.width(), fillPattern.height(), indices, indicesOffset, indicesLen, indexBase); } } else { int tex = ctx.fillImage().ensureTexture(); shader.prepareTexture(tex, Tint.combine(fillColor, tint)); shader.addTriangles(topTransform(), xys, xysOffset, xysLen, 1, 1, indices, indicesOffset, indicesLen, indexBase); } return this; }
/** Prepares this shader to render the specified texture, etc. */ public GLShader prepareTexture(int tex, int tint) { // if our GL context has been lost and regained we may need to recreate our core; we don't // destroy the old core because the underlying resources are gone and destroying using our // stale handles might result in destroying someone else's newly created resources if (texEpoch != ctx.epoch()) { texCore = null; } // create our core lazily so that we ensure we're on the GL thread when it happens if (texCore == null) { createCore(); } boolean justActivated = ctx.useShader(this); if (justActivated) { texCore.activate(ctx.curFbufWidth, ctx.curFbufHeight); if (GLContext.STATS_ENABLED) ctx.stats.shaderBinds++; } texCore.prepare(tex, tint, justActivated); return this; }
void drawImpl(GLShader shader, InternalTransform xform, int tex, int tint, float dx, float dy, float dw, float dh, float sl, float st, float sr, float sb) { if (tex > 0) { ctx.quadShader(shader).prepareTexture(tex, tint).addQuad( xform, dx, dy, dx + dw, dy + dh, sl, st, sr, sb); } }
public void run() { shader.clearProgram(); } });
void draw(GLShader shader, InternalTransform xform, int curTint) { if (tint != Tint.NOOP_TINT) curTint = Tint.combine(curTint, tint); // Draw this layer to the screen upside-down, because its contents are flipped (This happens // because it uses the same vertex program as everything else, which flips vertically to put // the origin at the top-left). ctx.quadShader(shader).prepareTexture(tex, curTint).addQuad( xform, 0, height, width, 0, 0, 0, 1, 1); }
public void init() { gl.glDisable(GL_CULL_FACE); gl.glEnable(GL_BLEND); gl.glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); gl.glClearColor(0, 0, 0, 1); if (quadShader != null) { quadShader.clearProgram(); } if (trisShader != null) { trisShader.clearProgram(); } quadShader = createQuadShader(); trisShader = new IndexedTrisShader(this); checkGLError("initGL"); }
@Override public Surface fillRect(float x, float y, float width, float height) { bindFramebuffer(); GLShader shader = ctx.quadShader(this.shader); if (fillPattern != null) { int tex = fillPattern.ensureTexture(); if (tex > 0) { shader.prepareTexture(tex, tint); float tw = fillPattern.width(), th = fillPattern.height(), r = x+width, b = y+height; shader.addQuad(topTransform(), x, y, x+width, y+height, x / tw, y / th, r / tw, b / th); } } else { int tex = ctx.fillImage().ensureTexture(); shader.prepareTexture(tex, Tint.combine(fillColor, tint)); shader.addQuad(topTransform(), x, y, x+width, y+height, 0, 0, 1, 1); } return this; }
@Override public void onSurfaceCreated() { createTexture(); if (cachedPixels != null) { try { AndroidGLContext actx = (AndroidGLContext) ctx; ByteBuffer pixelBuffer = ByteBuffer.allocate(texWidth * texHeight * 4); FileInputStream in = new FileInputStream(cachedPixels); in.read(pixelBuffer.array()); in.close(); int bufferTex = actx.createTexture(false, false, false); actx.gl.glTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_RGBA, texWidth, texHeight, 0, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, pixelBuffer); // bind our surface framebuffer and render the saved texture data into it bindFramebuffer(); ctx.quadShader(null).prepareTexture(bufferTex, Tint.NOOP_TINT).addQuad( StockInternalTransform.IDENTITY, 0, texHeight, texWidth, 0, 0, 0, 1, 1); // rebind the default frame buffer (which will flush the rendering operation) ctx.bindFramebuffer(); ctx.destroyTexture(bufferTex); pixelBuffer = null; cachedPixels.delete(); cachedPixels = null; } catch (IOException e) { PlayN.reportError("Error reading cached surface pixels from file.", e); } } }
@Override public void onSurfaceCreated() { createTexture(); if (cachedPixels != null) { try { AndroidGLContext actx = (AndroidGLContext) ctx; ByteBuffer pixelBuffer = ByteBuffer.allocate(texWidth * texHeight * 4); FileInputStream in = new FileInputStream(cachedPixels); in.read(pixelBuffer.array()); in.close(); int bufferTex = actx.createTexture(false, false, false); actx.gl.glTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_RGBA, texWidth, texHeight, 0, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, pixelBuffer); // bind our surface framebuffer and render the saved texture data into it bindFramebuffer(); ctx.quadShader(null).prepareTexture(bufferTex, Tint.NOOP_TINT).addQuad( StockInternalTransform.IDENTITY, 0, texHeight, texWidth, 0, 0, 0, 1, 1); // rebind the default frame buffer (which will flush the rendering operation) ctx.bindFramebuffer(); ctx.destroyTexture(bufferTex); pixelBuffer = null; cachedPixels.delete(); cachedPixels = null; } catch (IOException e) { PlayN.reportError("Error reading cached surface pixels from file.", e); } } }
int tex = fillPattern.ensureTexture(); if (tex > 0) { shader.prepareTexture(tex, tint); shader.addQuad(l, 0, 0, length, width, 0, 0, length/fillPattern.width(), width/fillPattern.height()); shader.prepareTexture(tex, Tint.combine(fillColor, tint)); shader.addQuad(l, 0, 0, length, width, 0, 0, 1, 1);