/*
* Copyright (C) 2015 Jorge Ruesga
*
* 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.ruesga.android.wallpapers.photophase;
import android.graphics.RectF;
import android.opengl.GLES20;
import android.util.Log;
import com.ruesga.android.wallpapers.photophase.model.Disposition;
import com.ruesga.android.wallpapers.photophase.textures.TextureManager;
import com.ruesga.android.wallpapers.photophase.textures.TextureRequestor;
import com.ruesga.android.wallpapers.photophase.utils.GLESUtil;
import com.ruesga.android.wallpapers.photophase.utils.GLESUtil.GLColor;
import com.ruesga.android.wallpapers.photophase.utils.GLESUtil.GLESTextureInfo;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
/**
* A GLES square geometry that represents one photo frame for show in the wallpaper.
*/
public class PhotoFrame implements TextureRequestor {
// The default texture coordinates (fit to frame)
private static final float[] DEFAULT_TEXTURE_COORDS = {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f
};
private final Disposition mDisposition;
private final TextureManager mTextureManager;
private final float[] mFrameVertex, mPhotoVertex;
private final float mFrameWidth, mFrameHeight;
private final float mPhotoWidth, mPhotoHeight;
private FloatBuffer mPositionBuffer;
private FloatBuffer mTextureBuffer;
private GLESTextureInfo mTextureInfo;
private final GLColor mBackgroundColor;
private boolean mLoaded;
private final Object mSync = new Object();
/**
* Constructor of <code>PhotoFrame</code>.
*
* @param disposition The associated disposition
* @param textureManager The texture manager
* @param frameVertex A 4 dimension array with the coordinates per vertex plus padding
* @param photoVertex A 4 dimension array with the coordinates per vertex without padding
* @param color Background color
*/
public PhotoFrame(Disposition disposition, TextureManager textureManager, float[] frameVertex,
float[] photoVertex, GLColor color) {
super();
mDisposition = disposition;
mLoaded = false;
mBackgroundColor = color;
mTextureManager = textureManager;
// Save dimensions
mFrameVertex = frameVertex;
mFrameWidth = frameVertex[6] - frameVertex[4];
mFrameHeight = frameVertex[1] - frameVertex[5];
mPhotoVertex = photoVertex;
mPhotoWidth = photoVertex[6] - photoVertex[4];
mPhotoHeight = photoVertex[5] - photoVertex[1];
// Initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(photoVertex.length * 4); // (# of coordinate values * 4 bytes per float)
bb.order(ByteOrder.nativeOrder());
mPositionBuffer = bb.asFloatBuffer();
mPositionBuffer.put(photoVertex);
mPositionBuffer.position(0);
// Load the texture
mTextureInfo = null;
// Request a new image for this frame
requestTexture();
}
public Disposition getDisposition() {
return mDisposition;
}
/**
* {@inheritDoc}
*/
@Override
public RectF getRequestorDimensions() {
return new RectF(0, 0, mPhotoWidth, mPhotoHeight);
}
/**
* {@inheritDoc}
*/
@Override
public void setTextureHandle(GLESTextureInfo ti) {
// If the picture is invalid request a new texture
if (ti == null || ti.handle <= 0) {
requestTexture();
return;
}
// Full frame picture
setTextureHandle(ti, DEFAULT_TEXTURE_COORDS);
mLoaded = true;
}
public void requestTexture() {
mTextureManager.request(this);
}
/**
* Internal method that expose the texture coordinates to set
*
* @param ti The texture info
* @param textureCoords The texture coordinates
*/
private void setTextureHandle(GLESTextureInfo ti, final float[] textureCoords) {
// Recycle the previous handle
if (mTextureInfo != null) {
if (GLES20.glIsTexture(mTextureInfo.handle)) {
int[] textures = new int[]{mTextureInfo.handle};
if (GLESUtil.DEBUG_GL_MEMOBJS) {
Log.d(GLESUtil.DEBUG_GL_MEMOBJS_DEL_TAG, "glDeleteTextures: ["
+ mTextureInfo.handle + "]");
}
GLES20.glDeleteTextures(1, textures, 0);
GLESUtil.glesCheckError("glDeleteTextures");
}
if (mTextureInfo.bitmap != null) {
mTextureInfo.bitmap.recycle();
mTextureInfo.bitmap = null;
}
}
// Initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(textureCoords.length * 4); // (# of coordinate values * 4 bytes per float)
bb.order(ByteOrder.nativeOrder());
synchronized (mSync) {
// Swap buffers
mTextureBuffer = bb.asFloatBuffer();
mTextureBuffer.put(textureCoords);
mTextureBuffer.position(0);
}
mTextureInfo = ti;
}
/**
* Method that returns the frame vertex
*
* @return float[] The frame vertex
*/
public float[] getFrameVertex() {
return mFrameVertex;
}
/**
* Method that returns the frame width
*
* @return float The frame width
*/
public float getFrameWidth() {
return mFrameWidth;
}
/**
* Method that returns the frame height
*
* @return float The frame height
*/
public float getFrameHeight() {
return mFrameHeight;
}
/**
* Method that returns the photo vertex
*
* @return float[] The photo vertex
*/
public float[] getPhotoVertex() {
return mPhotoVertex;
}
/**
* Method that returns the position vertex buffer
*
* @return FloatBuffer The position vertex buffer
*/
public FloatBuffer getPositionBuffer() {
return mPositionBuffer;
}
/**
* Method that returns the texture buffer
*
* @return FloatBuffer The texture buffer
*/
public FloatBuffer getTextureBuffer() {
synchronized (mSync) {
return mTextureBuffer;
}
}
/**
* Method that returns the texture handle
*
* @return int The texture handle
*/
public int getTextureHandle() {
if (mTextureInfo != null) {
return mTextureInfo.handle;
}
return -1;
}
/**
* Method that returns the texture info
*
* @return GLESTextureInfo The texture info
*/
public GLESTextureInfo getTextureInfo() {
return mTextureInfo;
}
/**
* Method that returns the background color of the frame
*
* @return GLColor The background color
*/
public GLColor getBackgroundColor() {
return mBackgroundColor;
}
/**
* Method that returns if the frame is loaded (has its picture loaded)
*
* @return boolean If the frame is loaded (has its picture loaded)
*/
public boolean isLoaded() {
return mLoaded;
}
/**
* Request a recycle of the references of the object
*/
public void recycle() {
if (mTextureInfo != null && mTextureInfo.handle != 0) {
int[] textures = new int[]{mTextureInfo.handle};
if (GLESUtil.DEBUG_GL_MEMOBJS) {
Log.d(GLESUtil.DEBUG_GL_MEMOBJS_DEL_TAG, "glDeleteTextures: ["
+ mTextureInfo.handle + "]");
}
GLES20.glDeleteTextures(1, textures, 0);
GLESUtil.glesCheckError("glDeleteTextures");
}
if (mTextureInfo != null && mTextureInfo.bitmap != null
&& !mTextureInfo.bitmap.isRecycled()) {
mTextureInfo.bitmap.recycle();
}
mTextureInfo = null;
if (mPositionBuffer != null) {
mPositionBuffer.clear();
}
if (mTextureBuffer != null) {
mTextureBuffer.clear();
}
mPositionBuffer = null;
mTextureBuffer = null;
}
}