diff options
-rw-r--r-- | AndroidManifest.xml | 10 | ||||
-rw-r--r-- | res/drawable-hdpi/night.jpg | bin | 0 -> 80167 bytes | |||
-rw-r--r-- | res/drawable-hdpi/sky.jpg | bin | 0 -> 27766 bytes | |||
-rw-r--r-- | res/drawable-hdpi/sunrise.jpg | bin | 0 -> 30351 bytes | |||
-rw-r--r-- | res/drawable-hdpi/sunset.jpg | bin | 0 -> 33914 bytes | |||
-rw-r--r-- | res/raw/grass.c | 212 | ||||
-rw-r--r-- | res/values/strings.xml | 6 | ||||
-rw-r--r-- | src/com/android/launcher2/Workspace.java | 2 | ||||
-rw-r--r-- | src/com/android/wallpaper/grass/GrassRS.java | 262 | ||||
-rw-r--r-- | src/com/android/wallpaper/grass/GrassWallpaper.java | 73 |
10 files changed, 564 insertions, 1 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index cdfe585ab..36f6e42b6 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -118,6 +118,16 @@ </intent-filter> </receiver> + <!-- TODO: Localize label --> + <service + android:label="@string/wallpaper_grass" + android:name="com.android.wallpaper.grass.GrassWallpaper" + android:permission="android.permission.BIND_WALLPAPER"> + <intent-filter> + <action android:name="android.service.wallpaper.WallpaperService" /> + </intent-filter> + </service> + <!-- The settings provider contains Home's data, like the workspace favorites --> <provider android:name="LauncherProvider" diff --git a/res/drawable-hdpi/night.jpg b/res/drawable-hdpi/night.jpg Binary files differnew file mode 100644 index 000000000..559c7cb2d --- /dev/null +++ b/res/drawable-hdpi/night.jpg diff --git a/res/drawable-hdpi/sky.jpg b/res/drawable-hdpi/sky.jpg Binary files differnew file mode 100644 index 000000000..a12fe201c --- /dev/null +++ b/res/drawable-hdpi/sky.jpg diff --git a/res/drawable-hdpi/sunrise.jpg b/res/drawable-hdpi/sunrise.jpg Binary files differnew file mode 100644 index 000000000..db016b262 --- /dev/null +++ b/res/drawable-hdpi/sunrise.jpg diff --git a/res/drawable-hdpi/sunset.jpg b/res/drawable-hdpi/sunset.jpg Binary files differnew file mode 100644 index 000000000..49bb0c631 --- /dev/null +++ b/res/drawable-hdpi/sunset.jpg diff --git a/res/raw/grass.c b/res/raw/grass.c new file mode 100644 index 000000000..2962d0f97 --- /dev/null +++ b/res/raw/grass.c @@ -0,0 +1,212 @@ +// 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. + +#pragma version(1) +#pragma stateVertex(PVBackground) +#pragma stateFragment(PFBackground) +#pragma stateFragmentStore(PFSBackground) + +#define RSID_STATE 0 +#define RSID_FRAME_COUNT 0 +#define RSID_BLADES_COUNT 1 +#define RSID_WIDTH 2 +#define RSID_HEIGHT 3 + +#define RSID_BLADES 1 +#define BLADE_STRUCT_FIELDS_COUNT 12 +#define BLADE_STRUCT_ANGLE 0 +#define BLADE_STRUCT_SIZE 1 +#define BLADE_STRUCT_XPOS 2 +#define BLADE_STRUCT_YPOS 3 +#define BLADE_STRUCT_OFFSET 4 +#define BLADE_STRUCT_SCALE 5 +#define BLADE_STRUCT_LENGTHX 6 +#define BLADE_STRUCT_LENGTHY 7 +#define BLADE_STRUCT_HARDNESS 8 +#define BLADE_STRUCT_H 9 +#define BLADE_STRUCT_S 10 +#define BLADE_STRUCT_B 11 + +#define TESSELATION 2.0f + +#define MAX_BEND 0.09f + +#define MIDNIGHT 0.0f +#define MORNING 0.375f +#define AFTERNOON 0.6f +#define DUSK 0.8f + +#define SECONDS_IN_DAY 24.0f * 3600.0f + +#define PI 3.1415926f + +#define REAL_TIME 0 + +float time(int frameCount) { + if (REAL_TIME) { + return (hour() * 3600.0f + minute() * 60.0f + second()) / SECONDS_IN_DAY; + } + return (frameCount % 180) / 180.0f; +} + +void alpha(float a) { + color(1.0f, 1.0f, 1.0f, a); +} + +void drawNight(int width, int height) { + bindProgramFragment(NAMED_PFNight); + bindTexture(NAMED_PFNight, 0, NAMED_TNight); + drawQuadTexCoords( + 0.0f, -32.0f, 0.0f, + 0.0f, 1.0f, + width, -32.0f, 0.0f, + 2.0f, 1.0f, + width, 1024.0f - 32.0f, 0.0f, + 2.0f, 0.0f, + 0.0f, 1024.0f - 32.0f, 0.0f, + 0.0f, 0.0f); + bindProgramFragment(NAMED_PFBackground); +} + +void drawSunrise(int width, int height) { + bindTexture(NAMED_PFBackground, 0, NAMED_TSunrise); + drawRect(0.0f, 0.0f, width, height, 0.0f); +} + +void drawNoon(int width, int height) { + bindTexture(NAMED_PFBackground, 0, NAMED_TSky); + drawRect(0.0f, 0.0f, width, height, 0.0f); +} + +void drawSunset(int width, int height) { + bindTexture(NAMED_PFBackground, 0, NAMED_TSunset); + drawRect(0.0f, 0.0f, width, height, 0.0f); +} + +void drawBlade(int index, float now, int frameCount) { + float *bladeStruct = loadArrayF(RSID_BLADES, index); + float offset = bladeStruct[BLADE_STRUCT_OFFSET]; + float scale = bladeStruct[BLADE_STRUCT_SCALE]; + float angle = bladeStruct[BLADE_STRUCT_ANGLE]; + float hardness = bladeStruct[BLADE_STRUCT_HARDNESS]; + + float xpos = bladeStruct[BLADE_STRUCT_XPOS]; + float ypos = bladeStruct[BLADE_STRUCT_YPOS]; + + float lengthX = bladeStruct[BLADE_STRUCT_LENGTHX]; + float lengthY = bladeStruct[BLADE_STRUCT_LENGTHY]; + + int size = bladeStruct[BLADE_STRUCT_SIZE]; + + float h = bladeStruct[BLADE_STRUCT_H]; + float s = bladeStruct[BLADE_STRUCT_S]; + float b = bladeStruct[BLADE_STRUCT_B]; + + float newB = 1.0f; + if (now >= MIDNIGHT && now < MORNING) { + newB = now / MORNING; + } + + if (now >= AFTERNOON && now < DUSK) { + newB = 1.0f - normf(AFTERNOON, DUSK, now); + } + + if (now >= DUSK) { + newB = 0.0f; + } + + hsb(h, s, lerpf(0, b, newB), 1.0f); + + float newAngle = turbulencef2(xpos * 0.006f, frameCount * 0.006f, 4.0f) - 0.5f; + newAngle /= 2.0f; + angle = clampf(angle + (newAngle + offset - angle) * 0.15f, -MAX_BEND, MAX_BEND); + + float currentAngle = PI / 2.0f; + + float bottomX = xpos; + float bottomY = ypos; + + int i = size * TESSELATION; + float lx = lengthX / TESSELATION; + float ly = lengthY / TESSELATION; + float ss = 4.0f / i + scale / TESSELATION; + float sh = 0.5f / TESSELATION; + float d = angle * hardness / TESSELATION; + + for ( ; i > 0; i--) { + float topX = bottomX - cosf(currentAngle) * size * lx; + float topY = bottomY - sinf(currentAngle) * size * ly; + currentAngle += d; + + float spi = (i - 1) * ss; + float si = i * ss; + + drawQuad(topX + spi, topY, 0.0f, + topX - spi, topY, 0.0f, + bottomX - si, bottomY + sh, 0.0f, + bottomX + si, bottomY + sh, 0.0f); + + bottomX = topX; + bottomY = topY; + } + + storeF(RSID_BLADES, index + BLADE_STRUCT_ANGLE, angle); +} + +void drawBlades(float now, int frameCount) { + // For anti-aliasing + bindTexture(NAMED_PFBackground, 0, NAMED_TAa); + + int bladesCount = loadI32(RSID_STATE, RSID_BLADES_COUNT); + int count = bladesCount * BLADE_STRUCT_FIELDS_COUNT; + + int i = 0; + for ( ; i < count; i += BLADE_STRUCT_FIELDS_COUNT) { + drawBlade(i, now, frameCount); + } +} + +int main(int launchID) { + int width = loadI32(RSID_STATE, RSID_WIDTH); + int height = loadI32(RSID_STATE, RSID_HEIGHT); + + int frameCount = loadI32(RSID_STATE, RSID_FRAME_COUNT); + float now = time(frameCount); + alpha(1.0f); + + if (now >= MIDNIGHT && now < MORNING) { + drawNight(width, height); + alpha(normf(MIDNIGHT, MORNING, now)); + drawSunrise(width, height); + } else if (now >= MORNING && now < AFTERNOON) { + drawSunrise(width, height); + alpha(normf(MORNING, AFTERNOON, now)); + drawNoon(width, height); + } else if (now >= AFTERNOON && now < DUSK) { + drawNoon(width, height); + alpha(normf(AFTERNOON, DUSK, now)); + drawSunset(width, height); + } else if (now >= DUSK) { + drawNight(width, height); + alpha(1.0f - normf(DUSK, 1.0f, now)); + drawSunset(width, height); + } + + drawBlades(now, frameCount); + + frameCount++; + storeI32(RSID_STATE, RSID_FRAME_COUNT, frameCount); + + return 1; +} diff --git a/res/values/strings.xml b/res/values/strings.xml index f286fa11e..b792d36a6 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -126,4 +126,10 @@ <!-- Text to show user in place of a gadget when we can't display it properly --> <string name="gadget_error_text">Problem loading widget</string> + + <!-- Wallpapers: --> + <skip /> + + <!-- Wallpaper showing grass and the sky --> + <string name="wallpaper_grass">Grass</string> </resources> diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java index c9604121f..9df5df0ef 100644 --- a/src/com/android/launcher2/Workspace.java +++ b/src/com/android/launcher2/Workspace.java @@ -461,7 +461,7 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag } private void updateWallpaperOffset(int scrollRange) { - mWallpaperManager.setWallpaperOffsets(getWindowToken(), mScrollX / (float) scrollRange, 0); + mWallpaperManager.setWallpaperOffsets(getWindowToken(), mScrollX / (float) scrollRange, -30); } @Override diff --git a/src/com/android/wallpaper/grass/GrassRS.java b/src/com/android/wallpaper/grass/GrassRS.java new file mode 100644 index 000000000..722685b14 --- /dev/null +++ b/src/com/android/wallpaper/grass/GrassRS.java @@ -0,0 +1,262 @@ +/* + * 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.grass; + +import android.content.res.Resources; +import android.renderscript.Sampler; +import static android.renderscript.ProgramFragment.EnvMode.*; +import static android.renderscript.ProgramStore.DepthFunc.*; +import static android.renderscript.ProgramStore.BlendSrcFunc; +import static android.renderscript.ProgramStore.BlendDstFunc; +import android.renderscript.RenderScript; +import android.renderscript.ProgramFragment; +import android.renderscript.ProgramStore; +import android.renderscript.Allocation; +import android.renderscript.ProgramVertex; +import static android.renderscript.Element.*; +import static android.util.MathUtils.*; +import android.renderscript.ScriptC; +import android.renderscript.Type; +import android.renderscript.Dimension; +import static android.renderscript.Sampler.Value.*; +import com.android.launcher2.R; + +import java.util.TimeZone; + +class GrassRS { + private static final int RSID_STATE = 0; + private static final int RSID_STATE_FRAMECOUNT = 0; + private static final int RSID_STATE_BLADES_COUNT = 1; + private static final int RSID_STATE_WIDTH = 2; + private static final int RSID_STATE_HEIGHT = 3; + + private static final int TEXTURES_COUNT = 5; + + private static final int RSID_BLADES = 1; + private static final int BLADES_COUNT = 200; + private static final int BLADE_STRUCT_FIELDS_COUNT = 12; + private static final int BLADE_STRUCT_ANGLE = 0; + private static final int BLADE_STRUCT_SIZE = 1; + private static final int BLADE_STRUCT_XPOS = 2; + private static final int BLADE_STRUCT_YPOS = 3; + private static final int BLADE_STRUCT_OFFSET = 4; + private static final int BLADE_STRUCT_SCALE = 5; + private static final int BLADE_STRUCT_LENGTHX = 6; + private static final int BLADE_STRUCT_LENGTHY = 7; + private static final int BLADE_STRUCT_HARDNESS = 8; + private static final int BLADE_STRUCT_H = 9; + private static final int BLADE_STRUCT_S = 10; + private static final int BLADE_STRUCT_B = 11; + + private Resources mResources; + private RenderScript mRS; + + private final int mWidth; + private final int mHeight; + + private ScriptC mScript; + private Sampler mSampler; + private Sampler mNightSampler; + private ProgramFragment mPfBackground; + private ProgramFragment mPfNight; + private ProgramStore mPfsBackground; + private ProgramVertex mPvBackground; + private ProgramVertex.MatrixAllocation mPvOrthoAlloc; + + private Allocation[] mTextures; + + private Allocation mState; + private Allocation mBlades; + + public GrassRS(int width, int height) { + mWidth = width; + mHeight = height; + } + + public void init(RenderScript rs, Resources res) { + mRS = rs; + mResources = res; + initRS(); + } + + public void destroy() { + mScript.destroy(); + mSampler.destroy(); + mPfBackground.destroy(); + mPfsBackground.destroy(); + mPvBackground.destroy(); + mPvOrthoAlloc.mAlloc.destroy(); + for (Allocation a : mTextures) { + a.destroy(); + } + mState.destroy(); + mBlades.destroy(); + mNightSampler.destroy(); + mPfNight.destroy(); + } + + @Override + protected void finalize() throws Throwable { + try { + destroy(); + } finally { + super.finalize(); + } + } + + private void initRS() { + createProgramVertex(); + createProgramFragmentStore(); + createProgramFragment(); + createScriptStructures(); + loadTextures(); + + ScriptC.Builder sb = new ScriptC.Builder(mRS); + sb.setScript(mResources, R.raw.grass); + sb.setRoot(true); + mScript = sb.create(); + mScript.setClearColor(0.0f, 0.0f, 0.0f, 1.0f); + mScript.setTimeZone(TimeZone.getDefault().getID()); + + mScript.bindAllocation(mState, RSID_STATE); + mScript.bindAllocation(mBlades, RSID_BLADES); + + mRS.contextBindRootScript(mScript); + } + + private void createScriptStructures() { + final int[] data = new int[4]; + mState = Allocation.createSized(mRS, USER_I32, data.length); + data[RSID_STATE_FRAMECOUNT] = 0; + data[RSID_STATE_BLADES_COUNT] = BLADES_COUNT; + data[RSID_STATE_WIDTH] = mWidth; + data[RSID_STATE_HEIGHT] = mHeight; + mState.data(data); + + final float[] blades = new float[BLADES_COUNT * BLADE_STRUCT_FIELDS_COUNT]; + mBlades = Allocation.createSized(mRS, USER_FLOAT, blades.length); + for (int i = 0; i < blades.length; i+= BLADE_STRUCT_FIELDS_COUNT) { + createBlade(blades, i); + } + mBlades.data(blades); + } + + private void createBlade(float[] blades, int index) { + //noinspection PointlessArithmeticExpression + blades[index + BLADE_STRUCT_ANGLE] = 0.0f; + blades[index + BLADE_STRUCT_SIZE] = random(4.0f) + 4.0f; + blades[index + BLADE_STRUCT_XPOS] = random(mWidth); + blades[index + BLADE_STRUCT_YPOS] = mHeight; + blades[index + BLADE_STRUCT_OFFSET] = random(0.2f) - 0.1f; + blades[index + BLADE_STRUCT_SCALE] = random(0.6f) + 0.2f; + blades[index + BLADE_STRUCT_LENGTHX] = random(4.5f) + 3.0f; + blades[index + BLADE_STRUCT_LENGTHY] = random(5.5f) + 2.0f; + blades[index + BLADE_STRUCT_HARDNESS] = random(1.0f) + 0.2f; + blades[index + BLADE_STRUCT_H] = random(0.02f) + 0.2f; + blades[index + BLADE_STRUCT_S] = random(0.22f) + 0.78f; + blades[index + BLADE_STRUCT_B] = random(0.65f) + 0.35f; + } + + private void loadTextures() { + mTextures = new Allocation[TEXTURES_COUNT]; + + final Allocation[] textures = mTextures; + textures[0] = loadTexture(R.drawable.night, "TNight"); + textures[1] = loadTexture(R.drawable.sunrise, "TSunrise"); + textures[2] = loadTexture(R.drawable.sky, "TSky"); + textures[3] = loadTexture(R.drawable.sunset, "TSunset"); + textures[4] = generateTextureAlpha(4, 1, new int[] { 0x00FFFF00 }, "TAa"); + + final int count = textures.length; + for (int i = 0; i < count; i++) { + final Allocation texture = textures[i]; + texture.uploadToTexture(0); + } + } + + private Allocation generateTextureAlpha(int width, int height, int[] data, String name) { + final Type.Builder builder = new Type.Builder(mRS, A_8); + builder.add(Dimension.X, width); + builder.add(Dimension.Y, height); + + final Allocation allocation = Allocation.createTyped(mRS, builder.create()); + allocation.data(data); + allocation.setName(name); + return allocation; + } + + private Allocation loadTexture(int id, String name) { + final Allocation allocation = Allocation.createFromBitmapResource(mRS, mResources, + id, RGB_565, false); + allocation.setName(name); + return allocation; + } + + private void createProgramFragment() { + Sampler.Builder bs = new Sampler.Builder(mRS); + bs.setMin(LINEAR); + bs.setMag(LINEAR); + bs.setWrapS(CLAMP); + bs.setWrapT(CLAMP); + mSampler = bs.create(); + + ProgramFragment.Builder b; + b = new ProgramFragment.Builder(mRS, null, null); + b.setTexEnable(true, 0); + b.setTexEnvMode(REPLACE, 0); + mPfBackground = b.create(); + mPfBackground.setName("PFBackground"); + mPfBackground.bindSampler(mSampler, 0); + + bs = new Sampler.Builder(mRS); + bs.setMin(LINEAR); + bs.setMag(LINEAR); + bs.setWrapS(WRAP); + bs.setWrapT(WRAP); + mNightSampler = bs.create(); + + b = new ProgramFragment.Builder(mRS, null, null); + b.setTexEnable(true, 0); + b.setTexEnvMode(REPLACE, 0); + mPfNight = b.create(); + mPfNight.setName("PFNight"); + mPfNight.bindSampler(mNightSampler, 0); + } + + private void createProgramFragmentStore() { + ProgramStore.Builder b; + b = new ProgramStore.Builder(mRS, null, null); + + b.setDepthFunc(ALWAYS); + b.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA); + b.setDitherEnable(true); + b.setDepthMask(false); + mPfsBackground = b.create(); + mPfsBackground.setName("PFSBackground"); + } + + private void createProgramVertex() { + mPvOrthoAlloc = new ProgramVertex.MatrixAllocation(mRS); + mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight); + + ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null); + pvb.setTextureMatrixEnable(true); + mPvBackground = pvb.create(); + mPvBackground.bindAllocation(mPvOrthoAlloc); + mPvBackground.setName("PVBackground"); + } +} diff --git a/src/com/android/wallpaper/grass/GrassWallpaper.java b/src/com/android/wallpaper/grass/GrassWallpaper.java new file mode 100644 index 000000000..d374424a7 --- /dev/null +++ b/src/com/android/wallpaper/grass/GrassWallpaper.java @@ -0,0 +1,73 @@ +/* + * 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.grass; + +import android.service.wallpaper.WallpaperService; +import android.view.SurfaceHolder; +import android.view.Surface; +import android.renderscript.RenderScript; + +public class GrassWallpaper extends WallpaperService { + public Engine onCreateEngine() { + return new RenderScriptEngine(); + } + + private class RenderScriptEngine extends Engine { + private RenderScript mRs; + private GrassRS mRenderer; + + @Override + public void onCreate(SurfaceHolder surfaceHolder) { + super.onCreate(surfaceHolder); + surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_GPU); + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + @Override + public void onVisibilityChanged(boolean visible) { + super.onVisibilityChanged(visible); + } + + @Override + public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { + super.onSurfaceChanged(holder, format, width, height); + mRenderer = new GrassRS(width, height); + mRenderer.init(mRs, getResources()); + } + + @Override + public void onSurfaceCreated(SurfaceHolder holder) { + super.onSurfaceCreated(holder); + + Surface surface = null; + while (surface == null) { + surface = holder.getSurface(); + } + mRs = new RenderScript(surface); + } + + @Override + public void onSurfaceDestroyed(SurfaceHolder holder) { + super.onSurfaceDestroyed(holder); + mRenderer.destroy(); + } + } +} |