diff options
Diffstat (limited to 'src/com/android/gallery3d/glrenderer/TiledTexture.java')
-rw-r--r-- | src/com/android/gallery3d/glrenderer/TiledTexture.java | 349 |
1 files changed, 0 insertions, 349 deletions
diff --git a/src/com/android/gallery3d/glrenderer/TiledTexture.java b/src/com/android/gallery3d/glrenderer/TiledTexture.java deleted file mode 100644 index 6ca1de088..000000000 --- a/src/com/android/gallery3d/glrenderer/TiledTexture.java +++ /dev/null @@ -1,349 +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.glrenderer; - -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffXfermode; -import android.graphics.RectF; -import android.os.SystemClock; - -import com.android.gallery3d.ui.GLRoot; -import com.android.gallery3d.ui.GLRoot.OnGLIdleListener; - -import java.util.ArrayDeque; -import java.util.ArrayList; - -// This class is similar to BitmapTexture, except the bitmap is -// split into tiles. By doing so, we may increase the time required to -// upload the whole bitmap but we reduce the time of uploading each tile -// so it make the animation more smooth and prevents jank. -public class TiledTexture implements Texture { - private static final int CONTENT_SIZE = 254; - private static final int BORDER_SIZE = 1; - private static final int TILE_SIZE = CONTENT_SIZE + 2 * BORDER_SIZE; - private static final int INIT_CAPACITY = 8; - - // We are targeting at 60fps, so we have 16ms for each frame. - // In this 16ms, we use about 4~8 ms to upload tiles. - private static final long UPLOAD_TILE_LIMIT = 4; // ms - - private static Tile sFreeTileHead = null; - private static final Object sFreeTileLock = new Object(); - - private static Bitmap sUploadBitmap; - private static Canvas sCanvas; - private static Paint sBitmapPaint; - private static Paint sPaint; - - private int mUploadIndex = 0; - - private final Tile[] mTiles; // Can be modified in different threads. - // Should be protected by "synchronized." - private final int mWidth; - private final int mHeight; - private final RectF mSrcRect = new RectF(); - private final RectF mDestRect = new RectF(); - - public static class Uploader implements OnGLIdleListener { - private final ArrayDeque<TiledTexture> mTextures = - new ArrayDeque<TiledTexture>(INIT_CAPACITY); - - private final GLRoot mGlRoot; - private boolean mIsQueued = false; - - public Uploader(GLRoot glRoot) { - mGlRoot = glRoot; - } - - public synchronized void clear() { - mTextures.clear(); - } - - public synchronized void addTexture(TiledTexture t) { - if (t.isReady()) return; - mTextures.addLast(t); - - if (mIsQueued) return; - mIsQueued = true; - mGlRoot.addOnGLIdleListener(this); - } - - @Override - public boolean onGLIdle(GLCanvas canvas, boolean renderRequested) { - ArrayDeque<TiledTexture> deque = mTextures; - synchronized (this) { - long now = SystemClock.uptimeMillis(); - long dueTime = now + UPLOAD_TILE_LIMIT; - while (now < dueTime && !deque.isEmpty()) { - TiledTexture t = deque.peekFirst(); - if (t.uploadNextTile(canvas)) { - deque.removeFirst(); - mGlRoot.requestRender(); - } - now = SystemClock.uptimeMillis(); - } - mIsQueued = !mTextures.isEmpty(); - - // return true to keep this listener in the queue - return mIsQueued; - } - } - } - - private static class Tile extends UploadedTexture { - public int offsetX; - public int offsetY; - public Bitmap bitmap; - public Tile nextFreeTile; - public int contentWidth; - public int contentHeight; - - @Override - public void setSize(int width, int height) { - contentWidth = width; - contentHeight = height; - mWidth = width + 2 * BORDER_SIZE; - mHeight = height + 2 * BORDER_SIZE; - mTextureWidth = TILE_SIZE; - mTextureHeight = TILE_SIZE; - } - - @Override - protected Bitmap onGetBitmap() { - int x = BORDER_SIZE - offsetX; - int y = BORDER_SIZE - offsetY; - int r = bitmap.getWidth() + x; - int b = bitmap.getHeight() + y; - sCanvas.drawBitmap(bitmap, x, y, sBitmapPaint); - bitmap = null; - - // draw borders if need - if (x > 0) sCanvas.drawLine(x - 1, 0, x - 1, TILE_SIZE, sPaint); - if (y > 0) sCanvas.drawLine(0, y - 1, TILE_SIZE, y - 1, sPaint); - if (r < CONTENT_SIZE) sCanvas.drawLine(r, 0, r, TILE_SIZE, sPaint); - if (b < CONTENT_SIZE) sCanvas.drawLine(0, b, TILE_SIZE, b, sPaint); - - return sUploadBitmap; - } - - @Override - protected void onFreeBitmap(Bitmap bitmap) { - // do nothing - } - } - - private static void freeTile(Tile tile) { - tile.invalidateContent(); - tile.bitmap = null; - synchronized (sFreeTileLock) { - tile.nextFreeTile = sFreeTileHead; - sFreeTileHead = tile; - } - } - - private static Tile obtainTile() { - synchronized (sFreeTileLock) { - Tile result = sFreeTileHead; - if (result == null) return new Tile(); - sFreeTileHead = result.nextFreeTile; - result.nextFreeTile = null; - return result; - } - } - - private boolean uploadNextTile(GLCanvas canvas) { - if (mUploadIndex == mTiles.length) return true; - - synchronized (mTiles) { - Tile next = mTiles[mUploadIndex++]; - - // Make sure tile has not already been recycled by the time - // this is called (race condition in onGLIdle) - if (next.bitmap != null) { - boolean hasBeenLoad = next.isLoaded(); - next.updateContent(canvas); - - // It will take some time for a texture to be drawn for the first - // time. When scrolling, we need to draw several tiles on the screen - // at the same time. It may cause a UI jank even these textures has - // been uploaded. - if (!hasBeenLoad) next.draw(canvas, 0, 0); - } - } - return mUploadIndex == mTiles.length; - } - - public TiledTexture(Bitmap bitmap) { - mWidth = bitmap.getWidth(); - mHeight = bitmap.getHeight(); - ArrayList<Tile> list = new ArrayList<Tile>(); - - for (int x = 0, w = mWidth; x < w; x += CONTENT_SIZE) { - for (int y = 0, h = mHeight; y < h; y += CONTENT_SIZE) { - Tile tile = obtainTile(); - tile.offsetX = x; - tile.offsetY = y; - tile.bitmap = bitmap; - tile.setSize( - Math.min(CONTENT_SIZE, mWidth - x), - Math.min(CONTENT_SIZE, mHeight - y)); - list.add(tile); - } - } - mTiles = list.toArray(new Tile[list.size()]); - } - - public boolean isReady() { - return mUploadIndex == mTiles.length; - } - - // Can be called in UI thread. - public void recycle() { - synchronized (mTiles) { - for (int i = 0, n = mTiles.length; i < n; ++i) { - freeTile(mTiles[i]); - } - } - } - - public static void freeResources() { - sUploadBitmap = null; - sCanvas = null; - sBitmapPaint = null; - sPaint = null; - } - - public static void prepareResources() { - sUploadBitmap = Bitmap.createBitmap(TILE_SIZE, TILE_SIZE, Config.ARGB_8888); - sCanvas = new Canvas(sUploadBitmap); - sBitmapPaint = new Paint(Paint.FILTER_BITMAP_FLAG); - sBitmapPaint.setXfermode(new PorterDuffXfermode(Mode.SRC)); - sPaint = new Paint(); - sPaint.setXfermode(new PorterDuffXfermode(Mode.SRC)); - sPaint.setColor(Color.TRANSPARENT); - } - - // We want to draw the "source" on the "target". - // This method is to find the "output" rectangle which is - // the corresponding area of the "src". - // (x,y) target - // (x0,y0) source +---------------+ - // +----------+ | | - // | src | | output | - // | +--+ | linear map | +----+ | - // | +--+ | ----------> | | | | - // | | by (scaleX, scaleY) | +----+ | - // +----------+ | | - // Texture +---------------+ - // Canvas - private static void mapRect(RectF output, - RectF src, float x0, float y0, float x, float y, float scaleX, - float scaleY) { - output.set(x + (src.left - x0) * scaleX, - y + (src.top - y0) * scaleY, - x + (src.right - x0) * scaleX, - y + (src.bottom - y0) * scaleY); - } - - // Draws a mixed color of this texture and a specified color onto the - // a rectangle. The used color is: from * (1 - ratio) + to * ratio. - public void drawMixed(GLCanvas canvas, int color, float ratio, - int x, int y, int width, int height) { - RectF src = mSrcRect; - RectF dest = mDestRect; - float scaleX = (float) width / mWidth; - float scaleY = (float) height / mHeight; - synchronized (mTiles) { - for (int i = 0, n = mTiles.length; i < n; ++i) { - Tile t = mTiles[i]; - src.set(0, 0, t.contentWidth, t.contentHeight); - src.offset(t.offsetX, t.offsetY); - mapRect(dest, src, 0, 0, x, y, scaleX, scaleY); - src.offset(BORDER_SIZE - t.offsetX, BORDER_SIZE - t.offsetY); - canvas.drawMixed(t, color, ratio, mSrcRect, mDestRect); - } - } - } - - // Draws the texture on to the specified rectangle. - @Override - public void draw(GLCanvas canvas, int x, int y, int width, int height) { - RectF src = mSrcRect; - RectF dest = mDestRect; - float scaleX = (float) width / mWidth; - float scaleY = (float) height / mHeight; - synchronized (mTiles) { - for (int i = 0, n = mTiles.length; i < n; ++i) { - Tile t = mTiles[i]; - src.set(0, 0, t.contentWidth, t.contentHeight); - src.offset(t.offsetX, t.offsetY); - mapRect(dest, src, 0, 0, x, y, scaleX, scaleY); - src.offset(BORDER_SIZE - t.offsetX, BORDER_SIZE - t.offsetY); - canvas.drawTexture(t, mSrcRect, mDestRect); - } - } - } - - // Draws a sub region of this texture on to the specified rectangle. - public void draw(GLCanvas canvas, RectF source, RectF target) { - RectF src = mSrcRect; - RectF dest = mDestRect; - float x0 = source.left; - float y0 = source.top; - float x = target.left; - float y = target.top; - float scaleX = target.width() / source.width(); - float scaleY = target.height() / source.height(); - - synchronized (mTiles) { - for (int i = 0, n = mTiles.length; i < n; ++i) { - Tile t = mTiles[i]; - src.set(0, 0, t.contentWidth, t.contentHeight); - src.offset(t.offsetX, t.offsetY); - if (!src.intersect(source)) continue; - mapRect(dest, src, x0, y0, x, y, scaleX, scaleY); - src.offset(BORDER_SIZE - t.offsetX, BORDER_SIZE - t.offsetY); - canvas.drawTexture(t, src, dest); - } - } - } - - @Override - public int getWidth() { - return mWidth; - } - - @Override - public int getHeight() { - return mHeight; - } - - @Override - public void draw(GLCanvas canvas, int x, int y) { - draw(canvas, x, y, mWidth, mHeight); - } - - @Override - public boolean isOpaque() { - return false; - } -} |