content: package com.angcyo.pldroiddemo;
  
  import android.content.Context;
  import android.graphics.Bitmap;
  import android.opengl.GLES20;
  import android.opengl.GLUtils;
  import android.support.annotation.Nullable;
  import android.support.annotation.RawRes;
  import android.util.Log;
  
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.nio.ByteBuffer;
  import java.nio.ByteOrder;
  import java.nio.FloatBuffer;
  
  /**
   * Created by jerikc on 16/2/23.
   */
  public class GlUtil {
      private static final String TAG = "GlDemoUtil";
      /** Identity matrix for general use.  Don't modify or life will get weird. */
  
      public static final int NO_TEXTURE = -1;
  
      private static final int SIZEOF_FLOAT = 4;
  
      private GlUtil() { // do not instantiate
      }
  
      public static int createProgram(Context applicationContext, @RawRes int vertexSourceRawId,
                                      @RawRes int fragmentSourceRawId) {
  
          String vertexSource = readTextFromRawResource(applicationContext, vertexSourceRawId);
          String fragmentSource = readTextFromRawResource(applicationContext, fragmentSourceRawId);
  
          return createProgram(vertexSource, fragmentSource);
      }
  
      public static int createProgram(String vertexSource, String fragmentSource) {
          int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
          if (vertexShader == 0) {
              return 0;
          }
          int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
          if (pixelShader == 0) {
              return 0;
          }
          int program = GLES20.glCreateProgram();
          checkGlError("glCreateProgram");
          if (program == 0) {
              Log.e(TAG, "Could not create program");
          }
          GLES20.glAttachShader(program, vertexShader);
          checkGlError("glAttachShader");
          GLES20.glAttachShader(program, pixelShader);
          checkGlError("glAttachShader");
          GLES20.glLinkProgram(program);
          int[] linkStatus = new int[1];
          GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
          if (linkStatus[0] != GLES20.GL_TRUE) {
              Log.e(TAG, "Could not link program: ");
              Log.e(TAG, GLES20.glGetProgramInfoLog(program));
              GLES20.glDeleteProgram(program);
              program = 0;
          }
          Log.i(TAG, "linkStatus:" + linkStatus[0]);
          return program;
      }
  
      public static int loadShader(int shaderType, String source) {
          int shader = GLES20.glCreateShader(shaderType);
          checkGlError("glCreateShader type=" + shaderType);
          GLES20.glShaderSource(shader, source);
          GLES20.glCompileShader(shader);
          int[] compiled = new int[1];
          GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
          if (compiled[0] == 0) {
              Log.e(TAG, "Could not compile shader " + shaderType + ":");
              Log.e(TAG, " " + GLES20.glGetShaderInfoLog(shader));
              GLES20.glDeleteShader(shader);
              shader = 0;
          }
          return shader;
      }
  
      public static int createTexture(int textureTarget, @Nullable Bitmap bitmap, int minFilter,
                                      int magFilter, int wrapS, int wrapT) {
          int[] textureHandle = new int[1];
  
          GLES20.glGenTextures(1, textureHandle, 0);
          GlUtil.checkGlError("glGenTextures");
          GLES20.glBindTexture(textureTarget, textureHandle[0]);
          GlUtil.checkGlError("glBindTexture " + textureHandle[0]);
          GLES20.glTexParameterf(textureTarget, GLES20.GL_TEXTURE_MIN_FILTER, minFilter);
          GLES20.glTexParameterf(textureTarget, GLES20.GL_TEXTURE_MAG_FILTER, magFilter); //线性插值
          GLES20.glTexParameteri(textureTarget, GLES20.GL_TEXTURE_WRAP_S, wrapS);
          GLES20.glTexParameteri(textureTarget, GLES20.GL_TEXTURE_WRAP_T, wrapT);
  
          if (bitmap != null) {
              GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
          }
  
          GlUtil.checkGlError("glTexParameter");
          return textureHandle[0];
      }
  
      public static int createTexture(int textureTarget) {
          return createTexture(textureTarget, null, GLES20.GL_LINEAR, GLES20.GL_LINEAR,
                  GLES20.GL_CLAMP_TO_EDGE, GLES20.GL_CLAMP_TO_EDGE);
      }
  
      public static int createTexture(int textureTarget, Bitmap bitmap) {
          return createTexture(textureTarget, bitmap, GLES20.GL_LINEAR, GLES20.GL_LINEAR,
                  GLES20.GL_CLAMP_TO_EDGE, GLES20.GL_CLAMP_TO_EDGE);
      }
  
      /**
       * Checks to see if a GLES error has been raised.
       */
      public static void checkGlError(String op) {
          int error = GLES20.glGetError();
          if (error != GLES20.GL_NO_ERROR) {
              String msg = op + ": glError 0x" + Integer.toHexString(error);
              Log.e(TAG, msg);
              throw new RuntimeException(msg);
          }
      }
  
      /**
       * Allocates a direct float buffer, and populates it with the float array data.
       */
      public static FloatBuffer createFloatBuffer(float[] coords) {
          // Allocate a direct ByteBuffer, using 4 bytes per float, and copy coords into it.
          ByteBuffer bb = ByteBuffer.allocateDirect(coords.length * SIZEOF_FLOAT);
          bb.order(ByteOrder.nativeOrder());
          FloatBuffer fb = bb.asFloatBuffer();
          fb.put(coords);
          fb.position(0);
          return fb;
      }
  
      public static String readTextFromRawResource(final Context applicationContext,
                                                   @RawRes final int resourceId) {
          final InputStream inputStream =
                  applicationContext.getResources().openRawResource(resourceId);
          final InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
          final BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
          String nextLine;
          final StringBuilder body = new StringBuilder();
          try {
              while ((nextLine = bufferedReader.readLine()) != null) {
                  body.append(nextLine);
                  body.append('\n');
              }
          } catch (IOException e) {
              return null;
          }
  
          return body.toString();
      }
  }
  