1104c45677660586026a7e74ef8c47d396403d50eMichael Jurka/* 2104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Copyright (C) 2013 The Android Open Source Project 3104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * 4104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Licensed under the Apache License, Version 2.0 (the "License"); 5104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * you may not use this file except in compliance with the License. 6104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * You may obtain a copy of the License at 7104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * 8104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * http://www.apache.org/licenses/LICENSE-2.0 9104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * 10104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Unless required by applicable law or agreed to in writing, software 11104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * distributed under the License is distributed on an "AS IS" BASIS, 12104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * See the License for the specific language governing permissions and 14104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * limitations under the License. 15104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 16104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 17104c45677660586026a7e74ef8c47d396403d50eMichael Jurkapackage com.android.photos.views; 18104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 19104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.annotation.SuppressLint; 20104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.annotation.TargetApi; 21104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.content.Context; 22104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.Bitmap; 23104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.Canvas; 24104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.Color; 25104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.Matrix; 26104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.Paint; 27104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.Paint.Align; 28104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.RectF; 29104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.opengl.GLSurfaceView; 30104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.opengl.GLSurfaceView.Renderer; 31104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.os.Build; 32104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.util.AttributeSet; 33104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.view.Choreographer; 34104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.view.Choreographer.FrameCallback; 35104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.view.View; 36104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.widget.FrameLayout; 37104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 38104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport com.android.gallery3d.glrenderer.BasicTexture; 39104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport com.android.gallery3d.glrenderer.GLES20Canvas; 40104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport com.android.photos.views.TiledImageRenderer.TileSource; 41104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 42104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport javax.microedition.khronos.egl.EGLConfig; 43104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport javax.microedition.khronos.opengles.GL10; 44104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 45104c45677660586026a7e74ef8c47d396403d50eMichael Jurka/** 46104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Shows an image using {@link TiledImageRenderer} using either {@link GLSurfaceView} 47104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * or {@link BlockingGLTextureView}. 48104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 49104c45677660586026a7e74ef8c47d396403d50eMichael Jurkapublic class TiledImageView extends FrameLayout { 50104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 51104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final boolean USE_TEXTURE_VIEW = false; 52104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final boolean IS_SUPPORTED = 53104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; 54104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final boolean USE_CHOREOGRAPHER = 55104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; 56104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 57104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private BlockingGLTextureView mTextureView; 58104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private GLSurfaceView mGLSurfaceView; 59104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private boolean mInvalPending = false; 60104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private FrameCallback mFrameCallback; 61104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 62104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected static class ImageRendererWrapper { 63104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Guarded by locks 64104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public float scale; 65104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public int centerX, centerY; 668713a94562c535bd2cc7d72e767caf9468d7bbaaMichael Jurka public int rotation; 67104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public TileSource source; 68104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Runnable isReadyCallback; 69104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 70104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // GL thread only 71104c45677660586026a7e74ef8c47d396403d50eMichael Jurka TiledImageRenderer image; 72104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 73104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 74104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private float[] mValues = new float[9]; 75104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 76104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // ------------------------- 77104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Guarded by mLock 78104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // ------------------------- 79104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected Object mLock = new Object(); 80104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected ImageRendererWrapper mRenderer; 81104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 82104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public static boolean isTilingSupported() { 83104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return IS_SUPPORTED; 84104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 85104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 86104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public TiledImageView(Context context) { 87104c45677660586026a7e74ef8c47d396403d50eMichael Jurka this(context, null); 88104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 89104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 90104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public TiledImageView(Context context, AttributeSet attrs) { 91104c45677660586026a7e74ef8c47d396403d50eMichael Jurka super(context, attrs); 92104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (!IS_SUPPORTED) { 93104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 94104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 95104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 96104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer = new ImageRendererWrapper(); 97104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.image = new TiledImageRenderer(this); 98104c45677660586026a7e74ef8c47d396403d50eMichael Jurka View view; 99104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (USE_TEXTURE_VIEW) { 100104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTextureView = new BlockingGLTextureView(context); 101104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTextureView.setRenderer(new TileRenderer()); 102104c45677660586026a7e74ef8c47d396403d50eMichael Jurka view = mTextureView; 103104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } else { 104104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mGLSurfaceView = new GLSurfaceView(context); 105104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mGLSurfaceView.setEGLContextClientVersion(2); 106104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mGLSurfaceView.setRenderer(new TileRenderer()); 107104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); 108104c45677660586026a7e74ef8c47d396403d50eMichael Jurka view = mGLSurfaceView; 109104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 110104c45677660586026a7e74ef8c47d396403d50eMichael Jurka addView(view, new LayoutParams( 111104c45677660586026a7e74ef8c47d396403d50eMichael Jurka LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); 112104c45677660586026a7e74ef8c47d396403d50eMichael Jurka //setTileSource(new ColoredTiles()); 113104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 114104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 115ffed65886ecd83f52dc1c052897511c95a5f371aSelim Cinek @Override 116ffed65886ecd83f52dc1c052897511c95a5f371aSelim Cinek public void setVisibility(int visibility) { 117ffed65886ecd83f52dc1c052897511c95a5f371aSelim Cinek super.setVisibility(visibility); 118ffed65886ecd83f52dc1c052897511c95a5f371aSelim Cinek // need to update inner view's visibility because it seems like we're causing it to draw 119ffed65886ecd83f52dc1c052897511c95a5f371aSelim Cinek // from {@link #dispatchDraw} or {@link #invalidate} even if we are invisible. 120ffed65886ecd83f52dc1c052897511c95a5f371aSelim Cinek if (USE_TEXTURE_VIEW) { 121ffed65886ecd83f52dc1c052897511c95a5f371aSelim Cinek mTextureView.setVisibility(visibility); 122ffed65886ecd83f52dc1c052897511c95a5f371aSelim Cinek } else { 123ffed65886ecd83f52dc1c052897511c95a5f371aSelim Cinek mGLSurfaceView.setVisibility(visibility); 124ffed65886ecd83f52dc1c052897511c95a5f371aSelim Cinek } 125ffed65886ecd83f52dc1c052897511c95a5f371aSelim Cinek } 126ffed65886ecd83f52dc1c052897511c95a5f371aSelim Cinek 127104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void destroy() { 128104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (!IS_SUPPORTED) { 129104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 130104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 131104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (USE_TEXTURE_VIEW) { 132104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTextureView.destroy(); 133104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } else { 134104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mGLSurfaceView.queueEvent(mFreeTextures); 135104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 136104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 137104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 138104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private Runnable mFreeTextures = new Runnable() { 139104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 140104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 141104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void run() { 142104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.image.freeTextures(); 143104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 144104c45677660586026a7e74ef8c47d396403d50eMichael Jurka }; 145104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 146104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void onPause() { 147104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (!IS_SUPPORTED) { 148104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 149104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 150104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (!USE_TEXTURE_VIEW) { 151104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mGLSurfaceView.onPause(); 152104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 153104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 154104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 155104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void onResume() { 156104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (!IS_SUPPORTED) { 157104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 158104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 159104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (!USE_TEXTURE_VIEW) { 160104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mGLSurfaceView.onResume(); 161104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 162104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 163104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 164104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void setTileSource(TileSource source, Runnable isReadyCallback) { 165104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (!IS_SUPPORTED) { 166104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 167104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 168104c45677660586026a7e74ef8c47d396403d50eMichael Jurka synchronized (mLock) { 169104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.source = source; 170104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.isReadyCallback = isReadyCallback; 171104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.centerX = source != null ? source.getImageWidth() / 2 : 0; 172104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.centerY = source != null ? source.getImageHeight() / 2 : 0; 173104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.rotation = source != null ? source.getRotation() : 0; 174104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.scale = 0; 175104c45677660586026a7e74ef8c47d396403d50eMichael Jurka updateScaleIfNecessaryLocked(mRenderer); 176104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 177104c45677660586026a7e74ef8c47d396403d50eMichael Jurka invalidate(); 178104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 179104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 180104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 181104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected void onLayout(boolean changed, int left, int top, int right, 182104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int bottom) { 183104c45677660586026a7e74ef8c47d396403d50eMichael Jurka super.onLayout(changed, left, top, right, bottom); 184104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (!IS_SUPPORTED) { 185104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 186104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 187104c45677660586026a7e74ef8c47d396403d50eMichael Jurka synchronized (mLock) { 188104c45677660586026a7e74ef8c47d396403d50eMichael Jurka updateScaleIfNecessaryLocked(mRenderer); 189104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 190104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 191104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 192104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private void updateScaleIfNecessaryLocked(ImageRendererWrapper renderer) { 193104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (renderer == null || renderer.source == null 194104c45677660586026a7e74ef8c47d396403d50eMichael Jurka || renderer.scale > 0 || getWidth() == 0) { 195104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 196104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 197104c45677660586026a7e74ef8c47d396403d50eMichael Jurka renderer.scale = Math.min( 198104c45677660586026a7e74ef8c47d396403d50eMichael Jurka (float) getWidth() / (float) renderer.source.getImageWidth(), 199104c45677660586026a7e74ef8c47d396403d50eMichael Jurka (float) getHeight() / (float) renderer.source.getImageHeight()); 200104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 201104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 202104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 203104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected void dispatchDraw(Canvas canvas) { 204104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (!IS_SUPPORTED) { 205104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 206104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 207104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (USE_TEXTURE_VIEW) { 208104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTextureView.render(); 209104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 210104c45677660586026a7e74ef8c47d396403d50eMichael Jurka super.dispatchDraw(canvas); 211104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 212104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 213104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @SuppressLint("NewApi") 214104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 215104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void setTranslationX(float translationX) { 216104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (!IS_SUPPORTED) { 217104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 218104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 219104c45677660586026a7e74ef8c47d396403d50eMichael Jurka super.setTranslationX(translationX); 220104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 221104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 222104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 223104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void invalidate() { 224104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (!IS_SUPPORTED) { 225104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 226104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 227104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (USE_TEXTURE_VIEW) { 228104c45677660586026a7e74ef8c47d396403d50eMichael Jurka super.invalidate(); 229104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTextureView.invalidate(); 230104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } else { 231104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (USE_CHOREOGRAPHER) { 232104c45677660586026a7e74ef8c47d396403d50eMichael Jurka invalOnVsync(); 233104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } else { 234104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mGLSurfaceView.requestRender(); 235104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 236104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 237104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 238104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 239104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 240104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private void invalOnVsync() { 241104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (!mInvalPending) { 242104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mInvalPending = true; 243104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (mFrameCallback == null) { 244104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mFrameCallback = new FrameCallback() { 245104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 246104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void doFrame(long frameTimeNanos) { 247104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mInvalPending = false; 248104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mGLSurfaceView.requestRender(); 249104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 250104c45677660586026a7e74ef8c47d396403d50eMichael Jurka }; 251104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 252104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Choreographer.getInstance().postFrameCallback(mFrameCallback); 253104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 254104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 255104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 256104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private RectF mTempRectF = new RectF(); 257104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void positionFromMatrix(Matrix matrix) { 258104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (!IS_SUPPORTED) { 259104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 260104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 261104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (mRenderer.source != null) { 262104c45677660586026a7e74ef8c47d396403d50eMichael Jurka final int rotation = mRenderer.source.getRotation(); 263104c45677660586026a7e74ef8c47d396403d50eMichael Jurka final boolean swap = !(rotation % 180 == 0); 264104c45677660586026a7e74ef8c47d396403d50eMichael Jurka final int width = swap ? mRenderer.source.getImageHeight() 265104c45677660586026a7e74ef8c47d396403d50eMichael Jurka : mRenderer.source.getImageWidth(); 266104c45677660586026a7e74ef8c47d396403d50eMichael Jurka final int height = swap ? mRenderer.source.getImageWidth() 267104c45677660586026a7e74ef8c47d396403d50eMichael Jurka : mRenderer.source.getImageHeight(); 268104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTempRectF.set(0, 0, width, height); 269104c45677660586026a7e74ef8c47d396403d50eMichael Jurka matrix.mapRect(mTempRectF); 270104c45677660586026a7e74ef8c47d396403d50eMichael Jurka matrix.getValues(mValues); 271104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int cx = width / 2; 272104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int cy = height / 2; 273104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float scale = mValues[Matrix.MSCALE_X]; 274104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int xoffset = Math.round((getWidth() - mTempRectF.width()) / 2 / scale); 275104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int yoffset = Math.round((getHeight() - mTempRectF.height()) / 2 / scale); 276104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (rotation == 90 || rotation == 180) { 277104c45677660586026a7e74ef8c47d396403d50eMichael Jurka cx += (mTempRectF.left / scale) - xoffset; 278104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } else { 279104c45677660586026a7e74ef8c47d396403d50eMichael Jurka cx -= (mTempRectF.left / scale) - xoffset; 280104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 281104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (rotation == 180 || rotation == 270) { 282104c45677660586026a7e74ef8c47d396403d50eMichael Jurka cy += (mTempRectF.top / scale) - yoffset; 283104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } else { 284104c45677660586026a7e74ef8c47d396403d50eMichael Jurka cy -= (mTempRectF.top / scale) - yoffset; 285104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 286104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.scale = scale; 287104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.centerX = swap ? cy : cx; 288104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.centerY = swap ? cx : cy; 289104c45677660586026a7e74ef8c47d396403d50eMichael Jurka invalidate(); 290104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 291104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 292104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 293104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private class TileRenderer implements Renderer { 294104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 295104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private GLES20Canvas mCanvas; 296104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 297104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 298104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void onSurfaceCreated(GL10 gl, EGLConfig config) { 299104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCanvas = new GLES20Canvas(); 300104c45677660586026a7e74ef8c47d396403d50eMichael Jurka BasicTexture.invalidateAllTextures(); 301104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.image.setModel(mRenderer.source, mRenderer.rotation); 302104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 303104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 304104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 305104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void onSurfaceChanged(GL10 gl, int width, int height) { 306104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCanvas.setSize(width, height); 307104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.image.setViewSize(width, height); 308104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 309104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 310104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 311104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void onDrawFrame(GL10 gl) { 312104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCanvas.clearBuffer(); 313104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Runnable readyCallback; 314104c45677660586026a7e74ef8c47d396403d50eMichael Jurka synchronized (mLock) { 315104c45677660586026a7e74ef8c47d396403d50eMichael Jurka readyCallback = mRenderer.isReadyCallback; 316104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.image.setModel(mRenderer.source, mRenderer.rotation); 317104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.image.setPosition(mRenderer.centerX, mRenderer.centerY, 318104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.scale); 319104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 320104c45677660586026a7e74ef8c47d396403d50eMichael Jurka boolean complete = mRenderer.image.draw(mCanvas); 321104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (complete && readyCallback != null) { 322104c45677660586026a7e74ef8c47d396403d50eMichael Jurka synchronized (mLock) { 323104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Make sure we don't trample on a newly set callback/source 324104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // if it changed while we were rendering 325104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (mRenderer.isReadyCallback == readyCallback) { 326104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mRenderer.isReadyCallback = null; 327104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 328104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 329104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (readyCallback != null) { 330104c45677660586026a7e74ef8c47d396403d50eMichael Jurka post(readyCallback); 331104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 332104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 333104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 334104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 335104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 336104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 337104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @SuppressWarnings("unused") 338104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static class ColoredTiles implements TileSource { 339104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int[] COLORS = new int[] { 340104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Color.RED, 341104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Color.BLUE, 342104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Color.YELLOW, 343104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Color.GREEN, 344104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Color.CYAN, 345104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Color.MAGENTA, 346104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Color.WHITE, 347104c45677660586026a7e74ef8c47d396403d50eMichael Jurka }; 348104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 349104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private Paint mPaint = new Paint(); 350104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private Canvas mCanvas = new Canvas(); 351104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 352104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 353104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public int getTileSize() { 354104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return 256; 355104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 356104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 357104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 358104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public int getImageWidth() { 359104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return 16384; 360104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 361104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 362104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 363104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public int getImageHeight() { 364104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return 8192; 365104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 366104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 367104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 368104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public int getRotation() { 369104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return 0; 370104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 371104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 372104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 373104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public Bitmap getTile(int level, int x, int y, Bitmap bitmap) { 374104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int tileSize = getTileSize(); 375104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (bitmap == null) { 376104c45677660586026a7e74ef8c47d396403d50eMichael Jurka bitmap = Bitmap.createBitmap(tileSize, tileSize, 377104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Bitmap.Config.ARGB_8888); 378104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 379104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCanvas.setBitmap(bitmap); 380104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCanvas.drawColor(COLORS[level]); 381104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mPaint.setColor(Color.BLACK); 382104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mPaint.setTextSize(20); 383104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mPaint.setTextAlign(Align.CENTER); 384104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCanvas.drawText(x + "x" + y, 128, 128, mPaint); 385104c45677660586026a7e74ef8c47d396403d50eMichael Jurka tileSize <<= level; 386104c45677660586026a7e74ef8c47d396403d50eMichael Jurka x /= tileSize; 387104c45677660586026a7e74ef8c47d396403d50eMichael Jurka y /= tileSize; 388104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCanvas.drawText(x + "x" + y + " @ " + level, 128, 30, mPaint); 389104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCanvas.setBitmap(null); 390104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return bitmap; 391104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 392104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 393104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 394104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public BasicTexture getPreview() { 395104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return null; 396104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 397104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 398104c45677660586026a7e74ef8c47d396403d50eMichael Jurka} 399