static void init(int num) {
    pool = null;

    TextureObject to;

    int[] textureIds = new int[num];
    GLES20.glGenTextures(num, textureIds, 0);

    for (int i = 1; i < num; i++) {
      initTexture(textureIds[i]);
      to = new TextureObject(textureIds[i]);

      to.next = pool;
      pool = to;
    }

    mBitmaps = new ArrayList<Bitmap>(10);

    for (int i = 0; i < 4; i++) {
      Bitmap bitmap = Bitmap.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT, Bitmap.Config.ARGB_8888);

      mBitmaps.add(bitmap);
    }

    mBitmapFormat = GLUtils.getInternalFormat(mBitmaps.get(0));
    mBitmapType = GLUtils.getType(mBitmaps.get(0));
  }
  public static void uploadTexture(
      TextureObject to, Bitmap bitmap, int format, int type, int w, int h) {

    if (to == null) {
      Log.d("...", "no texture!");
      return;
    }
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, to.id);
    if (to.width == w && to.height == h)
      GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, bitmap, format, type);
    else {
      GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, format, bitmap, type, 0);
      to.width = w;
      to.height = h;
    }
  }
  public static synchronized void uploadTexture(TextureObject to) {
    if (TextureRenderer.debug) Log.d("...", "upload texture " + to.id);

    if (to.id < 0) {
      int[] textureIds = new int[1];
      GLES20.glGenTextures(1, textureIds, 0);
      to.id = textureIds[0];
      initTexture(to.id);
      if (TextureRenderer.debug) Log.d("...", "new texture " + to.id);
    }

    uploadTexture(to, to.bitmap, mBitmapFormat, mBitmapType, TEXTURE_WIDTH, TEXTURE_HEIGHT);

    mBitmaps.add(to.bitmap);
    to.bitmap = null;
  }
  public static synchronized void release(TextureObject to) {
    while (to != null) {
      if (TextureRenderer.debug) Log.d("...", "release texture " + to.id);

      TextureObject next = to.next;

      if (to.bitmap != null) {
        mBitmaps.add(to.bitmap);
        to.bitmap = null;
      }

      to.next = pool;
      pool = to;

      to = next;
    }
  }
  public static synchronized TextureObject get() {
    TextureObject to;

    if (pool == null) {
      objectCount += 1;
      if (TextureRenderer.debug) Log.d("...", "textures: " + objectCount);
      pool = new TextureObject(-1);
    }

    to = pool;
    pool = pool.next;

    to.next = null;

    to.bitmap = getBitmap();
    to.bitmap.eraseColor(Color.TRANSPARENT);

    if (TextureRenderer.debug) Log.d("...", "get texture " + to.id + " " + to.bitmap);

    return to;
  }