diff options
Diffstat (limited to 'WallpaperPicker/src/com/android/photos')
4 files changed, 99 insertions, 672 deletions
diff --git a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java index 66ece4ff6..2d496a5a6 100644 --- a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java +++ b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java @@ -20,15 +20,14 @@ import android.annotation.TargetApi; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.BitmapRegionDecoder; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.net.Uri; +import android.opengl.GLUtils; import android.os.Build; -import android.os.Build.VERSION_CODES; import android.util.Log; import com.android.gallery3d.common.BitmapUtils; @@ -148,24 +147,19 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { private static final String TAG = "BitmapRegionTileSource"; - private static final boolean REUSE_BITMAP = - Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; private static final int GL_SIZE_LIMIT = 2048; // This must be no larger than half the size of the GL_SIZE_LIMIT // due to decodePreview being allowed to be up to 2x the size of the target - public static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2; + private static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2; public static abstract class BitmapSource { private SimpleBitmapRegionDecoder mDecoder; private Bitmap mPreview; - private int mPreviewSize; private int mRotation; public enum State { NOT_LOADED, LOADED, ERROR_LOADING }; private State mState = State.NOT_LOADED; - public BitmapSource(int previewSize) { - mPreviewSize = previewSize; - } - public boolean loadInBackground() { + + public boolean loadInBackground(InBitmapProvider bitmapProvider) { ExifInterface ei = new ExifInterface(); if (readExif(ei)) { Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION); @@ -180,18 +174,44 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { } else { int width = mDecoder.getWidth(); int height = mDecoder.getHeight(); - if (mPreviewSize != 0) { - int previewSize = Math.min(mPreviewSize, MAX_PREVIEW_SIZE); - BitmapFactory.Options opts = new BitmapFactory.Options(); - opts.inPreferredConfig = Bitmap.Config.ARGB_8888; - opts.inPreferQualityOverSpeed = true; - - float scale = (float) previewSize / Math.max(width, height); - opts.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale); - opts.inJustDecodeBounds = false; + + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inPreferredConfig = Bitmap.Config.ARGB_8888; + opts.inPreferQualityOverSpeed = true; + + float scale = (float) MAX_PREVIEW_SIZE / Math.max(width, height); + opts.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale); + opts.inJustDecodeBounds = false; + opts.inMutable = true; + + if (bitmapProvider != null) { + int expectedPixles = (width / opts.inSampleSize) * (height / opts.inSampleSize); + Bitmap reusableBitmap = bitmapProvider.forPixelCount(expectedPixles); + if (reusableBitmap != null) { + // Try loading with reusable bitmap + opts.inBitmap = reusableBitmap; + try { + mPreview = loadPreviewBitmap(opts); + } catch (IllegalArgumentException e) { + Log.d(TAG, "Unable to reusage bitmap", e); + opts.inBitmap = null; + mPreview = null; + } + } + } + if (mPreview == null) { mPreview = loadPreviewBitmap(opts); } - mState = State.LOADED; + + // Verify that the bitmap can be used on GL surface + try { + GLUtils.getInternalFormat(mPreview); + GLUtils.getType(mPreview); + mState = State.LOADED; + } catch (IllegalArgumentException e) { + Log.d(TAG, "Image cannot be rendered on a GL surface", e); + mState = State.ERROR_LOADING; + } return true; } } @@ -208,10 +228,6 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { return mPreview; } - public int getPreviewSize() { - return mPreviewSize; - } - public int getRotation() { return mRotation; } @@ -219,12 +235,15 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { public abstract boolean readExif(ExifInterface ei); public abstract SimpleBitmapRegionDecoder loadBitmapRegionDecoder(); public abstract Bitmap loadPreviewBitmap(BitmapFactory.Options options); + + public interface InBitmapProvider { + Bitmap forPixelCount(int count); + } } public static class FilePathBitmapSource extends BitmapSource { private String mPath; - public FilePathBitmapSource(String path, int previewSize) { - super(previewSize); + public FilePathBitmapSource(String path) { mPath = path; } @Override @@ -258,8 +277,7 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { public static class UriBitmapSource extends BitmapSource { private Context mContext; private Uri mUri; - public UriBitmapSource(Context context, Uri uri, int previewSize) { - super(previewSize); + public UriBitmapSource(Context context, Uri uri) { mContext = context; mUri = uri; } @@ -306,13 +324,13 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { Utils.closeSilently(is); return true; } catch (FileNotFoundException e) { - Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e); + Log.d("BitmapRegionTileSource", "Failed to load URI " + mUri, e); return false; } catch (IOException e) { - Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e); + Log.d("BitmapRegionTileSource", "Failed to load URI " + mUri, e); return false; } catch (NullPointerException e) { - Log.e("BitmapRegionTileSource", "Failed to read EXIF for URI " + mUri, e); + Log.d("BitmapRegionTileSource", "Failed to read EXIF for URI " + mUri, e); return false; } finally { Utils.closeSilently(is); @@ -323,8 +341,7 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { public static class ResourceBitmapSource extends BitmapSource { private Resources mRes; private int mResId; - public ResourceBitmapSource(Resources res, int resId, int previewSize) { - super(previewSize); + public ResourceBitmapSource(Resources res, int resId) { mRes = res; mResId = resId; } @@ -372,11 +389,9 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { // For use only by getTile private Rect mWantRegion = new Rect(); - private Rect mOverlapRegion = new Rect(); private BitmapFactory.Options mOptions; - private Canvas mCanvas; - public BitmapRegionTileSource(Context context, BitmapSource source) { + public BitmapRegionTileSource(Context context, BitmapSource source, byte[] tempStorage) { mTileSize = TiledImageRenderer.suggestedTileSize(context); mRotation = source.getRotation(); mDecoder = source.getBitmapRegionDecoder(); @@ -386,27 +401,26 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { mOptions = new BitmapFactory.Options(); mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888; mOptions.inPreferQualityOverSpeed = true; - mOptions.inTempStorage = new byte[16 * 1024]; - int previewSize = source.getPreviewSize(); - if (previewSize != 0) { - previewSize = Math.min(previewSize, MAX_PREVIEW_SIZE); - // Although this is the same size as the Bitmap that is likely already - // loaded, the lifecycle is different and interactions are on a different - // thread. Thus to simplify, this source will decode its own bitmap. - Bitmap preview = decodePreview(source, previewSize); - if (preview.getWidth() <= GL_SIZE_LIMIT && preview.getHeight() <= GL_SIZE_LIMIT) { + mOptions.inTempStorage = tempStorage; + + Bitmap preview = source.getPreviewBitmap(); + if (preview != null && + preview.getWidth() <= GL_SIZE_LIMIT && preview.getHeight() <= GL_SIZE_LIMIT) { mPreview = new BitmapTexture(preview); - } else { - Log.w(TAG, String.format( - "Failed to create preview of apropriate size! " - + " in: %dx%d, out: %dx%d", - mWidth, mHeight, - preview.getWidth(), preview.getHeight())); - } + } else { + Log.w(TAG, String.format( + "Failed to create preview of apropriate size! " + + " in: %dx%d, out: %dx%d", + mWidth, mHeight, + preview.getWidth(), preview.getHeight())); } } } + public Bitmap getBitmap() { + return mPreview instanceof BitmapTexture ? ((BitmapTexture) mPreview).getBitmap() : null; + } + @Override public int getTileSize() { return mTileSize; @@ -435,10 +449,6 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { @Override public Bitmap getTile(int level, int x, int y, Bitmap bitmap) { int tileSize = getTileSize(); - if (!REUSE_BITMAP) { - return getTileWithoutReusingBitmap(level, x, y, tileSize); - } - int t = tileSize << level; mWantRegion.set(x, y, x + t, y + t); @@ -462,64 +472,4 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { } return bitmap; } - - private Bitmap getTileWithoutReusingBitmap( - int level, int x, int y, int tileSize) { - - int t = tileSize << level; - mWantRegion.set(x, y, x + t, y + t); - - mOverlapRegion.set(0, 0, mWidth, mHeight); - - mOptions.inSampleSize = (1 << level); - Bitmap bitmap = mDecoder.decodeRegion(mOverlapRegion, mOptions); - - if (bitmap == null) { - Log.w(TAG, "fail in decoding region"); - } - - if (mWantRegion.equals(mOverlapRegion)) { - return bitmap; - } - - Bitmap result = Bitmap.createBitmap(tileSize, tileSize, Config.ARGB_8888); - if (mCanvas == null) { - mCanvas = new Canvas(); - } - mCanvas.setBitmap(result); - mCanvas.drawBitmap(bitmap, - (mOverlapRegion.left - mWantRegion.left) >> level, - (mOverlapRegion.top - mWantRegion.top) >> level, null); - mCanvas.setBitmap(null); - return result; - } - - /** - * Note that the returned bitmap may have a long edge that's longer - * than the targetSize, but it will always be less than 2x the targetSize - */ - private Bitmap decodePreview(BitmapSource source, int targetSize) { - Bitmap result = source.getPreviewBitmap(); - if (result == null) { - return null; - } - - // We need to resize down if the decoder does not support inSampleSize - // or didn't support the specified inSampleSize (some decoders only do powers of 2) - float scale = (float) targetSize / (float) (Math.max(result.getWidth(), result.getHeight())); - - if (scale <= 0.5) { - result = BitmapUtils.resizeBitmapByScale(result, scale, true); - } - return ensureGLCompatibleBitmap(result); - } - - private static Bitmap ensureGLCompatibleBitmap(Bitmap bitmap) { - if (bitmap == null || bitmap.getConfig() != null) { - return bitmap; - } - Bitmap newBitmap = bitmap.copy(Config.ARGB_8888, false); - bitmap.recycle(); - return newBitmap; - } } diff --git a/WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java b/WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java deleted file mode 100644 index 8a0505185..000000000 --- a/WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * 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.android.photos.views; - -import android.content.Context; -import android.graphics.SurfaceTexture; -import android.opengl.GLSurfaceView.Renderer; -import android.opengl.GLUtils; -import android.util.Log; -import android.view.TextureView; -import android.view.TextureView.SurfaceTextureListener; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.egl.EGLDisplay; -import javax.microedition.khronos.egl.EGLSurface; -import javax.microedition.khronos.opengles.GL10; - -/** - * A TextureView that supports blocking rendering for synchronous drawing - */ -public class BlockingGLTextureView extends TextureView - implements SurfaceTextureListener { - - private RenderThread mRenderThread; - - public BlockingGLTextureView(Context context) { - super(context); - setSurfaceTextureListener(this); - } - - public void setRenderer(Renderer renderer) { - if (mRenderThread != null) { - throw new IllegalArgumentException("Renderer already set"); - } - mRenderThread = new RenderThread(renderer); - } - - public void render() { - mRenderThread.render(); - } - - public void destroy() { - if (mRenderThread != null) { - mRenderThread.finish(); - mRenderThread = null; - } - } - - @Override - public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, - int height) { - mRenderThread.setSurface(surface); - mRenderThread.setSize(width, height); - } - - @Override - public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, - int height) { - mRenderThread.setSize(width, height); - } - - @Override - public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { - if (mRenderThread != null) { - mRenderThread.setSurface(null); - } - return false; - } - - @Override - public void onSurfaceTextureUpdated(SurfaceTexture surface) { - } - - @Override - protected void finalize() throws Throwable { - try { - destroy(); - } catch (Throwable t) { - // Ignore - } - super.finalize(); - } - - /** - * An EGL helper class. - */ - - private static class EglHelper { - private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; - private static final int EGL_OPENGL_ES2_BIT = 4; - - EGL10 mEgl; - EGLDisplay mEglDisplay; - EGLSurface mEglSurface; - EGLConfig mEglConfig; - EGLContext mEglContext; - - private EGLConfig chooseEglConfig() { - int[] configsCount = new int[1]; - EGLConfig[] configs = new EGLConfig[1]; - int[] configSpec = getConfig(); - if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) { - throw new IllegalArgumentException("eglChooseConfig failed " + - GLUtils.getEGLErrorString(mEgl.eglGetError())); - } else if (configsCount[0] > 0) { - return configs[0]; - } - return null; - } - - private static int[] getConfig() { - return new int[] { - EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL10.EGL_RED_SIZE, 8, - EGL10.EGL_GREEN_SIZE, 8, - EGL10.EGL_BLUE_SIZE, 8, - EGL10.EGL_ALPHA_SIZE, 8, - EGL10.EGL_DEPTH_SIZE, 0, - EGL10.EGL_STENCIL_SIZE, 0, - EGL10.EGL_NONE - }; - } - - EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) { - int[] attribList = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; - return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attribList); - } - - /** - * Initialize EGL for a given configuration spec. - */ - public void start() { - /* - * Get an EGL instance - */ - mEgl = (EGL10) EGLContext.getEGL(); - - /* - * Get to the default display. - */ - mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); - - if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { - throw new RuntimeException("eglGetDisplay failed"); - } - - /* - * We can now initialize EGL for that display - */ - int[] version = new int[2]; - if (!mEgl.eglInitialize(mEglDisplay, version)) { - throw new RuntimeException("eglInitialize failed"); - } - mEglConfig = chooseEglConfig(); - - /* - * Create an EGL context. We want to do this as rarely as we can, because an - * EGL context is a somewhat heavy object. - */ - mEglContext = createContext(mEgl, mEglDisplay, mEglConfig); - - if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) { - mEglContext = null; - throwEglException("createContext"); - } - - mEglSurface = null; - } - - /** - * Create an egl surface for the current SurfaceTexture surface. If a surface - * already exists, destroy it before creating the new surface. - * - * @return true if the surface was created successfully. - */ - public boolean createSurface(SurfaceTexture surface) { - /* - * Check preconditions. - */ - if (mEgl == null) { - throw new RuntimeException("egl not initialized"); - } - if (mEglDisplay == null) { - throw new RuntimeException("eglDisplay not initialized"); - } - if (mEglConfig == null) { - throw new RuntimeException("mEglConfig not initialized"); - } - - /* - * The window size has changed, so we need to create a new - * surface. - */ - destroySurfaceImp(); - - /* - * Create an EGL surface we can render into. - */ - if (surface != null) { - mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surface, null); - } else { - mEglSurface = null; - } - - if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { - int error = mEgl.eglGetError(); - if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { - Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); - } - return false; - } - - /* - * Before we can issue GL commands, we need to make sure - * the context is current and bound to a surface. - */ - if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { - /* - * Could not make the context current, probably because the underlying - * SurfaceView surface has been destroyed. - */ - logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", mEgl.eglGetError()); - return false; - } - - return true; - } - - /** - * Create a GL object for the current EGL context. - */ - public GL10 createGL() { - return (GL10) mEglContext.getGL(); - } - - /** - * Display the current render surface. - * @return the EGL error code from eglSwapBuffers. - */ - public int swap() { - if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { - return mEgl.eglGetError(); - } - return EGL10.EGL_SUCCESS; - } - - public void destroySurface() { - destroySurfaceImp(); - } - - private void destroySurfaceImp() { - if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { - mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_CONTEXT); - mEgl.eglDestroySurface(mEglDisplay, mEglSurface); - mEglSurface = null; - } - } - - public void finish() { - if (mEglContext != null) { - mEgl.eglDestroyContext(mEglDisplay, mEglContext); - mEglContext = null; - } - if (mEglDisplay != null) { - mEgl.eglTerminate(mEglDisplay); - mEglDisplay = null; - } - } - - private void throwEglException(String function) { - throwEglException(function, mEgl.eglGetError()); - } - - public static void throwEglException(String function, int error) { - String message = formatEglError(function, error); - throw new RuntimeException(message); - } - - public static void logEglErrorAsWarning(String tag, String function, int error) { - Log.w(tag, formatEglError(function, error)); - } - - public static String formatEglError(String function, int error) { - return function + " failed: " + error; - } - - } - - private static class RenderThread extends Thread { - private static final int INVALID = -1; - private static final int RENDER = 1; - private static final int CHANGE_SURFACE = 2; - private static final int RESIZE_SURFACE = 3; - private static final int FINISH = 4; - - private EglHelper mEglHelper = new EglHelper(); - - private Object mLock = new Object(); - private int mExecMsgId = INVALID; - private SurfaceTexture mSurface; - private Renderer mRenderer; - private int mWidth, mHeight; - - private boolean mFinished = false; - private GL10 mGL; - - public RenderThread(Renderer renderer) { - super("RenderThread"); - mRenderer = renderer; - start(); - } - - private void checkRenderer() { - if (mRenderer == null) { - throw new IllegalArgumentException("Renderer is null!"); - } - } - - private void checkSurface() { - if (mSurface == null) { - throw new IllegalArgumentException("surface is null!"); - } - } - - public void setSurface(SurfaceTexture surface) { - // If the surface is null we're being torn down, don't need a - // renderer then - if (surface != null) { - checkRenderer(); - } - mSurface = surface; - exec(CHANGE_SURFACE); - } - - public void setSize(int width, int height) { - checkRenderer(); - checkSurface(); - mWidth = width; - mHeight = height; - exec(RESIZE_SURFACE); - } - - public void render() { - checkRenderer(); - if (mSurface != null) { - exec(RENDER); - mSurface.updateTexImage(); - } - } - - public void finish() { - mSurface = null; - exec(FINISH); - try { - join(); - } catch (InterruptedException e) { - // Ignore - } - } - - private void exec(int msgid) { - synchronized (mLock) { - if (mExecMsgId != INVALID) { - throw new IllegalArgumentException( - "Message already set - multithreaded access?"); - } - mExecMsgId = msgid; - mLock.notify(); - try { - mLock.wait(); - } catch (InterruptedException e) { - // Ignore - } - } - } - - private void handleMessageLocked(int what) { - switch (what) { - case CHANGE_SURFACE: - if (mEglHelper.createSurface(mSurface)) { - mGL = mEglHelper.createGL(); - mRenderer.onSurfaceCreated(mGL, mEglHelper.mEglConfig); - } - break; - case RESIZE_SURFACE: - mRenderer.onSurfaceChanged(mGL, mWidth, mHeight); - break; - case RENDER: - mRenderer.onDrawFrame(mGL); - mEglHelper.swap(); - break; - case FINISH: - mEglHelper.destroySurface(); - mEglHelper.finish(); - mFinished = true; - break; - } - } - - @Override - public void run() { - synchronized (mLock) { - mEglHelper.start(); - while (!mFinished) { - while (mExecMsgId == INVALID) { - try { - mLock.wait(); - } catch (InterruptedException e) { - // Ignore - } - } - handleMessageLocked(mExecMsgId); - mExecMsgId = INVALID; - mLock.notify(); - } - mExecMsgId = FINISH; - } - } - } -} diff --git a/WallpaperPicker/src/com/android/photos/views/TiledImageRenderer.java b/WallpaperPicker/src/com/android/photos/views/TiledImageRenderer.java index c4e493b34..e57ce70b9 100644 --- a/WallpaperPicker/src/com/android/photos/views/TiledImageRenderer.java +++ b/WallpaperPicker/src/com/android/photos/views/TiledImageRenderer.java @@ -20,11 +20,11 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.RectF; -import android.support.v4.util.LongSparseArray; +import android.support.v4.util.Pools.Pool; +import android.support.v4.util.Pools.SynchronizedPool; import android.util.DisplayMetrics; import android.util.Log; -import android.util.Pools.Pool; -import android.util.Pools.SynchronizedPool; +import android.util.LongSparseArray; import android.view.View; import android.view.WindowManager; @@ -32,6 +32,7 @@ import com.android.gallery3d.common.Utils; import com.android.gallery3d.glrenderer.BasicTexture; import com.android.gallery3d.glrenderer.GLCanvas; import com.android.gallery3d.glrenderer.UploadedTexture; +import com.android.launcher3.util.Thunk; /** * Handles laying out, decoding, and drawing of tiles in GL @@ -67,12 +68,12 @@ public class TiledImageRenderer { private static final int STATE_RECYCLING = 0x20; private static final int STATE_RECYCLED = 0x40; - private static Pool<Bitmap> sTilePool = new SynchronizedPool<Bitmap>(64); + @Thunk static Pool<Bitmap> sTilePool = new SynchronizedPool<Bitmap>(64); // TILE_SIZE must be 2^N - private int mTileSize; + @Thunk int mTileSize; - private TileSource mModel; + @Thunk TileSource mModel; private BasicTexture mPreview; protected int mLevelCount; // cache the value of mScaledBitmaps.length @@ -82,7 +83,7 @@ public class TiledImageRenderer { // half size of the previous one). If the value is in [0, mLevelCount), we // use the bitmap in mScaledBitmaps[mLevel] for display, otherwise the value // is mLevelCount - private int mLevel = 0; + @Thunk int mLevel = 0; private int mOffsetX; private int mOffsetY; @@ -96,10 +97,10 @@ public class TiledImageRenderer { private final LongSparseArray<Tile> mActiveTiles = new LongSparseArray<Tile>(); // The following three queue are guarded by mQueueLock - private final Object mQueueLock = new Object(); + @Thunk final Object mQueueLock = new Object(); private final TileQueue mRecycledQueue = new TileQueue(); private final TileQueue mUploadQueue = new TileQueue(); - private final TileQueue mDecodeQueue = new TileQueue(); + @Thunk final TileQueue mDecodeQueue = new TileQueue(); // The width and height of the full-sized bitmap protected int mImageWidth = SIZE_UNKNOWN; @@ -489,7 +490,7 @@ public class TiledImageRenderer { } } - private void decodeTile(Tile tile) { + @Thunk void decodeTile(Tile tile) { synchronized (mQueueLock) { if (tile.mTileState != STATE_IN_QUEUE) { return; @@ -556,7 +557,7 @@ public class TiledImageRenderer { mActiveTiles.put(key, tile); } - private Tile getTile(int x, int y, int level) { + @Thunk Tile getTile(int x, int y, int level) { return mActiveTiles.get(makeTileKey(x, y, level)); } @@ -748,7 +749,7 @@ public class TiledImageRenderer { } } - private static class TileQueue { + @Thunk static class TileQueue { private Tile mHead; public Tile pop() { @@ -786,7 +787,7 @@ public class TiledImageRenderer { } } - private class TileDecoder extends Thread { + @Thunk class TileDecoder extends Thread { public void finishAndWait() { interrupt(); diff --git a/WallpaperPicker/src/com/android/photos/views/TiledImageView.java b/WallpaperPicker/src/com/android/photos/views/TiledImageView.java index 94063b027..7e3e1a936 100644 --- a/WallpaperPicker/src/com/android/photos/views/TiledImageView.java +++ b/WallpaperPicker/src/com/android/photos/views/TiledImageView.java @@ -16,8 +16,6 @@ package com.android.photos.views; -import android.annotation.SuppressLint; -import android.annotation.TargetApi; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -28,35 +26,26 @@ import android.graphics.Paint.Align; import android.graphics.RectF; import android.opengl.GLSurfaceView; import android.opengl.GLSurfaceView.Renderer; -import android.os.Build; import android.util.AttributeSet; import android.view.Choreographer; import android.view.Choreographer.FrameCallback; -import android.view.View; import android.widget.FrameLayout; import com.android.gallery3d.glrenderer.BasicTexture; import com.android.gallery3d.glrenderer.GLES20Canvas; +import com.android.launcher3.util.Thunk; import com.android.photos.views.TiledImageRenderer.TileSource; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; /** - * Shows an image using {@link TiledImageRenderer} using either {@link GLSurfaceView} - * or {@link BlockingGLTextureView}. + * Shows an image using {@link TiledImageRenderer} using either {@link GLSurfaceView}. */ public class TiledImageView extends FrameLayout { - private static final boolean USE_TEXTURE_VIEW = false; - private static final boolean IS_SUPPORTED = - Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; - private static final boolean USE_CHOREOGRAPHER = - Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; - - private BlockingGLTextureView mTextureView; - private GLSurfaceView mGLSurfaceView; - private boolean mInvalPending = false; + @Thunk GLSurfaceView mGLSurfaceView; + @Thunk boolean mInvalPending = false; private FrameCallback mFrameCallback; protected static class ImageRendererWrapper { @@ -79,35 +68,19 @@ public class TiledImageView extends FrameLayout { protected Object mLock = new Object(); protected ImageRendererWrapper mRenderer; - public static boolean isTilingSupported() { - return IS_SUPPORTED; - } - public TiledImageView(Context context) { this(context, null); } public TiledImageView(Context context, AttributeSet attrs) { super(context, attrs); - if (!IS_SUPPORTED) { - return; - } - mRenderer = new ImageRendererWrapper(); mRenderer.image = new TiledImageRenderer(this); - View view; - if (USE_TEXTURE_VIEW) { - mTextureView = new BlockingGLTextureView(context); - mTextureView.setRenderer(new TileRenderer()); - view = mTextureView; - } else { - mGLSurfaceView = new GLSurfaceView(context); - mGLSurfaceView.setEGLContextClientVersion(2); - mGLSurfaceView.setRenderer(new TileRenderer()); - mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); - view = mGLSurfaceView; - } - addView(view, new LayoutParams( + mGLSurfaceView = new GLSurfaceView(context); + mGLSurfaceView.setEGLContextClientVersion(2); + mGLSurfaceView.setRenderer(new TileRenderer()); + mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); + addView(mGLSurfaceView, new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); //setTileSource(new ColoredTiles()); } @@ -117,22 +90,11 @@ public class TiledImageView extends FrameLayout { super.setVisibility(visibility); // need to update inner view's visibility because it seems like we're causing it to draw // from {@link #dispatchDraw} or {@link #invalidate} even if we are invisible. - if (USE_TEXTURE_VIEW) { - mTextureView.setVisibility(visibility); - } else { - mGLSurfaceView.setVisibility(visibility); - } + mGLSurfaceView.setVisibility(visibility); } public void destroy() { - if (!IS_SUPPORTED) { - return; - } - if (USE_TEXTURE_VIEW) { - mTextureView.destroy(); - } else { - mGLSurfaceView.queueEvent(mFreeTextures); - } + mGLSurfaceView.queueEvent(mFreeTextures); } private Runnable mFreeTextures = new Runnable() { @@ -144,27 +106,14 @@ public class TiledImageView extends FrameLayout { }; public void onPause() { - if (!IS_SUPPORTED) { - return; - } - if (!USE_TEXTURE_VIEW) { - mGLSurfaceView.onPause(); - } + mGLSurfaceView.onPause(); } public void onResume() { - if (!IS_SUPPORTED) { - return; - } - if (!USE_TEXTURE_VIEW) { - mGLSurfaceView.onResume(); - } + mGLSurfaceView.onResume(); } public void setTileSource(TileSource source, Runnable isReadyCallback) { - if (!IS_SUPPORTED) { - return; - } synchronized (mLock) { mRenderer.source = source; mRenderer.isReadyCallback = isReadyCallback; @@ -177,13 +126,14 @@ public class TiledImageView extends FrameLayout { invalidate(); } + public TileSource getTileSource() { + return mRenderer.source; + } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); - if (!IS_SUPPORTED) { - return; - } synchronized (mLock) { updateScaleIfNecessaryLocked(mRenderer); } @@ -200,43 +150,10 @@ public class TiledImageView extends FrameLayout { } @Override - protected void dispatchDraw(Canvas canvas) { - if (!IS_SUPPORTED) { - return; - } - if (USE_TEXTURE_VIEW) { - mTextureView.render(); - } - super.dispatchDraw(canvas); - } - - @SuppressLint("NewApi") - @Override - public void setTranslationX(float translationX) { - if (!IS_SUPPORTED) { - return; - } - super.setTranslationX(translationX); - } - - @Override public void invalidate() { - if (!IS_SUPPORTED) { - return; - } - if (USE_TEXTURE_VIEW) { - super.invalidate(); - mTextureView.invalidate(); - } else { - if (USE_CHOREOGRAPHER) { - invalOnVsync(); - } else { - mGLSurfaceView.requestRender(); - } - } + invalOnVsync(); } - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private void invalOnVsync() { if (!mInvalPending) { mInvalPending = true; @@ -255,9 +172,6 @@ public class TiledImageView extends FrameLayout { private RectF mTempRectF = new RectF(); public void positionFromMatrix(Matrix matrix) { - if (!IS_SUPPORTED) { - return; - } if (mRenderer.source != null) { final int rotation = mRenderer.source.getRotation(); final boolean swap = !(rotation % 180 == 0); @@ -290,7 +204,7 @@ public class TiledImageView extends FrameLayout { } } - private class TileRenderer implements Renderer { + @Thunk class TileRenderer implements Renderer { private GLES20Canvas mCanvas; |