From 037e06c5e11ca4a4e40b0741f2d6604b2fd9337a Mon Sep 17 00:00:00 2001 From: Chih-Chung Chang Date: Thu, 22 Mar 2012 17:42:33 +0800 Subject: Use SurfaceTexture to show Camera preview. Change-Id: I8bf63dfc5b969ecce51841378b093a650b6f91d8 --- src/com/android/gallery3d/app/AlbumPage.java | 6 + .../android/gallery3d/app/CameraScreenNail.java | 225 +++++++++++++++++++++ src/com/android/gallery3d/app/CameraView.java | 117 ----------- .../android/gallery3d/app/PhotoDataAdapter.java | 2 +- src/com/android/gallery3d/app/PhotoPage.java | 72 +++---- .../android/gallery3d/app/ScreenNailBridge.java | 122 ----------- src/com/android/gallery3d/data/SnailSource.java | 15 +- src/com/android/gallery3d/ui/BasicTexture.java | 3 + src/com/android/gallery3d/ui/BitmapScreenNail.java | 10 +- .../android/gallery3d/ui/BitmapTileProvider.java | 2 +- src/com/android/gallery3d/ui/ExtTexture.java | 89 ++++++++ src/com/android/gallery3d/ui/GLCanvas.java | 6 +- src/com/android/gallery3d/ui/GLCanvasImpl.java | 47 +++-- src/com/android/gallery3d/ui/GLId.java | 40 ++++ src/com/android/gallery3d/ui/NinePatchTexture.java | 2 +- src/com/android/gallery3d/ui/PhotoView.java | 29 +-- src/com/android/gallery3d/ui/ScreenNail.java | 6 +- src/com/android/gallery3d/ui/ScreenNailHolder.java | 31 +++ .../gallery3d/ui/SurfaceTextureScreenNail.java | 116 +++++++++++ src/com/android/gallery3d/ui/TileImageView.java | 12 +- src/com/android/gallery3d/ui/UploadedTexture.java | 7 +- .../src/com/android/gallery3d/ui/GLCanvasStub.java | 2 + .../src/com/android/gallery3d/ui/TextureTest.java | 10 + 23 files changed, 643 insertions(+), 328 deletions(-) create mode 100644 src/com/android/gallery3d/app/CameraScreenNail.java delete mode 100644 src/com/android/gallery3d/app/CameraView.java delete mode 100644 src/com/android/gallery3d/app/ScreenNailBridge.java create mode 100644 src/com/android/gallery3d/ui/ExtTexture.java create mode 100644 src/com/android/gallery3d/ui/GLId.java create mode 100644 src/com/android/gallery3d/ui/ScreenNailHolder.java create mode 100644 src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java diff --git a/src/com/android/gallery3d/app/AlbumPage.java b/src/com/android/gallery3d/app/AlbumPage.java index 8bd2badf8..37ddb184c 100644 --- a/src/com/android/gallery3d/app/AlbumPage.java +++ b/src/com/android/gallery3d/app/AlbumPage.java @@ -51,6 +51,7 @@ import com.android.gallery3d.ui.HighlightDrawer; import com.android.gallery3d.ui.PositionProvider; import com.android.gallery3d.ui.PositionRepository; import com.android.gallery3d.ui.PositionRepository.Position; +import com.android.gallery3d.ui.ScreenNailHolder; import com.android.gallery3d.ui.SelectionManager; import com.android.gallery3d.ui.SlotView; import com.android.gallery3d.util.Future; @@ -77,6 +78,7 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster private static final int BIT_LOADING_SYNC = 2; private static final float USER_DISTANCE_METER = 0.3f; + private static final boolean TEST_CAMERA_PREVIEW = false; private boolean mIsActive = false; private AlbumView mAlbumView; @@ -196,6 +198,10 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster mMediaSetPath.toString()); data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, item.getPath().toString()); + if (TEST_CAMERA_PREVIEW) { + ScreenNailHolder holder = new CameraScreenNailHolder(mActivity); + data.putParcelable(PhotoPage.KEY_SCREENNAIL_HOLDER, holder); + } mActivity.getStateManager().startStateForResult( PhotoPage.class, REQUEST_PHOTO, data); } diff --git a/src/com/android/gallery3d/app/CameraScreenNail.java b/src/com/android/gallery3d/app/CameraScreenNail.java new file mode 100644 index 000000000..f68ab72f8 --- /dev/null +++ b/src/com/android/gallery3d/app/CameraScreenNail.java @@ -0,0 +1,225 @@ +/* + * 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.app; + +import android.app.Activity; +import android.graphics.SurfaceTexture; +import android.hardware.Camera; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Message; +import android.util.Log; +import android.view.Surface; + +import com.android.gallery3d.ui.GLCanvas; +import com.android.gallery3d.ui.ScreenNail; +import com.android.gallery3d.ui.ScreenNailHolder; +import com.android.gallery3d.ui.SurfaceTextureScreenNail; + +// This is a ScreenNail which displays camera preview. This demos the usage of +// SurfaceTextureScreenNail. It is not intended for production use. +class CameraScreenNail extends SurfaceTextureScreenNail { + private static final String TAG = "CameraScreenNail"; + private static final int CAMERA_ID = 0; + private static final int PREVIEW_WIDTH = 960; + private static final int PREVIEW_HEIGHT = 720; + private static final int MSG_START_CAMERA = 1; + private static final int MSG_STOP_CAMERA = 2; + + public interface Listener { + void requestRender(); + } + + private Activity mActivity; + private Listener mListener; + private int mOrientation; + private Camera mCamera; + + private HandlerThread mHandlerThread; + private Handler mHandler; + private volatile boolean mVisible; + private volatile boolean mHasFrame; + + public CameraScreenNail(Activity activity, Listener listener) { + mActivity = activity; + mListener = listener; + + mOrientation = getCameraDisplayOrientation(mActivity, CAMERA_ID); + if (mOrientation % 180 == 0) { + setSize(PREVIEW_WIDTH, PREVIEW_HEIGHT); + } else { + setSize(PREVIEW_HEIGHT, PREVIEW_WIDTH); + } + + mHandlerThread = new HandlerThread("Camera"); + mHandlerThread.start(); + mHandler = new Handler(mHandlerThread.getLooper()) { + public void handleMessage(Message message) { + if (message.what == MSG_START_CAMERA && mCamera == null) { + startCamera(); + } else if (message.what == MSG_STOP_CAMERA && mCamera != null) { + stopCamera(); + } + } + }; + mHandler.sendEmptyMessage(MSG_START_CAMERA); + } + + private void startCamera() { + try { + acquireSurfaceTexture(); + Camera camera = Camera.open(CAMERA_ID); + Camera.Parameters param = camera.getParameters(); + param.setPreviewSize(PREVIEW_WIDTH, PREVIEW_HEIGHT); + camera.setParameters(param); + camera.setDisplayOrientation(mOrientation); + camera.setPreviewTexture(getSurfaceTexture()); + camera.startPreview(); + synchronized (this) { + mCamera = camera; + } + } catch (Throwable th) { + Log.e(TAG, "cannot open camera", th); + } + } + + private void stopCamera() { + releaseSurfaceTexture(); + mCamera.stopPreview(); + mCamera.release(); + synchronized (this) { + mCamera = null; + notifyAll(); + } + mHasFrame = false; + } + + @Override + public void draw(GLCanvas canvas, int x, int y, int width, int height) { + if (!mVisible) { + mVisible = true; + // Only send one message when mVisible makes transition from + // false to true. + mHandler.sendEmptyMessage(MSG_START_CAMERA); + } + + if (mVisible && mHasFrame) { + super.draw(canvas, x, y, width, height); + } + } + + @Override + public void noDraw() { + mVisible = false; + } + + @Override + public void pauseDraw() { + mVisible = false; + } + + @Override + public void onFrameAvailable(SurfaceTexture surfaceTexture) { + mHasFrame = true; + if (mVisible) { + // We need to ask for re-render if the SurfaceTexture receives a new + // frame (and we are visible). + mListener.requestRender(); + } + } + + public void destroy() { + synchronized (this) { + mHandler.sendEmptyMessage(MSG_STOP_CAMERA); + + // Wait until camera is closed. + while (mCamera != null) { + try { + wait(); + } catch (Exception ex) { + // ignore. + } + } + } + mHandlerThread.quit(); + } + + // The three methods below are copied from Camera.java + private static int getCameraDisplayOrientation( + Activity activity, int cameraId) { + int displayRotation = getDisplayRotation(activity); + int displayOrientation = getDisplayOrientation( + displayRotation, cameraId); + return displayOrientation; + } + + private static int getDisplayRotation(Activity activity) { + int rotation = activity.getWindowManager().getDefaultDisplay() + .getRotation(); + switch (rotation) { + case Surface.ROTATION_0: return 0; + case Surface.ROTATION_90: return 90; + case Surface.ROTATION_180: return 180; + case Surface.ROTATION_270: return 270; + } + return 0; + } + + private static int getDisplayOrientation(int degrees, int cameraId) { + // See android.hardware.Camera.setDisplayOrientation for + // documentation. + Camera.CameraInfo info = new Camera.CameraInfo(); + Camera.getCameraInfo(cameraId, info); + int result; + if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { + result = (info.orientation + degrees) % 360; + result = (360 - result) % 360; // compensate the mirror + } else { // back-facing + result = (info.orientation - degrees + 360) % 360; + } + return result; + } +} + +// This holds a CameraScreenNail, so we can pass it to a PhotoPage. +class CameraScreenNailHolder extends ScreenNailHolder + implements CameraScreenNail.Listener { + private static final String TAG = "CameraScreenNailHolder"; + private GalleryActivity mActivity; + private CameraScreenNail mCameraScreenNail; + + public CameraScreenNailHolder(GalleryActivity activity) { + mActivity = activity; + } + + @Override + public void requestRender() { + mActivity.getGLRoot().requestRender(); + } + + @Override + public ScreenNail attach() { + mCameraScreenNail = new CameraScreenNail((Activity) mActivity, this); + return mCameraScreenNail; + } + + @Override + public void detach() { + mCameraScreenNail.destroy(); + mCameraScreenNail = null; + } +} diff --git a/src/com/android/gallery3d/app/CameraView.java b/src/com/android/gallery3d/app/CameraView.java deleted file mode 100644 index a6c233291..000000000 --- a/src/com/android/gallery3d/app/CameraView.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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.app; - -import android.content.Context; -import android.graphics.SurfaceTexture; -import android.hardware.Camera; -import android.util.AttributeSet; -import android.util.Log; -import android.view.TextureView; -import android.view.View; - -import java.io.IOException; - -// This is a sample View which demos the usage of ScreenNailBridge. It -// is not intended for production use. -public class CameraView extends TextureView implements - TextureView.SurfaceTextureListener, ScreenNailBridge.Listener { - private static final String TAG = "CameraView"; - private static final int PREVIEW_WIDTH = 960; - private static final int PREVIEW_HEIGHT = 720; - private Camera mCamera; - private ScreenNailBridge mScreenNailBridge; - - public CameraView(Context context) { - super(context); - init(); - } - - public CameraView(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - private void init() { - setVisibility(View.INVISIBLE); - setSurfaceTextureListener(this); - } - - public void setScreenNailBridge(ScreenNailBridge s) { - mScreenNailBridge = s; - } - - @Override - public void onMeasure(int widthSpec, int heightSpec) { - int width = getDefaultSize(PREVIEW_WIDTH, widthSpec); - int height = getDefaultSize(PREVIEW_HEIGHT, heightSpec); - // Keep aspect ratio - if (width * PREVIEW_HEIGHT > PREVIEW_WIDTH * height) { - width = PREVIEW_WIDTH * height / PREVIEW_HEIGHT; - } else { - height = PREVIEW_HEIGHT * width / PREVIEW_WIDTH; - } - setMeasuredDimension(width, height); - } - - @Override - public void onSizeChanged(int w, int h, int oldw, int oldh) { - mScreenNailBridge.setSize(w, h); - } - - @Override - public void updateView(boolean visible, int x, int y, int w, int h) { - if (!visible) { - setVisibility(View.INVISIBLE); - } else { - setVisibility(View.VISIBLE); - setTranslationX(x); - setTranslationY(y); - } - } - - @Override - public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { - try { - mCamera = Camera.open(); - - Camera.Parameters param = mCamera.getParameters(); - param.setPreviewSize(PREVIEW_WIDTH, PREVIEW_HEIGHT); - mCamera.setParameters(param); - - mCamera.setPreviewTexture(surface); - mCamera.startPreview(); - } catch (Throwable ex) { - Log.e(TAG, "failed to open camera", ex); - } - } - - @Override - public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { - mCamera.stopPreview(); - mCamera.release(); - return true; - } - - @Override - public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { - } - - @Override - public void onSurfaceTextureUpdated(SurfaceTexture surface) { - } -} diff --git a/src/com/android/gallery3d/app/PhotoDataAdapter.java b/src/com/android/gallery3d/app/PhotoDataAdapter.java index a4fd411af..109323c1c 100644 --- a/src/com/android/gallery3d/app/PhotoDataAdapter.java +++ b/src/com/android/gallery3d/app/PhotoDataAdapter.java @@ -221,7 +221,7 @@ public class PhotoDataAdapter implements PhotoPage.Model { ScreenNail screenNail = future.get(); if (entry == null || entry.screenNailTask != future) { - if (screenNail != null) screenNail.recycle(); + if (screenNail != null) screenNail.pauseDraw(); return; } diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java index 3a18dd2e4..9a1992e54 100644 --- a/src/com/android/gallery3d/app/PhotoPage.java +++ b/src/com/android/gallery3d/app/PhotoPage.java @@ -55,6 +55,8 @@ import com.android.gallery3d.ui.GLCanvas; import com.android.gallery3d.ui.GLView; import com.android.gallery3d.ui.ImportCompleteListener; import com.android.gallery3d.ui.MenuExecutor; +import com.android.gallery3d.ui.ScreenNail; +import com.android.gallery3d.ui.ScreenNailHolder; import com.android.gallery3d.ui.PhotoView; import com.android.gallery3d.ui.PositionRepository; import com.android.gallery3d.ui.PositionRepository.Position; @@ -80,6 +82,7 @@ public class PhotoPage extends ActivityState public static final String KEY_MEDIA_ITEM_PATH = "media-item-path"; public static final String KEY_INDEX_HINT = "index-hint"; public static final String KEY_OPEN_ANIMATION_RECT = "open-animation-rect"; + public static final String KEY_SCREENNAIL_HOLDER = "screennail-holder"; private GalleryApp mApplication; private SelectionManager mSelectionManager; @@ -109,11 +112,8 @@ public class PhotoPage extends ActivityState private boolean mIsActive; private ShareActionProvider mShareActionProvider; private String mSetPathString; - - // This is for testing only. It should be removed once we have the real - // Camera view. - private CameraView mCameraView; - private ScreenNailBridge mScreenNail; + private ScreenNailHolder mScreenNailHolder; + private ScreenNail mScreenNail; public static interface Model extends PhotoView.Model { public void resume(); @@ -190,14 +190,24 @@ public class PhotoPage extends ActivityState Path itemPath = Path.fromString(data.getString(KEY_MEDIA_ITEM_PATH)); if (mSetPathString != null) { - // Uncomment the block below to test camera screennail. - /* - Path cameraScreenNailSetPath = addCameraScreenNail(); - - // Combine the original MediaSet with the one for camera ScreenNail. - mSetPathString = "/combo/item/{" + cameraScreenNailSetPath + "," + - mSetPathString + "}"; - */ + mScreenNailHolder = + (ScreenNailHolder) data.getParcelable(KEY_SCREENNAIL_HOLDER); + if (mScreenNailHolder != null) { + mScreenNail = mScreenNailHolder.attach(); + + // Get the ScreenNail from ScreenNailHolder and register it. + int id = SnailSource.registerScreenNail(mScreenNail); + Path screenNailSetPath = SnailSource.getSetPath(id); + Path screenNailItemPath = SnailSource.getItemPath(id); + + // Combine the original MediaSet with the one for CameraScreenNail. + mSetPathString = "/combo/item/{" + screenNailSetPath + + "," + mSetPathString + "}"; + + // Start from the screen nail. + itemPath = screenNailItemPath; + } + mMediaSet = mActivity.getDataManager().getMediaSet(mSetPathString); mCurrentIndex = data.getInt(KEY_INDEX_HINT, 0); mMediaSet = (MediaSet) @@ -279,34 +289,6 @@ public class PhotoPage extends ActivityState } } - // We create a Camera View and a ScreenNail. The two work together - // to present the view together with other pictures. Returns the - // Path of the MediaItem hosting the ScreenNail. - private Path addCameraScreenNail() { - // Create a camera view and add it to the root. - Activity activity = (Activity) mActivity; - mCameraView = new CameraView(activity); - ViewGroup galleryRoot = (ViewGroup) activity.findViewById(R.id.gallery_root); - galleryRoot.addView(mCameraView); - - // Create a ScreenNail and register it. - mScreenNail = new ScreenNailBridge(mCameraView); - mCameraView.setScreenNailBridge(mScreenNail); - return SnailSource.registerScreenNail(mScreenNail); - } - - private void removeCameraScreenNail() { - if (mCameraView == null) return; - - // Remove the camera view. - ((ViewGroup) mCameraView.getParent()).removeView(mCameraView); - mCameraView = null; - - // Unregister the ScreenNail. - SnailSource.unregisterScreenNail(mScreenNail); - mScreenNail = null; - } - private void updateShareURI(Path path) { if (mShareActionProvider != null) { DataManager manager = mActivity.getDataManager(); @@ -690,7 +672,13 @@ public class PhotoPage extends ActivityState @Override protected void onDestroy() { - removeCameraScreenNail(); + if (mScreenNailHolder != null) { + // Unregister the ScreenNail and notify mScreenNailHolder. + SnailSource.unregisterScreenNail(mScreenNail); + mScreenNailHolder.detach(); + mScreenNailHolder = null; + mScreenNail = null; + } super.onDestroy(); } diff --git a/src/com/android/gallery3d/app/ScreenNailBridge.java b/src/com/android/gallery3d/app/ScreenNailBridge.java deleted file mode 100644 index 9da197dca..000000000 --- a/src/com/android/gallery3d/app/ScreenNailBridge.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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.app; - -import android.graphics.RectF; -import android.os.Handler; -import android.util.Log; - -import com.android.gallery3d.ui.GLCanvas; -import com.android.gallery3d.ui.ScreenNail; - -// This is a ScreenNail whose actually display is done by an foreign component. -// The foreign component tells the ScreenNail its size by setSize(). The -// ScreenNail tells the foreign component the position to display by -// updateView(). -class ScreenNailBridge implements ScreenNail { - private static final String TAG = "ScreenNailBridge"; - private int mWidth, mHeight; - private boolean mVisible = false; - private int mDrawX, mDrawY, mDrawWidth, mDrawHeight; - private Listener mListener; - private Handler mMainHandler; - - public interface Listener { - // This is called from the main thread. - void updateView(boolean visible, int x, int y, int width, int height); - }; - - // The constructor should be called from the main thread. - public ScreenNailBridge(Listener listener) { - mListener = listener; - mMainHandler = new Handler(); - } - - // This can be called from any thread. (We expect it to be called from the - // main thread). - public synchronized void setSize(int w, int h) { - mWidth = w; - mHeight = h; - } - - // This can be called from any thread. (We expect it to be called from GL - // thread) - @Override - public synchronized int getWidth() { - return mWidth; - } - - // This can be called from any thread. (We expect it to be called from GL - // thread) - @Override - public synchronized int getHeight() { - return mHeight; - } - - @Override - public int getRotation() { - return 0; - } - - // This is run in the main thread. - private Runnable mUpdateViewRunnable = new Runnable() { - public void run() { - boolean v; - int x, y, width, height; - synchronized (ScreenNailBridge.this) { - v = mVisible; - x = mDrawX; - y = mDrawY; - width = mDrawWidth; - height = mDrawHeight; - } - mListener.updateView(v, x, y, width, height); - } - }; - - @Override - public synchronized void draw(GLCanvas canvas, int x, int y, int width, int height) { - if (mVisible && mDrawX == x && mDrawY == y && mDrawWidth == width && - mDrawHeight == height) { - return; - } - mVisible = true; - mDrawX = x; - mDrawY = y; - mDrawWidth = width; - mDrawHeight = height; - mMainHandler.post(mUpdateViewRunnable); - } - - @Override - public synchronized void disableDraw() { - if (!mVisible) return; - mVisible = false; - mMainHandler.post(mUpdateViewRunnable); - } - - @Override - public void recycle() { - // Make sure we will not draw anymore. - disableDraw(); - } - - @Override - public void draw(GLCanvas canvas, RectF source, RectF dest) { - throw new UnsupportedOperationException(); - } -} diff --git a/src/com/android/gallery3d/data/SnailSource.java b/src/com/android/gallery3d/data/SnailSource.java index 17b899dba..e74a8bb94 100644 --- a/src/com/android/gallery3d/data/SnailSource.java +++ b/src/com/android/gallery3d/data/SnailSource.java @@ -55,14 +55,23 @@ public class SnailSource extends MediaSource { return null; } - // Register a ScreenNail. Returns the Path of the MediaSet - // containing the MediaItem associated with the ScreenNail. - public static synchronized Path registerScreenNail(ScreenNail s) { + // Registers a ScreenNail and returns the id of it. You can obtain the Path + // of the MediaItem associated with the ScreenNail by getItemPath(), and the + // Path of the MediaSet containing that MediaItem by getSetPath(). + public static synchronized int registerScreenNail(ScreenNail s) { int id = sNextId++; sRegistry.put(id, s); + return id; + } + + public static Path getSetPath(int id) { return Path.fromString("/snail/set").getChild(id); } + public static Path getItemPath(int id) { + return Path.fromString("/snail/item").getChild(id); + } + public static synchronized void unregisterScreenNail(ScreenNail s) { int index = sRegistry.indexOfValue(s); sRegistry.removeAt(index); diff --git a/src/com/android/gallery3d/ui/BasicTexture.java b/src/com/android/gallery3d/ui/BasicTexture.java index d3dfd745c..6a9a17d92 100644 --- a/src/com/android/gallery3d/ui/BasicTexture.java +++ b/src/com/android/gallery3d/ui/BasicTexture.java @@ -130,6 +130,9 @@ abstract class BasicTexture implements Texture { // It should make sure the data is uploaded to GL memory. abstract protected boolean onBind(GLCanvas canvas); + // Returns the GL texture target for this texture (e.g. GL_TEXTURE_2D). + abstract protected int getTarget(); + public boolean isLoaded(GLCanvas canvas) { return mState == STATE_LOADED; } diff --git a/src/com/android/gallery3d/ui/BitmapScreenNail.java b/src/com/android/gallery3d/ui/BitmapScreenNail.java index 117a9ac30..5a1006845 100644 --- a/src/com/android/gallery3d/ui/BitmapScreenNail.java +++ b/src/com/android/gallery3d/ui/BitmapScreenNail.java @@ -56,7 +56,11 @@ public class BitmapScreenNail implements ScreenNail { } @Override - public void recycle() { + public void noDraw() { + } + + @Override + public void pauseDraw() { if (mTexture != null) { mTexture.recycle(); } @@ -70,10 +74,6 @@ public class BitmapScreenNail implements ScreenNail { mTexture.draw(canvas, x, y, width, height); } - @Override - public void disableDraw() { - } - @Override public void draw(GLCanvas canvas, RectF source, RectF dest) { if (mTexture == null) { diff --git a/src/com/android/gallery3d/ui/BitmapTileProvider.java b/src/com/android/gallery3d/ui/BitmapTileProvider.java index 99b64d42e..1e78cfd33 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.recycle(); + mScreenNail.pauseDraw(); } } diff --git a/src/com/android/gallery3d/ui/ExtTexture.java b/src/com/android/gallery3d/ui/ExtTexture.java new file mode 100644 index 000000000..e39f317a3 --- /dev/null +++ b/src/com/android/gallery3d/ui/ExtTexture.java @@ -0,0 +1,89 @@ +/* + * 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; + +import android.graphics.SurfaceTexture; +import javax.microedition.khronos.opengles.GL11; +import javax.microedition.khronos.opengles.GL11Ext; + +// ExtTexture is a texture whose content comes from a external texture. +// Before drawing, setSize() should be called. +public class ExtTexture extends BasicTexture { + + private static int[] sTextureId = new int[1]; + private static float[] sCropRect = new float[4]; + private int mTarget; + + public ExtTexture(int target) { + GLId.glGenTextures(1, sTextureId, 0); + mId = sTextureId[0]; + mTarget = target; + } + + private void uploadToCanvas(GLCanvas canvas) { + GL11 gl = canvas.getGLInstance(); + + int width = getWidth(); + int height = getHeight(); + // Define a vertically flipped crop rectangle for OES_draw_texture. + // The four values in sCropRect are: left, bottom, width, and + // height. Negative value of width or height means flip. + sCropRect[0] = 0; + sCropRect[1] = height; + sCropRect[2] = width; + sCropRect[3] = -height; + + // Set texture parameters. + gl.glBindTexture(mTarget, mId); + gl.glTexParameterfv(mTarget, + GL11Ext.GL_TEXTURE_CROP_RECT_OES, sCropRect, 0); + gl.glTexParameteri(mTarget, + GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP_TO_EDGE); + gl.glTexParameteri(mTarget, + GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP_TO_EDGE); + gl.glTexParameterf(mTarget, + GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); + gl.glTexParameterf(mTarget, + GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); + + setAssociatedCanvas(canvas); + mState = UploadedTexture.STATE_LOADED; + } + + @Override + protected boolean onBind(GLCanvas canvas) { + if (!isLoaded(canvas)) { + uploadToCanvas(canvas); + } + + return true; + } + + @Override + public int getTarget() { + return mTarget; + } + + public boolean isOpaque() { + return true; + } + + @Override + public void yield() { + // we cannot free the texture because we have no backup. + } +} diff --git a/src/com/android/gallery3d/ui/GLCanvas.java b/src/com/android/gallery3d/ui/GLCanvas.java index 1359115f8..9b8053ffc 100644 --- a/src/com/android/gallery3d/ui/GLCanvas.java +++ b/src/com/android/gallery3d/ui/GLCanvas.java @@ -85,9 +85,13 @@ public interface GLCanvas { public void drawMesh(BasicTexture tex, int x, int y, int xyBuffer, int uvBuffer, int indexBuffer, int indexCount); - // Draws a the source rectangle part of the texture to the target rectangle. + // Draws the source rectangle part of the texture to the target rectangle. public void drawTexture(BasicTexture texture, RectF source, RectF target); + // Draw a texture with a specified texture transform. + public void drawTexture(BasicTexture texture, float[] mTextureTransform, + int x, int y, int w, int h); + // Draw two textures to the specified rectangle. The actual texture used is // from * (1 - ratio) + to * ratio // The two textures must have the same size. diff --git a/src/com/android/gallery3d/ui/GLCanvasImpl.java b/src/com/android/gallery3d/ui/GLCanvasImpl.java index 68f5636f7..686e712bd 100644 --- a/src/com/android/gallery3d/ui/GLCanvasImpl.java +++ b/src/com/android/gallery3d/ui/GLCanvasImpl.java @@ -136,7 +136,7 @@ public class GLCanvasImpl implements GLCanvas { xyBuffer.put(BOX_COORDINATES, 0, BOX_COORDINATES.length).position(0); int[] name = new int[1]; - gl.glGenBuffers(1, name, 0); + GLId.glGenBuffers(1, name, 0); mBoxCoords = name[0]; gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, mBoxCoords); @@ -377,6 +377,16 @@ public class GLCanvasImpl implements GLCanvas { textureRect(target.left, target.top, target.width(), target.height()); } + public void drawTexture(BasicTexture texture, float[] mTextureTransform, + int x, int y, int w, int h) { + mGLState.setBlendEnabled(mBlendEnabled + && (!texture.isOpaque() || mAlpha < OPAQUE_ALPHA)); + if (!bindTexture(texture)) return; + setTextureCoords(mTextureTransform); + mGLState.setTextureAlpha(mAlpha); + textureRect(x, y, w, h); + } + // This function changes the source coordinate to the texture coordinates. // It also clips the source and target coordinates if it is beyond the // bound of the texture. @@ -415,8 +425,9 @@ public class GLCanvasImpl implements GLCanvas { private boolean bindTexture(BasicTexture texture) { if (!texture.onBind(this)) return false; - mGLState.setTexture2DEnabled(true); - mGL.glBindTexture(GL11.GL_TEXTURE_2D, texture.getId()); + int target = texture.getTarget(); + mGLState.setTextureTarget(target); + mGL.glBindTexture(target, texture.getId()); return true; } @@ -513,7 +524,7 @@ public class GLCanvasImpl implements GLCanvas { private int mTexEnvMode = GL11.GL_REPLACE; private float mTextureAlpha = 1.0f; - private boolean mTexture2DEnabled = true; + private int mTextureTarget = 0; private boolean mBlendEnabled = true; private float mLineWidth = 1.0f; private boolean mLineSmooth = false; @@ -578,7 +589,7 @@ public class GLCanvasImpl implements GLCanvas { // again in setTextureAlpha(float) later. mTextureAlpha = -1.0f; - setTexture2DEnabled(false); + setTextureTarget(0); float prealpha = (color >>> 24) * alpha * 65535f / 255f / 255f; mGL.glColor4x( @@ -588,13 +599,15 @@ public class GLCanvasImpl implements GLCanvas { Math.round(255 * prealpha)); } - public void setTexture2DEnabled(boolean enabled) { - if (mTexture2DEnabled == enabled) return; - mTexture2DEnabled = enabled; - if (enabled) { - mGL.glEnable(GL11.GL_TEXTURE_2D); - } else { - mGL.glDisable(GL11.GL_TEXTURE_2D); + // target is a value like GL_TEXTURE_2D. If target = 0, texturing is disabled. + public void setTextureTarget(int target) { + if (mTextureTarget == target) return; + if (mTextureTarget != 0) { + mGL.glDisable(mTextureTarget); + } + mTextureTarget = target; + if (mTextureTarget != 0) { + mGL.glEnable(mTextureTarget); } } @@ -634,6 +647,12 @@ public class GLCanvasImpl implements GLCanvas { mGL.glMatrixMode(GL11.GL_MODELVIEW); } + private void setTextureCoords(float[] mTextureTransform) { + mGL.glMatrixMode(GL11.GL_TEXTURE); + mGL.glLoadMatrixf(mTextureTransform, 0); + mGL.glMatrixMode(GL11.GL_MODELVIEW); + } + // unloadTexture and deleteBuffer can be called from the finalizer thread, // so we synchronized on the mUnboundTextures object. public boolean unloadTexture(BasicTexture t) { @@ -654,13 +673,13 @@ public class GLCanvasImpl implements GLCanvas { synchronized (mUnboundTextures) { IntArray ids = mUnboundTextures; if (ids.size() > 0) { - mGL.glDeleteTextures(ids.size(), ids.getInternalArray(), 0); + GLId.glDeleteTextures(ids.size(), ids.getInternalArray(), 0); ids.clear(); } ids = mDeleteBuffers; if (ids.size() > 0) { - mGL.glDeleteBuffers(ids.size(), ids.getInternalArray(), 0); + GLId.glDeleteBuffers(ids.size(), ids.getInternalArray(), 0); ids.clear(); } } diff --git a/src/com/android/gallery3d/ui/GLId.java b/src/com/android/gallery3d/ui/GLId.java new file mode 100644 index 000000000..c228c350d --- /dev/null +++ b/src/com/android/gallery3d/ui/GLId.java @@ -0,0 +1,40 @@ +/* + * 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; + +// This mimics corresponding GL functions. +public class GLId { + static int sNextId = 1; + + public synchronized static void glGenTextures(int n, int[] textures, int offset) { + while (n-- > 0) { + textures[offset + n] = sNextId++; + } + } + + public synchronized static void glGenBuffers(int n, int[] buffers, int offset) { + while (n-- > 0) { + buffers[offset + n] = sNextId++; + } + } + + public synchronized static void glDeleteTextures(int n, int[] textures, int offset) { + } + + public synchronized static void glDeleteBuffers(int n, int[] buffers, int offset) { + } +} diff --git a/src/com/android/gallery3d/ui/NinePatchTexture.java b/src/com/android/gallery3d/ui/NinePatchTexture.java index 6a2ba0037..957229eb5 100644 --- a/src/com/android/gallery3d/ui/NinePatchTexture.java +++ b/src/com/android/gallery3d/ui/NinePatchTexture.java @@ -398,7 +398,7 @@ class NinePatchInstance { private void prepareBuffers(GLCanvas canvas) { mBufferNames = new int[3]; GL11 gl = canvas.getGLInstance(); - gl.glGenBuffers(3, mBufferNames, 0); + GLId.glGenBuffers(3, mBufferNames, 0); gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, mBufferNames[0]); gl.glBufferData(GL11.GL_ARRAY_BUFFER, diff --git a/src/com/android/gallery3d/ui/PhotoView.java b/src/com/android/gallery3d/ui/PhotoView.java index 252f3484d..77e3d99e7 100644 --- a/src/com/android/gallery3d/ui/PhotoView.java +++ b/src/com/android/gallery3d/ui/PhotoView.java @@ -225,7 +225,7 @@ public class PhotoView extends GLView { return; } ScreenNailEntry entry = mScreenNails[which]; - entry.set(screenNail); + entry.updateScreenNail(screenNail); } // -1 previous, 0 current, 1 next @@ -650,10 +650,8 @@ public class PhotoView extends GLView { ScreenNailEntry prevNail = mScreenNails[ENTRY_PREVIOUS]; ScreenNailEntry nextNail = mScreenNails[ENTRY_NEXT]; mTileView.invalidateTiles(); - if (prevNail.mScreenNail != null) prevNail.mScreenNail.recycle(); - prevNail.set(mTileView.mScreenNail); - mTileView.updateScreenNail(nextNail.mScreenNail); - nextNail.set(null); + prevNail.updateScreenNail(mTileView.releaseScreenNail()); + mTileView.updateScreenNail(nextNail.releaseScreenNail()); mModel.next(); } @@ -662,10 +660,8 @@ public class PhotoView extends GLView { ScreenNailEntry prevNail = mScreenNails[ENTRY_PREVIOUS]; ScreenNailEntry nextNail = mScreenNails[ENTRY_NEXT]; mTileView.invalidateTiles(); - if (nextNail.mScreenNail != null) nextNail.mScreenNail.recycle(); - nextNail.set(mTileView.mScreenNail); - mTileView.updateScreenNail(prevNail.mScreenNail); - nextNail.set(null); + nextNail.updateScreenNail(mTileView.releaseScreenNail()); + mTileView.updateScreenNail(prevNail.releaseScreenNail()); mModel.previous(); } @@ -715,10 +711,10 @@ public class PhotoView extends GLView { private ScreenNail mScreenNail; - public void set(ScreenNail screenNail) { + public void updateScreenNail(ScreenNail screenNail) { mEnabled = (screenNail != null); if (mScreenNail == screenNail) return; - if (mScreenNail != null) mScreenNail.recycle(); + if (mScreenNail != null) mScreenNail.pauseDraw(); mScreenNail = screenNail; if (mScreenNail != null) { mRotation = mScreenNail.getRotation(); @@ -726,6 +722,13 @@ public class PhotoView extends GLView { } } + // Release the ownership of the ScreenNail from this entry. + public ScreenNail releaseScreenNail() { + ScreenNail s = mScreenNail; + mScreenNail = null; + return s; + } + public void layoutRightEdgeAt(int x) { mVisible = x > 0; mOffsetX = x - getRotated( @@ -767,7 +770,7 @@ public class PhotoView extends GLView { public void draw(GLCanvas canvas, boolean applyFadingAnimation) { if (mScreenNail == null) return; if (!mVisible) { - mScreenNail.disableDraw(); + mScreenNail.noDraw(); return; } @@ -877,7 +880,7 @@ public class PhotoView extends GLView { mTransitionMode = TRANS_NONE; mTileView.freeTextures(); for (ScreenNailEntry entry : mScreenNails) { - entry.set(null); + entry.updateScreenNail(null); } } diff --git a/src/com/android/gallery3d/ui/ScreenNail.java b/src/com/android/gallery3d/ui/ScreenNail.java index a2377fe2a..58ae8c942 100644 --- a/src/com/android/gallery3d/ui/ScreenNail.java +++ b/src/com/android/gallery3d/ui/ScreenNail.java @@ -21,11 +21,9 @@ public interface ScreenNail { public int getWidth(); public int getHeight(); public int getRotation(); - public void recycle(); public void draw(GLCanvas canvas, int x, int y, int width, int height); - - // We need this method to tell ScreenNail to stop displaying. - public void disableDraw(); + 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. // 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/ScreenNailHolder.java b/src/com/android/gallery3d/ui/ScreenNailHolder.java new file mode 100644 index 000000000..a7d541767 --- /dev/null +++ b/src/com/android/gallery3d/ui/ScreenNailHolder.java @@ -0,0 +1,31 @@ +/* + * 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; + +import android.os.Parcel; +import android.os.Parcelable; + +public abstract class ScreenNailHolder implements Parcelable { + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int flags) { + } + + public abstract ScreenNail attach(); + public abstract void detach(); +} diff --git a/src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java b/src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java new file mode 100644 index 000000000..3a8f2b0a4 --- /dev/null +++ b/src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java @@ -0,0 +1,116 @@ +/* + * 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; + +import android.graphics.RectF; +import android.graphics.SurfaceTexture; +import android.opengl.GLES11Ext; +import android.util.Log; + +import com.android.gallery3d.ui.GLCanvas; +import com.android.gallery3d.ui.ScreenNail; +import com.android.gallery3d.ui.ExtTexture; + +public abstract class SurfaceTextureScreenNail implements ScreenNail, + SurfaceTexture.OnFrameAvailableListener { + private static final String TAG = "SurfaceTextureScreenNail"; + private ExtTexture mExtTexture; + private SurfaceTexture mSurfaceTexture; + private int mWidth, mHeight; + private float[] mTransform = new float[16]; + private boolean mHasTexture = false; + + public SurfaceTextureScreenNail() { + } + + public void acquireSurfaceTexture() { + mExtTexture = new ExtTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES); + mExtTexture.setSize(mWidth, mHeight); + mSurfaceTexture = new SurfaceTexture(mExtTexture.getId()); + mSurfaceTexture.setOnFrameAvailableListener(this); + synchronized (this) { + mHasTexture = true; + } + } + + public SurfaceTexture getSurfaceTexture() { + return mSurfaceTexture; + } + + public void releaseSurfaceTexture() { + synchronized (this) { + mHasTexture = false; + } + mExtTexture.recycle(); + mExtTexture = null; + mSurfaceTexture.release(); + mSurfaceTexture = null; + } + + public void setSize(int width, int height) { + mWidth = width; + mHeight = height; + } + + @Override + public int getWidth() { + return mWidth; + } + + @Override + public int getHeight() { + return mHeight; + } + + @Override + public int getRotation() { + return 0; + } + + @Override + public void draw(GLCanvas canvas, int x, int y, int width, int height) { + synchronized (this) { + if (!mHasTexture) return; + mSurfaceTexture.updateTexImage(); + mSurfaceTexture.getTransformMatrix(mTransform); + + // Flip vertically. + canvas.save(GLCanvas.SAVE_FLAG_MATRIX); + int cx = x + width / 2; + int cy = y + height / 2; + canvas.translate(cx, cy); + canvas.scale(1, -1, 1); + canvas.translate(-cx, -cy); + canvas.drawTexture(mExtTexture, mTransform, x, y, width, height); + canvas.restore(); + } + } + + @Override + public void draw(GLCanvas canvas, RectF source, RectF dest) { + throw new UnsupportedOperationException(); + } + + @Override + abstract public void noDraw(); + + @Override + abstract public void pauseDraw(); + + @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 638a7f94b..d2ce1677a 100644 --- a/src/com/android/gallery3d/ui/TileImageView.java +++ b/src/com/android/gallery3d/ui/TileImageView.java @@ -71,7 +71,7 @@ public class TileImageView extends GLView { private static final int STATE_RECYCLED = 0x40; private Model mModel; - protected ScreenNail mScreenNail; + private ScreenNail mScreenNail; protected int mLevelCount; // cache the value of mScaledBitmaps.length // The mLevel variable indicates which level of bitmap we should use. @@ -155,10 +155,16 @@ public class TileImageView extends GLView { public void updateScreenNail(ScreenNail s) { if (mScreenNail == s) return; - if (mScreenNail != null) mScreenNail.recycle(); + if (mScreenNail != null) mScreenNail.pauseDraw(); mScreenNail = s; } + public ScreenNail releaseScreenNail() { + ScreenNail s = mScreenNail; + mScreenNail = null; + return s; + } + public void notifyModelInvalidated() { invalidateTiles(); if (mModel == null) { @@ -421,7 +427,7 @@ public class TileImageView extends GLView { try { if (level != mLevelCount) { if (mScreenNail != null) { - mScreenNail.disableDraw(); + mScreenNail.noDraw(); } int size = (TILE_SIZE << level); diff --git a/src/com/android/gallery3d/ui/UploadedTexture.java b/src/com/android/gallery3d/ui/UploadedTexture.java index c4d8d82f8..85aa1c4b2 100644 --- a/src/com/android/gallery3d/ui/UploadedTexture.java +++ b/src/com/android/gallery3d/ui/UploadedTexture.java @@ -228,7 +228,7 @@ abstract class UploadedTexture extends BasicTexture { sCropRect[3] = -bHeight; // Upload the bitmap to a new texture. - gl.glGenTextures(1, sTextureId, 0); + GLId.glGenTextures(1, sTextureId, 0); gl.glBindTexture(GL11.GL_TEXTURE_2D, sTextureId[0]); gl.glTexParameterfv(GL11.GL_TEXTURE_2D, GL11Ext.GL_TEXTURE_CROP_RECT_OES, sCropRect, 0); @@ -299,6 +299,11 @@ abstract class UploadedTexture extends BasicTexture { return isContentValid(canvas); } + @Override + protected int getTarget() { + return GL11.GL_TEXTURE_2D; + } + public void setOpaque(boolean isOpaque) { mOpaque = isOpaque; } diff --git a/tests/src/com/android/gallery3d/ui/GLCanvasStub.java b/tests/src/com/android/gallery3d/ui/GLCanvasStub.java index 70fef1a1c..ee43cb943 100644 --- a/tests/src/com/android/gallery3d/ui/GLCanvasStub.java +++ b/tests/src/com/android/gallery3d/ui/GLCanvasStub.java @@ -57,6 +57,8 @@ public class GLCanvasStub implements GLCanvas { public void drawTexture(BasicTexture texture, int x, int y, int width, int height, float alpha) {} public void drawTexture(BasicTexture texture, RectF source, RectF target) {} + public void drawTexture(BasicTexture texture, float[] mTextureTransform, + int x, int y, int w, int h) {} public void drawMixed(BasicTexture from, BasicTexture to, float ratio, int x, int y, int w, int h) {} public void drawMixed(BasicTexture from, int to, diff --git a/tests/src/com/android/gallery3d/ui/TextureTest.java b/tests/src/com/android/gallery3d/ui/TextureTest.java index 821d49bb1..be2356c8e 100644 --- a/tests/src/com/android/gallery3d/ui/TextureTest.java +++ b/tests/src/com/android/gallery3d/ui/TextureTest.java @@ -43,6 +43,11 @@ public class TextureTest extends TestCase { return true; } + @Override + protected int getTarget() { + return GL11.GL_TEXTURE_2D; + } + public boolean isOpaque() { mOpaqueCalled++; return true; @@ -171,6 +176,11 @@ public class TextureTest extends TestCase { return true; } + @Override + protected int getTarget() { + return GL11.GL_TEXTURE_2D; + } + public boolean isOpaque() { return true; } -- cgit v1.2.3