diff options
19 files changed, 192 insertions, 113 deletions
diff --git a/src/com/android/gallery3d/app/AbstractGalleryActivity.java b/src/com/android/gallery3d/app/AbstractGalleryActivity.java index eddaea5cb..00f6ac5e1 100644 --- a/src/com/android/gallery3d/app/AbstractGalleryActivity.java +++ b/src/com/android/gallery3d/app/AbstractGalleryActivity.java @@ -178,6 +178,7 @@ public class AbstractGalleryActivity extends Activity implements GalleryActivity mGLRootView.unlockRenderThread(); } MediaItem.getMicroThumbPool().clear(); + MediaItem.getThumbPool().clear(); MediaItem.getBytesBufferPool().clear(); } diff --git a/src/com/android/gallery3d/app/CameraScreenNail.java b/src/com/android/gallery3d/app/CameraScreenNail.java index f68ab72f8..24857a48f 100644 --- a/src/com/android/gallery3d/app/CameraScreenNail.java +++ b/src/com/android/gallery3d/app/CameraScreenNail.java @@ -128,7 +128,7 @@ class CameraScreenNail extends SurfaceTextureScreenNail { } @Override - public void pauseDraw() { + public void recycle() { mVisible = false; } diff --git a/src/com/android/gallery3d/app/PhotoDataAdapter.java b/src/com/android/gallery3d/app/PhotoDataAdapter.java index 10ed8f3d0..f9979f88e 100644 --- a/src/com/android/gallery3d/app/PhotoDataAdapter.java +++ b/src/com/android/gallery3d/app/PhotoDataAdapter.java @@ -55,6 +55,7 @@ public class PhotoDataAdapter implements PhotoPage.Model { private static final int MSG_LOAD_START = 1; private static final int MSG_LOAD_FINISH = 2; private static final int MSG_RUN_OBJECT = 3; + private static final int MSG_UPDATE_IMAGE_REQUESTS = 4; private static final int MIN_LOAD_COUNT = 8; private static final int DATA_CACHE_SIZE = 32; @@ -143,9 +144,9 @@ public class PhotoDataAdapter implements PhotoPage.Model { private int mSize = 0; private Path mItemPath; private boolean mIsActive; + private boolean mNeedFullImage; public interface DataListener extends LoadingListener { - public void onPhotoAvailable(long version, boolean fullImage); public void onPhotoChanged(int index, Path item); } @@ -164,6 +165,7 @@ public class PhotoDataAdapter implements PhotoPage.Model { mItemPath = Utils.checkNotNull(itemPath); mCurrentIndex = indexHint; mThreadPool = activity.getThreadPool(); + mNeedFullImage = true; Arrays.fill(mChanges, MediaObject.INVALID_DATA_VERSION); @@ -183,6 +185,10 @@ public class PhotoDataAdapter implements PhotoPage.Model { if (mDataListener != null) mDataListener.onLoadingFinished(); return; } + case MSG_UPDATE_IMAGE_REQUESTS: { + updateImageRequests(); + return; + } default: throw new AssertionError(); } } @@ -211,26 +217,29 @@ public class PhotoDataAdapter implements PhotoPage.Model { mDataListener = listener; } + @Override + public void setNeedFullImage(boolean enabled) { + mNeedFullImage = enabled; + mMainHandler.sendEmptyMessage(MSG_UPDATE_IMAGE_REQUESTS); + } + private void updateScreenNail(long version, Future<ScreenNail> future) { ImageEntry entry = mImageCache.get(version); ScreenNail screenNail = future.get(); if (entry == null || entry.screenNailTask != future) { - if (screenNail != null) screenNail.pauseDraw(); + if (screenNail != null) screenNail.recycle(); return; } entry.screenNailTask = null; + Utils.assertTrue(entry.screenNail == null); entry.screenNail = screenNail; if (screenNail == null) { entry.failToLoad = true; } - if (mDataListener != null) { - mDataListener.onPhotoAvailable(version, false); - } - for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; ++i) { if (version == getVersion(mCurrentIndex + i)) { if (i == 0) updateTileProvider(entry); @@ -252,9 +261,6 @@ public class PhotoDataAdapter implements PhotoPage.Model { entry.fullImageTask = null; entry.fullImage = future.get(); if (entry.fullImage != null) { - if (mDataListener != null) { - mDataListener.onPhotoAvailable(version, true); - } if (version == getVersion(mCurrentIndex)) { updateTileProvider(entry); mPhotoView.notifyImageChange(0); @@ -286,6 +292,7 @@ public class PhotoDataAdapter implements PhotoPage.Model { for (ImageEntry entry : mImageCache.values()) { if (entry.fullImageTask != null) entry.fullImageTask.cancel(); if (entry.screenNailTask != null) entry.screenNailTask.cancel(); + if (entry.screenNail != null) entry.screenNail.recycle(); } mImageCache.clear(); mTileProvider.clear(); @@ -457,6 +464,7 @@ public class PhotoDataAdapter implements PhotoPage.Model { for (int i = 0; i < sImageFetchSeq.length; i++) { int offset = sImageFetchSeq[i].indexOffset; int bit = sImageFetchSeq[i].imageBit; + if (bit == BIT_FULL_IMAGE && !mNeedFullImage) continue; task = startTaskIfNeeded(currentIndex + offset, bit); if (task != null) break; } @@ -570,6 +578,7 @@ public class PhotoDataAdapter implements PhotoPage.Model { ImageEntry entry = mImageCache.remove(version); if (entry.fullImageTask != null) entry.fullImageTask.cancel(); if (entry.screenNailTask != null) entry.screenNailTask.cancel(); + if (entry.screenNail != null) entry.screenNail.recycle(); } } diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java index 2bdf970d3..78bb34cab 100644 --- a/src/com/android/gallery3d/app/PhotoPage.java +++ b/src/com/android/gallery3d/app/PhotoPage.java @@ -238,10 +238,6 @@ public class PhotoPage extends ActivityState public void onLoadingStarted() { GalleryUtils.setSpinnerVisibility((Activity) mActivity, true); } - - @Override - public void onPhotoAvailable(long version, boolean fullImage) { - } }); } else { // Get default media set by the URI diff --git a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java index 315f5b59c..59959cf4a 100644 --- a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java +++ b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java @@ -113,6 +113,11 @@ public class SinglePhotoDataAdapter extends TileImageViewAdapter return mItem.getRotation(); } + @Override + public void setNeedFullImage(boolean enabled) { + // currently not necessary. + } + private void onDecodeLargeComplete(ImageBundle bundle) { try { setScreenNail(bundle.backupImage, diff --git a/src/com/android/gallery3d/data/BitmapPool.java b/src/com/android/gallery3d/data/BitmapPool.java index c52a57b0a..0fbd84ef5 100644 --- a/src/com/android/gallery3d/data/BitmapPool.java +++ b/src/com/android/gallery3d/data/BitmapPool.java @@ -1,4 +1,18 @@ -// Copyright 2012 Google Inc. All Rights Reserved. +/* + * Copyright (C) 2011 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.gallery3d.data; @@ -6,6 +20,7 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapFactory.Options; +import com.android.gallery3d.common.Utils; import com.android.gallery3d.ui.Log; import com.android.gallery3d.util.ThreadPool.JobContext; @@ -15,30 +30,63 @@ import java.util.ArrayList; public class BitmapPool { private static final String TAG = "BitmapPool"; - private static final int POOL_SIZE = 16; - private final ArrayList<Bitmap> mPool = new ArrayList<Bitmap>(POOL_SIZE); + private final ArrayList<Bitmap> mPool; + private final int mPoolLimit; - private final int mWidth; - private final int mHeight; + // mOneSize is true if the pool can only cache Bitmap with one size. + private final boolean mOneSize; + private final int mWidth, mHeight; // only used if mOneSize is true - public BitmapPool(int width, int height) { + // Construct a BitmapPool which caches bitmap with the specified size. + public BitmapPool(int width, int height, int poolLimit) { mWidth = width; mHeight = height; + mPoolLimit = poolLimit; + mPool = new ArrayList<Bitmap>(poolLimit); + mOneSize = true; } + // Construct a BitmapPool which caches bitmap with any size; + public BitmapPool(int poolLimit) { + mWidth = -1; + mHeight = -1; + mPoolLimit = poolLimit; + mPool = new ArrayList<Bitmap>(poolLimit); + mOneSize = false; + } + + // Get a Bitmap from the pool. public synchronized Bitmap getBitmap() { + Utils.assertTrue(mOneSize); int size = mPool.size(); return size > 0 ? mPool.remove(size - 1) : null; } + // Get a Bitmap from the pool with the specified size. + public synchronized Bitmap getBitmap(int width, int height) { + Utils.assertTrue(!mOneSize); + for (int i = mPool.size() - 1; i >= 0; i--) { + Bitmap b = mPool.get(i); + if (b.getWidth() == width && b.getHeight() == height) { + return mPool.remove(i); + } + } + return null; + } + + // Put a Bitmap into the pool, if the Bitmap has a proper size. Otherwise + // the Bitmap will be recycled. If the pool is full, an old Bitmap will be + // recycled. public void recycle(Bitmap bitmap) { if (bitmap == null) return; - if ((bitmap.getWidth() != mWidth) || (bitmap.getHeight() != mHeight)) { + if (mOneSize && ((bitmap.getWidth() != mWidth) || + (bitmap.getHeight() != mHeight))) { bitmap.recycle(); return; } synchronized (this) { - if (mPool.size() < POOL_SIZE) mPool.add(bitmap); + if (mPool.size() >= mPoolLimit) mPool.remove(0); + mPool.add(bitmap); } } @@ -46,12 +94,27 @@ public class BitmapPool { mPool.clear(); } + private Bitmap findCachedBitmap(JobContext jc, + byte[] data, int offset, int length, Options options) { + if (mOneSize) return getBitmap(); + DecodeUtils.decodeBounds(jc, data, offset, length, options); + return getBitmap(options.outWidth, options.outHeight); + } + + private Bitmap findCachedBitmap(JobContext jc, + FileDescriptor fileDescriptor, Options options) { + if (mOneSize) return getBitmap(); + DecodeUtils.decodeBounds(jc, fileDescriptor, options); + return getBitmap(options.outWidth, options.outHeight); + } + public Bitmap decode(JobContext jc, byte[] data, int offset, int length, BitmapFactory.Options options) { if (options == null) options = new BitmapFactory.Options(); if (options.inSampleSize < 1) options.inSampleSize = 1; options.inPreferredConfig = Bitmap.Config.ARGB_8888; - options.inBitmap = (options.inSampleSize == 1) ? getBitmap() : null; + options.inBitmap = (options.inSampleSize == 1) + ? findCachedBitmap(jc, data, offset, length, options) : null; try { Bitmap bitmap = DecodeUtils.decode(jc, data, offset, length, options); if (options.inBitmap != null && options.inBitmap != bitmap) { @@ -76,7 +139,8 @@ public class BitmapPool { if (options == null) options = new BitmapFactory.Options(); if (options.inSampleSize < 1) options.inSampleSize = 1; options.inPreferredConfig = Bitmap.Config.ARGB_8888; - options.inBitmap = (options.inSampleSize == 1) ? getBitmap() : null; + options.inBitmap = (options.inSampleSize == 1) + ? findCachedBitmap(jc, fileDescriptor, options) : null; try { Bitmap bitmap = DecodeUtils.decode(jc, fileDescriptor, options); if (options.inBitmap != null&& options.inBitmap != bitmap) { diff --git a/src/com/android/gallery3d/data/DecodeUtils.java b/src/com/android/gallery3d/data/DecodeUtils.java index 319458a14..e51dc3fa9 100644 --- a/src/com/android/gallery3d/data/DecodeUtils.java +++ b/src/com/android/gallery3d/data/DecodeUtils.java @@ -55,6 +55,15 @@ public class DecodeUtils { BitmapFactory.decodeFileDescriptor(fd, null, options)); } + public static void decodeBounds(JobContext jc, FileDescriptor fd, + Options options) { + Utils.assertTrue(options != null); + options.inJustDecodeBounds = true; + jc.setCancelListener(new DecodeCanceller(options)); + BitmapFactory.decodeFileDescriptor(fd, null, options); + options.inJustDecodeBounds = false; + } + public static Bitmap decode(JobContext jc, byte[] bytes, Options options) { return decode(jc, bytes, 0, bytes.length, options); } @@ -67,6 +76,15 @@ public class DecodeUtils { BitmapFactory.decodeByteArray(bytes, offset, length, options)); } + public static void decodeBounds(JobContext jc, byte[] bytes, int offset, + int length, Options options) { + Utils.assertTrue(options != null); + options.inJustDecodeBounds = true; + jc.setCancelListener(new DecodeCanceller(options)); + BitmapFactory.decodeByteArray(bytes, offset, length, options); + options.inJustDecodeBounds = false; + } + public static Bitmap decodeThumbnail( JobContext jc, String filePath, Options options, int targetSize, int type) { FileInputStream fis = null; diff --git a/src/com/android/gallery3d/data/ImageCacheRequest.java b/src/com/android/gallery3d/data/ImageCacheRequest.java index c10158bcd..81660c915 100644 --- a/src/com/android/gallery3d/data/ImageCacheRequest.java +++ b/src/com/android/gallery3d/data/ImageCacheRequest.java @@ -60,7 +60,7 @@ abstract class ImageCacheRequest implements Job<Bitmap> { bitmap = MediaItem.getMicroThumbPool().decode(jc, buffer.data, buffer.offset, buffer.length, options); } else { - bitmap = DecodeUtils.decode(jc, + bitmap = MediaItem.getThumbPool().decode(jc, buffer.data, buffer.offset, buffer.length, options); } if (bitmap == null && !jc.isCancelled()) { diff --git a/src/com/android/gallery3d/data/MediaItem.java b/src/com/android/gallery3d/data/MediaItem.java index 3de70d954..f0f1af434 100644 --- a/src/com/android/gallery3d/data/MediaItem.java +++ b/src/com/android/gallery3d/data/MediaItem.java @@ -42,9 +42,9 @@ public abstract class MediaItem extends MediaObject { private static final int BYTESBUFFE_POOL_SIZE = 4; private static final int BYTESBUFFER_SIZE = 200 * 1024; - private static final BitmapPool sMicroThumbPool = - new BitmapPool(MICROTHUMBNAIL_TARGET_SIZE, MICROTHUMBNAIL_TARGET_SIZE); - + private static final BitmapPool sMicroThumbPool = new BitmapPool( + MICROTHUMBNAIL_TARGET_SIZE, MICROTHUMBNAIL_TARGET_SIZE, 16); + private static final BitmapPool sThumbPool = new BitmapPool(4); private static final BytesBufferPool sMicroThumbBufferPool = new BytesBufferPool(BYTESBUFFE_POOL_SIZE, BYTESBUFFER_SIZE); @@ -122,6 +122,10 @@ public abstract class MediaItem extends MediaObject { return sMicroThumbPool; } + public static BitmapPool getThumbPool() { + return sThumbPool; + } + public static BytesBufferPool getBytesBufferPool() { return sMicroThumbBufferPool; } diff --git a/src/com/android/gallery3d/ui/AlbumLabelMaker.java b/src/com/android/gallery3d/ui/AlbumLabelMaker.java index 43a9055a4..f837092b8 100644 --- a/src/com/android/gallery3d/ui/AlbumLabelMaker.java +++ b/src/com/android/gallery3d/ui/AlbumLabelMaker.java @@ -1,4 +1,18 @@ -// Copyright 2012 Google Inc. All Rights Reserved. +/* + * Copyright (C) 2012 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.gallery3d.ui; @@ -106,7 +120,7 @@ public class AlbumLabelMaker { mLabelWidth = width; int borders = 2 * BORDER_SIZE; mBitmapPool = new BitmapPool( - width + borders, mSpec.labelBackgroundHeight + borders); + width + borders, mSpec.labelBackgroundHeight + borders, 16); } public ThreadPool.Job<Bitmap> requestLabel( @@ -192,7 +206,7 @@ public class AlbumLabelMaker { } } - public void reycleLabel(Bitmap label) { + public void recycleLabel(Bitmap label) { mBitmapPool.recycle(label); } diff --git a/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java b/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java index 10943eaa6..7fa7df48a 100644 --- a/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java +++ b/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java @@ -492,7 +492,7 @@ public class AlbumSetSlidingWindow implements AlbumSetDataLoader.DataListener { @Override protected void recycleBitmap(Bitmap bitmap) { - mLabelMaker.reycleLabel(bitmap); + mLabelMaker.recycleLabel(bitmap); } @Override diff --git a/src/com/android/gallery3d/ui/BitmapScreenNail.java b/src/com/android/gallery3d/ui/BitmapScreenNail.java index 3481aa18e..064e1af0e 100644 --- a/src/com/android/gallery3d/ui/BitmapScreenNail.java +++ b/src/com/android/gallery3d/ui/BitmapScreenNail.java @@ -20,6 +20,8 @@ import android.graphics.Bitmap; import android.graphics.RectF; import android.util.Log; +import com.android.gallery3d.data.MediaItem; + // This is a ScreenNail wraps a Bitmap. It also includes the rotation // information. The getWidth() and getHeight() methods return the width/height // before rotation. @@ -28,7 +30,7 @@ public class BitmapScreenNail implements ScreenNail { private final int mWidth; private final int mHeight; private final int mRotation; - private final Bitmap mBitmap; + private Bitmap mBitmap; private BitmapTexture mTexture; public BitmapScreenNail(Bitmap bitmap, int rotation) { @@ -60,11 +62,15 @@ public class BitmapScreenNail implements ScreenNail { } @Override - public void pauseDraw() { + public void recycle() { if (mTexture != null) { mTexture.recycle(); mTexture = null; } + if (mBitmap != null) { + MediaItem.getThumbPool().recycle(mBitmap); + mBitmap = null; + } } @Override diff --git a/src/com/android/gallery3d/ui/BitmapTileProvider.java b/src/com/android/gallery3d/ui/BitmapTileProvider.java index 1e78cfd33..99b64d42e 100644 --- a/src/com/android/gallery3d/ui/BitmapTileProvider.java +++ b/src/com/android/gallery3d/ui/BitmapTileProvider.java @@ -96,7 +96,7 @@ public class BitmapTileProvider implements TileImageView.Model { BitmapUtils.recycleSilently(bitmap); } if (mScreenNail != null) { - mScreenNail.pauseDraw(); + mScreenNail.recycle(); } } diff --git a/src/com/android/gallery3d/ui/PhotoView.java b/src/com/android/gallery3d/ui/PhotoView.java index b2a4be49d..f0b4a12e7 100644 --- a/src/com/android/gallery3d/ui/PhotoView.java +++ b/src/com/android/gallery3d/ui/PhotoView.java @@ -52,6 +52,7 @@ public class PhotoView extends GLView { // ScreenNail at previous (negative offset) or next (positive offset) // positions. Returns null if the specified ScreenNail is unavailable. public ScreenNail getScreenNail(int offset); + public void setNeedFullImage(boolean enabled); } public interface PhotoTapListener { @@ -90,10 +91,6 @@ public class PhotoView extends GLView { // SCREEN_NAIL_MAX. private final RangeArray<Picture> mPictures = new RangeArray<Picture>(-SCREEN_NAIL_MAX, SCREEN_NAIL_MAX); - private final RangeBoolArray mReused = - new RangeBoolArray(-SCREEN_NAIL_MAX, SCREEN_NAIL_MAX); - private final RangeArray<ScreenNail> mTempScreenNail = - new RangeArray<ScreenNail>(-SCREEN_NAIL_MAX, SCREEN_NAIL_MAX); private final long mDataVersion[] = new long[2 * SCREEN_NAIL_MAX + 1]; private final int mFromIndex[] = new int[2 * SCREEN_NAIL_MAX + 1]; @@ -247,11 +244,6 @@ public class PhotoView extends GLView { } if (!changed) return; - // Remembers those ScreenNail which are reused. - for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) { - mReused.put(i, false); - } - // Create the mFromIndex array, which records the index where the picture // come from. The value Integer.MAX_VALUE means it's a new picture. for (int i = 0; i < N; i++) { @@ -265,7 +257,6 @@ public class PhotoView extends GLView { int j; for (j = 0; j < N; j++) { if (mDataVersion[j] == v) { - mReused.put(j - SCREEN_NAIL_MAX, true); break; } } @@ -280,25 +271,8 @@ public class PhotoView extends GLView { // Move the boxes mPositionController.moveBox(mFromIndex); - // Free those ScreenNails that are not reused. - for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) { - if (!mReused.get(i)) mPictures.get(i).updateScreenNail(null); - } - - // Collect the reused ScreenNails, so we don't need to re-upload the - // textures. + // Update the ScreenNails. for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) { - mTempScreenNail.put(i, mPictures.get(i).releaseScreenNail()); - } - - // Put back the reused ScreenNails. - for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) { - int j = mFromIndex[i + SCREEN_NAIL_MAX]; - if (j != Integer.MAX_VALUE) { - ScreenNail s = mTempScreenNail.get(j); - mTempScreenNail.put(j, null); - mPictures.get(i).updateScreenNail(s); - } mPictures.get(i).reload(); } @@ -317,11 +291,7 @@ public class PhotoView extends GLView { private interface Picture { void reload(); void draw(GLCanvas canvas, Rect r); - - void updateScreenNail(ScreenNail s); - // Release the ownership of the ScreenNail from this entry. - ScreenNail releaseScreenNail(); - + void setScreenNail(ScreenNail s); boolean isEnabled(); }; @@ -352,8 +322,7 @@ public class PhotoView extends GLView { getRotated(mRotation, w, h), getRotated(mRotation, h, w)); } - updateScreenNail(mModel == null - ? null : mModel.getScreenNail(0)); + setScreenNail(mModel == null ? null : mModel.getScreenNail(0)); updateLoadingState(); } @@ -374,14 +343,9 @@ public class PhotoView extends GLView { } @Override - public void updateScreenNail(ScreenNail s) { + public void setScreenNail(ScreenNail s) { mIsNonBitmap = (s != null && !(s instanceof BitmapScreenNail)); - mTileView.updateScreenNail(s); - } - - @Override - public ScreenNail releaseScreenNail() { - return mTileView.releaseScreenNail(); + mTileView.setScreenNail(s); } @Override @@ -489,8 +453,7 @@ public class PhotoView extends GLView { @Override public void reload() { - updateScreenNail(mModel == null ? null - : mModel.getScreenNail(mIndex)); + setScreenNail(mModel == null ? null : mModel.getScreenNail(mIndex)); } @Override @@ -533,12 +496,9 @@ public class PhotoView extends GLView { } @Override - public void updateScreenNail(ScreenNail s) { + public void setScreenNail(ScreenNail s) { mEnabled = (s != null); if (mScreenNail == s) return; - if (mScreenNail != null) { - mScreenNail.pauseDraw(); - } mScreenNail = s; if (mScreenNail != null) { mRotation = mScreenNail.getRotation(); @@ -553,13 +513,6 @@ public class PhotoView extends GLView { } @Override - public ScreenNail releaseScreenNail() { - ScreenNail s = mScreenNail; - mScreenNail = null; - return s; - } - - @Override public boolean isEnabled() { return mEnabled; } @@ -704,6 +657,7 @@ public class PhotoView extends GLView { if (mFilmMode == enabled) return; mFilmMode = enabled; mPositionController.setFilmMode(mFilmMode); + mModel.setNeedFullImage(!enabled); } //////////////////////////////////////////////////////////////////////////// @@ -724,7 +678,7 @@ public class PhotoView extends GLView { mPositionController.skipAnimation(); mTileView.freeTextures(); for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) { - mPictures.get(i).updateScreenNail(null); + mPictures.get(i).setScreenNail(null); } } diff --git a/src/com/android/gallery3d/ui/PositionController.java b/src/com/android/gallery3d/ui/PositionController.java index 6650d246c..a5eb22425 100644 --- a/src/com/android/gallery3d/ui/PositionController.java +++ b/src/com/android/gallery3d/ui/PositionController.java @@ -578,7 +578,7 @@ class PositionController { if (changed) redraw(); } - public boolean advanceAnimation() { + public void advanceAnimation() { boolean changed = false; changed |= mPlatform.advanceAnimation(); for (int i = -BOX_MAX; i <= BOX_MAX; i++) { @@ -588,7 +588,6 @@ class PositionController { changed |= mGaps.get(i).advanceAnimation(); } if (changed) redraw(); - return changed; } //////////////////////////////////////////////////////////////////////////// diff --git a/src/com/android/gallery3d/ui/ScreenNail.java b/src/com/android/gallery3d/ui/ScreenNail.java index 58ae8c942..25adc77da 100644 --- a/src/com/android/gallery3d/ui/ScreenNail.java +++ b/src/com/android/gallery3d/ui/ScreenNail.java @@ -22,8 +22,12 @@ public interface ScreenNail { public int getHeight(); public int getRotation(); public void draw(GLCanvas canvas, int x, int y, int width, int height); - public void noDraw(); // we do not need to draw this ScreenNail in this frame. - public void pauseDraw(); // we do not expect to draw this ScreenNail for some time. + + // We do not need to draw this ScreenNail in this frame. + public void noDraw(); + + // This ScreenNail will not be used anymore. Release related resources. + public void recycle(); // This is only used by TileImageView to back up the tiles not yet loaded. public void draw(GLCanvas canvas, RectF source, RectF dest); diff --git a/src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java b/src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java index 3a8f2b0a4..f8442d059 100644 --- a/src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java +++ b/src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java @@ -109,7 +109,7 @@ public abstract class SurfaceTextureScreenNail implements ScreenNail, abstract public void noDraw(); @Override - abstract public void pauseDraw(); + abstract public void recycle(); @Override abstract public void onFrameAvailable(SurfaceTexture surfaceTexture); diff --git a/src/com/android/gallery3d/ui/TileImageView.java b/src/com/android/gallery3d/ui/TileImageView.java index 610a34688..b37cf9c4a 100644 --- a/src/com/android/gallery3d/ui/TileImageView.java +++ b/src/com/android/gallery3d/ui/TileImageView.java @@ -153,18 +153,10 @@ public class TileImageView extends GLView { if (model != null) notifyModelInvalidated(); } - public void updateScreenNail(ScreenNail s) { - if (mScreenNail == s) return; - if (mScreenNail != null) mScreenNail.pauseDraw(); + public void setScreenNail(ScreenNail s) { mScreenNail = s; } - public ScreenNail releaseScreenNail() { - ScreenNail s = mScreenNail; - mScreenNail = null; - return s; - } - public void notifyModelInvalidated() { invalidateTiles(); if (mModel == null) { @@ -173,7 +165,7 @@ public class TileImageView extends GLView { mImageHeight = 0; mLevelCount = 0; } else { - updateScreenNail(mModel.getScreenNail()); + setScreenNail(mModel.getScreenNail()); mImageWidth = mModel.getImageWidth(); mImageHeight = mModel.getImageHeight(); mLevelCount = mModel.getLevelCount(); @@ -389,7 +381,7 @@ public class TileImageView extends GLView { tile = mRecycledQueue.pop(); } } - updateScreenNail(null); + setScreenNail(null); } public void prepareTextures() { @@ -399,7 +391,7 @@ public class TileImageView extends GLView { if (mIsTextureFreed) { layoutTiles(mCenterX, mCenterY, mScale, mRotation); mIsTextureFreed = false; - updateScreenNail(mModel != null ? mModel.getScreenNail() : null); + setScreenNail(mModel == null ? null : mModel.getScreenNail()); } } diff --git a/src/com/android/gallery3d/ui/TileImageViewAdapter.java b/src/com/android/gallery3d/ui/TileImageViewAdapter.java index a441c21c2..8061657fd 100644 --- a/src/com/android/gallery3d/ui/TileImageViewAdapter.java +++ b/src/com/android/gallery3d/ui/TileImageViewAdapter.java @@ -28,6 +28,7 @@ import com.android.gallery3d.common.Utils; public class TileImageViewAdapter implements TileImageView.Model { private static final String TAG = "TileImageViewAdapter"; protected ScreenNail mScreenNail; + protected boolean mOwnScreenNail; protected BitmapRegionDecoder mRegionDecoder; protected int mImageWidth; protected int mImageHeight; @@ -37,8 +38,10 @@ public class TileImageViewAdapter implements TileImageView.Model { public TileImageViewAdapter() { } - public TileImageViewAdapter(Bitmap bitmap, BitmapRegionDecoder regionDecoder) { - mScreenNail = new BitmapScreenNail(Utils.checkNotNull(bitmap), 0); + public TileImageViewAdapter( + Bitmap bitmap, BitmapRegionDecoder regionDecoder) { + Utils.checkNotNull(bitmap); + updateScreenNail(new BitmapScreenNail(bitmap, 0), true); mRegionDecoder = regionDecoder; mImageWidth = regionDecoder.getWidth(); mImageHeight = regionDecoder.getHeight(); @@ -46,7 +49,7 @@ public class TileImageViewAdapter implements TileImageView.Model { } public synchronized void clear() { - mScreenNail = null; + updateScreenNail(null, false); mImageWidth = 0; mImageHeight = 0; mLevelCount = 0; @@ -55,7 +58,8 @@ public class TileImageViewAdapter implements TileImageView.Model { } public synchronized void setScreenNail(Bitmap bitmap, int width, int height) { - mScreenNail = new BitmapScreenNail(Utils.checkNotNull(bitmap), 0); + Utils.checkNotNull(bitmap); + updateScreenNail(new BitmapScreenNail(bitmap, 0), true); mImageWidth = width; mImageHeight = height; mRegionDecoder = null; @@ -65,7 +69,8 @@ public class TileImageViewAdapter implements TileImageView.Model { public synchronized void setScreenNail( ScreenNail screenNail, int width, int height) { - mScreenNail = Utils.checkNotNull(screenNail); + Utils.checkNotNull(screenNail); + updateScreenNail(screenNail, false); mImageWidth = width; mImageHeight = height; mRegionDecoder = null; @@ -73,6 +78,14 @@ public class TileImageViewAdapter implements TileImageView.Model { mFailedToLoad = false; } + private void updateScreenNail(ScreenNail screenNail, boolean own) { + if (mScreenNail != null && mOwnScreenNail) { + mScreenNail.recycle(); + } + mScreenNail = screenNail; + mOwnScreenNail = own; + } + public synchronized void setRegionDecoder(BitmapRegionDecoder decoder) { mRegionDecoder = Utils.checkNotNull(decoder); mImageWidth = decoder.getWidth(); |