// Path: src/com/android/launcher3/wallpaperpicker/common/Utils.java
// public class Utils {
//     private static final String TAG = "Utils";
// 
//     // Throws AssertionError if the input is false.
//     public static void assertTrue(boolean cond) {
//         if (!cond) {
//             throw new AssertionError();
//         }
//     }
// 
//     // Returns the next power of two.
//     // Returns the input if it is already power of 2.
//     // Throws IllegalArgumentException if the input is <= 0 or
//     // the answer overflows.
//     public static int nextPowerOf2(int n) {
//         if (n <= 0 || n > (1 << 30)) throw new IllegalArgumentException("n is invalid: " + n);
//         n -= 1;
//         n |= n >> 16;
//         n |= n >> 8;
//         n |= n >> 4;
//         n |= n >> 2;
//         n |= n >> 1;
//         return n + 1;
//     }
// 
//     // Returns the previous power of two.
//     // Returns the input if it is already power of 2.
//     // Throws IllegalArgumentException if the input is <= 0
//     public static int prevPowerOf2(int n) {
//         if (n <= 0) throw new IllegalArgumentException();
//         return Integer.highestOneBit(n);
//     }
// 
//     // Returns the input value x clamped to the range [min, max].
//     public static int clamp(int x, int min, int max) {
//         if (x > max) return max;
//         if (x < min) return min;
//         return x;
//     }
// 
//     public static int ceilLog2(float value) {
//         int i;
//         for (i = 0; i < 31; i++) {
//             if ((1 << i) >= value) break;
//         }
//         return i;
//     }
// 
//     public static int floorLog2(float value) {
//         int i;
//         for (i = 0; i < 31; i++) {
//             if ((1 << i) > value) break;
//         }
//         return i - 1;
//     }
// 
//     public static void closeSilently(Closeable c) {
//         if (c == null) return;
//         try {
//             c.close();
//         } catch (IOException t) {
//             Log.w(TAG, "close fail ", t);
//         }
//     }
// 
//     public static RectF getMaxCropRect(
//             int inWidth, int inHeight, int outWidth, int outHeight, boolean leftAligned) {
//         RectF cropRect = new RectF();
//         // Get a crop rect that will fit this
//         if (inWidth / (float) inHeight > outWidth / (float) outHeight) {
//             cropRect.top = 0;
//             cropRect.bottom = inHeight;
//             cropRect.left = (inWidth - (outWidth / (float) outHeight) * inHeight) / 2;
//             cropRect.right = inWidth - cropRect.left;
//             if (leftAligned) {
//                 cropRect.right -= cropRect.left;
//                 cropRect.left = 0;
//             }
//         } else {
//             cropRect.left = 0;
//             cropRect.right = inWidth;
//             cropRect.top = (inHeight - (outHeight / (float) outWidth) * inWidth) / 2;
//             cropRect.bottom = inHeight - cropRect.top;
//         }
//         return cropRect;
//     }
// 
//     /**
//      * Find the min x that 1 / x >= scale
//      */
//     public static int computeSampleSizeLarger(float scale) {
//         int initialSize = (int) Math.floor(1f / scale);
//         if (initialSize <= 1) return 1;
//         return initialSize <= 8 ? prevPowerOf2(initialSize) : (initialSize / 8 * 8);
//     }
// }


import android.util.Log;
import com.android.launcher3.wallpaperpicker.common.Utils;
import java.util.WeakHashMap;
    protected GLCanvas mCanvasRef = null;
    private static WeakHashMap<BasicTexture, Object> sAllTextures
            = new WeakHashMap<>();
    private static ThreadLocal<Class<BasicTexture>> sInFinalizer = new ThreadLocal<>();

    protected BasicTexture(GLCanvas canvas, int id, int state) {
        setAssociatedCanvas(canvas);
        mId = id;
        mState = state;
        synchronized (sAllTextures) {
            sAllTextures.put(this, null);
        }
    }

    protected BasicTexture() {
        this(null, 0, STATE_UNLOADED);
    }

    protected void setAssociatedCanvas(GLCanvas canvas) {
        mCanvasRef = canvas;
    }

    /**
     * Sets the content size of this texture. In OpenGL, the actual texture
     * size must be of power of 2, the size of the content may be smaller.
     */
    public void setSize(int width, int height) {
        mWidth = width;
        mHeight = height;
        mTextureWidth = width > 0 ? Utils.nextPowerOf2(width) : 0;
// Path: src/com/android/launcher3/wallpaperpicker/common/Utils.java
// public class Utils {
//     private static final String TAG = "Utils";
// 
//     // Throws AssertionError if the input is false.
//     public static void assertTrue(boolean cond) {
//         if (!cond) {
//             throw new AssertionError();
//         }
//     }
// 
//     // Returns the next power of two.
//     // Returns the input if it is already power of 2.
//     // Throws IllegalArgumentException if the input is <= 0 or
//     // the answer overflows.
//     public static int nextPowerOf2(int n) {
//         if (n <= 0 || n > (1 << 30)) throw new IllegalArgumentException("n is invalid: " + n);
//         n -= 1;
//         n |= n >> 16;
//         n |= n >> 8;
//         n |= n >> 4;
//         n |= n >> 2;
//         n |= n >> 1;
//         return n + 1;
//     }
// 
//     // Returns the previous power of two.
//     // Returns the input if it is already power of 2.
//     // Throws IllegalArgumentException if the input is <= 0
//     public static int prevPowerOf2(int n) {
//         if (n <= 0) throw new IllegalArgumentException();
//         return Integer.highestOneBit(n);
//     }
// 
//     // Returns the input value x clamped to the range [min, max].
//     public static int clamp(int x, int min, int max) {
//         if (x > max) return max;
//         if (x < min) return min;
//         return x;
//     }
// 
//     public static int ceilLog2(float value) {
//         int i;
//         for (i = 0; i < 31; i++) {
//             if ((1 << i) >= value) break;
//         }
//         return i;
//     }
// 
//     public static int floorLog2(float value) {
//         int i;
//         for (i = 0; i < 31; i++) {
//             if ((1 << i) > value) break;
//         }
//         return i - 1;
//     }
// 
//     public static void closeSilently(Closeable c) {
//         if (c == null) return;
//         try {
//             c.close();
//         } catch (IOException t) {
//             Log.w(TAG, "close fail ", t);
//         }
//     }
// 
//     public static RectF getMaxCropRect(
//             int inWidth, int inHeight, int outWidth, int outHeight, boolean leftAligned) {
//         RectF cropRect = new RectF();
//         // Get a crop rect that will fit this
//         if (inWidth / (float) inHeight > outWidth / (float) outHeight) {
//             cropRect.top = 0;
//             cropRect.bottom = inHeight;
//             cropRect.left = (inWidth - (outWidth / (float) outHeight) * inHeight) / 2;
//             cropRect.right = inWidth - cropRect.left;
//             if (leftAligned) {
//                 cropRect.right -= cropRect.left;
//                 cropRect.left = 0;
//             }
//         } else {
//             cropRect.left = 0;
//             cropRect.right = inWidth;
//             cropRect.top = (inHeight - (outHeight / (float) outWidth) * inWidth) / 2;
//             cropRect.bottom = inHeight - cropRect.top;
//         }
//         return cropRect;
//     }
// 
//     /**
//      * Find the min x that 1 / x >= scale
//      */
//     public static int computeSampleSizeLarger(float scale) {
//         int initialSize = (int) Math.floor(1f / scale);
//         if (initialSize <= 1) return 1;
//         return initialSize <= 8 ? prevPowerOf2(initialSize) : (initialSize / 8 * 8);
//     }
// }


// Path: src/com/android/launcher3/wallpaperpicker/glrenderer/BasicTexture.java
import android.util.Log;
import com.android.launcher3.wallpaperpicker.common.Utils;
import java.util.WeakHashMap;

    protected GLCanvas mCanvasRef = null;
    private static WeakHashMap<BasicTexture, Object> sAllTextures
            = new WeakHashMap<>();
    private static ThreadLocal<Class<BasicTexture>> sInFinalizer = new ThreadLocal<>();

    protected BasicTexture(GLCanvas canvas, int id, int state) {
        setAssociatedCanvas(canvas);
        mId = id;
        mState = state;
        synchronized (sAllTextures) {
            sAllTextures.put(this, null);
        }
    }

    protected BasicTexture() {
        this(null, 0, STATE_UNLOADED);
    }

    protected void setAssociatedCanvas(GLCanvas canvas) {
        mCanvasRef = canvas;
    }

    /**
     * Sets the content size of this texture. In OpenGL, the actual texture
     * size must be of power of 2, the size of the content may be smaller.
     */
    public void setSize(int width, int height) {
        mWidth = width;
        mHeight = height;
        mTextureWidth = width > 0 ? Utils.nextPowerOf2(width) : 0;
        mTextureHeight = height > 0 ? Utils.nextPowerOf2(height) : 0;