blob: 6d5cce73186a6d696e69099d4ea1e28bb0d19f09 [file] [log] [blame]
/*
* Copyright (C) 2009 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.wallpaper.nexus;
import static android.renderscript.Element.RGBA_8888;
import static android.renderscript.Element.RGB_565;
import static android.renderscript.ProgramStore.DepthFunc.ALWAYS;
import static android.renderscript.Sampler.Value.LINEAR;
import static android.renderscript.Sampler.Value.CLAMP;
import static android.renderscript.Sampler.Value.WRAP;
import com.android.wallpaper.R;
import com.android.wallpaper.RenderScriptScene;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.os.Bundle;
import android.renderscript.Allocation;
import android.renderscript.ProgramFragment;
import android.renderscript.ProgramStore;
import android.renderscript.ProgramVertex;
import android.renderscript.Sampler;
import android.renderscript.Script;
import android.renderscript.ScriptC;
import android.renderscript.Type;
import android.renderscript.ProgramStore.BlendDstFunc;
import android.renderscript.ProgramStore.BlendSrcFunc;
import android.view.SurfaceHolder;
import java.util.TimeZone;
class NexusRS extends RenderScriptScene {
private static final int RSID_STATE = 0;
private static final int RSID_COMMAND = 1;
private static final int TEXTURES_COUNT = 3;
private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
private ProgramFragment mPfTexture;
private ProgramFragment mPfTexture565;
private ProgramFragment mPfColor;
private ProgramStore mPsSolid;
private ProgramStore mPsBlend;
private ProgramVertex mPvOrtho;
private ProgramVertex.MatrixAllocation mPvOrthoAlloc;
private Sampler mClampSampler;
private Sampler mWrapSampler;
private Allocation mState;
private Type mStateType;
private WorldState mWorldState;
private Allocation mCommandAllocation;
private Type mCommandType;
private CommandState mCommand;
private Allocation[] mTextures = new Allocation[TEXTURES_COUNT];
public NexusRS(int width, int height) {
super(width, height);
mOptionsARGB.inScaled = false;
mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
}
@Override
public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
mWorldState.xOffset = xOffset;
mState.data(mWorldState);
}
@Override
public void start() {
super.start();
}
@Override
public void resize(int width, int height) {
super.resize(width, height);
mWorldState.width = width;
mWorldState.height = height;
mWorldState.rotate = width > height ? 1 : 0;
mState.data(mWorldState);
mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
}
@Override
protected ScriptC createScript() {
createProgramVertex();
createProgramFragmentStore();
createProgramFragment();
createState();
loadTextures();
ScriptC.Builder sb = new ScriptC.Builder(mRS);
sb.setType(mStateType, "State", RSID_STATE);
sb.setType(mCommandType, "Command", RSID_COMMAND);
sb.setScript(mResources, R.raw.nexus);
Script.Invokable invokable = sb.addInvokable("initPulses");
sb.setRoot(true);
ScriptC script = sb.create();
script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
script.setTimeZone(TimeZone.getDefault().getID());
script.bindAllocation(mState, RSID_STATE);
script.bindAllocation(mCommandAllocation, RSID_COMMAND);
invokable.execute();
return script;
}
static class WorldState {
public int width;
public int height;
public float glWidth;
public float glHeight;
public int rotate;
public int isPreview;
public float xOffset;
public int mode;
}
static class CommandState {
public int x;
public int y;
public int command;
}
private void createState() {
mWorldState = new WorldState();
mWorldState.width = mWidth;
mWorldState.height = mHeight;
mWorldState.rotate = mWidth > mHeight ? 1 : 0;
mWorldState.isPreview = isPreview() ? 1 : 0;
try {
mWorldState.mode = mResources.getInteger(R.integer.nexus_mode);
} catch (Resources.NotFoundException exc) {
mWorldState.mode = 0; // standard nexus mode
}
mStateType = Type.createFromClass(mRS, WorldState.class, 1, "WorldState");
mState = Allocation.createTyped(mRS, mStateType);
mState.data(mWorldState);
mCommand = new CommandState();
mCommand.x = -1;
mCommand.y = -1;
mCommand.command = 0;
mCommandType = Type.createFromClass(mRS, CommandState.class, 1, "DropState");
mCommandAllocation = Allocation.createTyped(mRS, mCommandType);
mCommandAllocation.data(mCommand);
}
private void loadTextures() {
mTextures[0] = loadTexture(R.drawable.pyramid_background, "TBackground");
mTextures[1] = loadTextureARGB(R.drawable.pulse, "TPulse");
mTextures[2] = loadTextureARGB(R.drawable.glow, "TGlow");
final int count = mTextures.length;
for (int i = 0; i < count; i++) {
mTextures[i].uploadToTexture(0);
}
}
private Allocation loadTexture(int id, String name) {
final Allocation allocation = Allocation.createFromBitmapResource(mRS, mResources,
id, RGB_565(mRS), false);
allocation.setName(name);
return allocation;
}
private Allocation loadTextureARGB(int id, String name) {
Bitmap b = BitmapFactory.decodeResource(mResources, id, mOptionsARGB);
final Allocation allocation = Allocation.createFromBitmap(mRS, b, RGBA_8888(mRS), false);
allocation.setName(name);
return allocation;
}
private void createProgramFragment() {
// sampler and program fragment for pulses
Sampler.Builder sampleBuilder = new Sampler.Builder(mRS);
sampleBuilder.setMin(LINEAR);
sampleBuilder.setMag(LINEAR);
sampleBuilder.setWrapS(WRAP);
sampleBuilder.setWrapT(WRAP);
mWrapSampler = sampleBuilder.create();
ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS);
builder.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
ProgramFragment.Builder.Format.RGBA, 0);
mPfTexture = builder.create();
mPfTexture.setName("PFTexture");
mPfTexture.bindSampler(mWrapSampler, 0);
builder = new ProgramFragment.Builder(mRS);
builder.setTexture(ProgramFragment.Builder.EnvMode.REPLACE,
ProgramFragment.Builder.Format.RGB, 0);
mPfColor = builder.create();
mPfColor.setName("PFColor");
mPfColor.bindSampler(mWrapSampler, 0);
// sampler and program fragment for background image
sampleBuilder.setWrapS(CLAMP);
sampleBuilder.setWrapT(CLAMP);
mClampSampler = sampleBuilder.create();
builder = new ProgramFragment.Builder(mRS);
builder.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
ProgramFragment.Builder.Format.RGB, 0);
mPfTexture565 = builder.create();
mPfTexture565.setName("PFTexture565");
mPfTexture565.bindSampler(mClampSampler, 0);
}
private void createProgramFragmentStore() {
ProgramStore.Builder builder = new ProgramStore.Builder(mRS, null, null);
builder.setDepthFunc(ALWAYS);
builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
builder.setDitherEnable(false);
builder.setDepthMask(true);
mPsSolid = builder.create();
mPsSolid.setName("PSSolid");
builder = new ProgramStore.Builder(mRS, null, null);
builder.setDepthFunc(ALWAYS);
// builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE);
builder.setDitherEnable(false);
builder.setDepthMask(true);
mPsBlend = builder.create();
mPsBlend.setName("PSBlend");
}
private void createProgramVertex() {
mPvOrthoAlloc = new ProgramVertex.MatrixAllocation(mRS);
mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
pvb.setTextureMatrixEnable(true);
mPvOrtho = pvb.create();
mPvOrtho.bindAllocation(mPvOrthoAlloc);
mPvOrtho.setName("PVOrtho");
}
@Override
public Bundle onCommand(String action, int x, int y, int z, Bundle extras,
boolean resultRequested) {
final int dw = mWorldState.width;
final int bw = 960;
x = (int) (x + mWorldState.xOffset * (bw-dw));
if ("android.wallpaper.tap".equals(action)) {
sendCommand(1, x, y);
} else if ("android.home.drop".equals(action)) {
sendCommand(2, x, y);
}
return null;
}
private void sendCommand(int command, int x, int y) {
mCommand.x = x;
mCommand.y = y;
mCommand.command = command;
mCommandAllocation.data(mCommand);
}
}