/* * Copyright (C) 2016 eschao <esc.chao@gmail.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.eschao.android.widget.pageflip; import android.content.Context; import static android.opengl.GLES20.GL_FRAGMENT_SHADER; import static android.opengl.GLES20.GL_LINK_STATUS; import static android.opengl.GLES20.GL_VERTEX_SHADER; import static android.opengl.GLES20.glAttachShader; import static android.opengl.GLES20.glCreateProgram; import static android.opengl.GLES20.glDeleteProgram; import static android.opengl.GLES20.glGetProgramiv; import static android.opengl.GLES20.glLinkProgram; import static android.opengl.GLES20.glUseProgram; /** * GLSL program class is used to load, compile and link shader scripts * * @author eschao */ public class GLProgram { // invalid GL getShaderRef including program reference and variable location protected final int INVALID_GL_HANDLE = -1; // GLSL program reference protected int mProgramRef; // Vertex shader protected GLShader mVertex; // Fragment shader protected GLShader mFragment; public GLProgram() { mProgramRef = INVALID_GL_HANDLE; mVertex = new GLShader(); mFragment = new GLShader(); } /** * Initiate with given vertex shader and fragment shader * * @param context android context * @param vertexResId vertex shader script id * @param fragmentResId fragment shader script id * @return self * @throws PageFlipException if fail to read or compile shader scripts */ public GLProgram init(Context context, int vertexResId, int fragmentResId) throws PageFlipException { // 1. init shader try { mVertex.compile(context, GL_VERTEX_SHADER, vertexResId); mFragment.compile(context, GL_FRAGMENT_SHADER, fragmentResId); } catch (PageFlipException e) { mVertex.delete(); mFragment.delete(); throw e; } // 2. create texture program and link shader mProgramRef = glCreateProgram(); if (mProgramRef == 0) { mVertex.delete(); mFragment.delete(); throw new PageFlipException("Can't create texture program"); } // 3. attach vertex and fragment shader glAttachShader(mProgramRef, mVertex.getShaderRef()); glAttachShader(mProgramRef, mFragment.getShaderRef()); glLinkProgram(mProgramRef); // 4. check shader link status int[] result = new int[1]; glGetProgramiv(mProgramRef, GL_LINK_STATUS, result, 0); if (result[0] == 0) { delete(); throw new PageFlipException("Can't link program"); } // 5. get all variable handles defined in scripts // subclass should implement getVarsLocation to be responsible for its // own variables in script glUseProgram(mProgramRef); getVarsLocation(); return this; } /** * Delete all handles */ public void delete() { mVertex.delete(); mFragment.delete(); if (mProgramRef != INVALID_GL_HANDLE) { glDeleteProgram(mProgramRef); mProgramRef = INVALID_GL_HANDLE; } } /** * Get program GL reference * * @return program GL reference for program */ public int getProgramRef() { return mProgramRef; } /** * Subclass should implement it to get its own variable handles which are * defined in its shader scripts */ protected void getVarsLocation() { } }