1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18package com.android.testapp;
19
20import java.util.ArrayList;
21
22import com.android.scenegraph.*;
23
24import android.content.res.Resources;
25import android.graphics.Bitmap;
26import android.graphics.BitmapFactory;
27import android.os.AsyncTask;
28import android.renderscript.*;
29import android.renderscript.Allocation.MipmapControl;
30import android.renderscript.Element.Builder;
31import android.renderscript.Font.Style;
32import android.renderscript.Program.TextureType;
33import android.renderscript.ProgramStore.DepthFunc;
34import android.util.Log;
35
36class FullscreenBlur {
37
38    static TextureRenderTarget sRenderTargetBlur0Color;
39    static TextureRenderTarget sRenderTargetBlur0Depth;
40    static TextureRenderTarget sRenderTargetBlur1Color;
41    static TextureRenderTarget sRenderTargetBlur1Depth;
42    static TextureRenderTarget sRenderTargetBlur2Color;
43    static TextureRenderTarget sRenderTargetBlur2Depth;
44
45    static FragmentShader mPF_BlurH;
46    static FragmentShader mPF_BlurV;
47    static FragmentShader mPF_SelectColor;
48    static FragmentShader mPF_Texture;
49    static VertexShader mPV_Paint;
50    static VertexShader mPV_Blur;
51
52    static int targetWidth;
53    static int targetHeight;
54
55    // This is only used when full screen blur is enabled
56    // Basically, it's the offscreen render targets
57    static void createRenderTargets(RenderScriptGL rs, int w, int h) {
58        targetWidth = w/8;
59        targetHeight = h/8;
60        Type.Builder b = new Type.Builder(rs, Element.RGBA_8888(rs));
61        Type renderType = b.setX(targetWidth).setY(targetHeight).create();
62        int usage = Allocation.USAGE_GRAPHICS_TEXTURE | Allocation.USAGE_GRAPHICS_RENDER_TARGET;
63        sRenderTargetBlur0Color = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
64        sRenderTargetBlur1Color = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
65        sRenderTargetBlur2Color = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
66
67        b = new Type.Builder(rs, Element.createPixel(rs, Element.DataType.UNSIGNED_16,
68                                                     Element.DataKind.PIXEL_DEPTH));
69        renderType = b.setX(targetWidth).setY(targetHeight).create();
70        usage = Allocation.USAGE_GRAPHICS_RENDER_TARGET;
71        sRenderTargetBlur0Depth = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
72        sRenderTargetBlur1Depth = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
73        sRenderTargetBlur2Depth = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
74    }
75
76    static void addOffsets(Renderable quad, float advance) {
77        quad.appendSourceParams(new Float4Param("blurOffset0", - advance * 2.5f));
78        quad.appendSourceParams(new Float4Param("blurOffset1", - advance * 0.5f));
79        quad.appendSourceParams(new Float4Param("blurOffset2", advance * 1.5f));
80        quad.appendSourceParams(new Float4Param("blurOffset3", advance * 3.5f));
81    }
82
83    static RenderPass addPass(Scene scene, Camera cam, TextureRenderTarget color, TextureRenderTarget depth) {
84        RenderPass pass = new RenderPass();
85        pass.setColorTarget(color);
86        pass.setDepthTarget(depth);
87        pass.setShouldClearColor(false);
88        pass.setShouldClearDepth(false);
89        pass.setCamera(cam);
90        scene.appendRenderPass(pass);
91        return pass;
92    }
93
94    static void addBlurPasses(Scene scene, RenderScriptGL rs, Camera cam) {
95        SceneManager sceneManager = SceneManager.getInstance();
96        ArrayList<RenderableBase> allDraw = scene.getRenderables();
97        int numDraw = allDraw.size();
98
99        ProgramRaster cullNone = ProgramRaster.CULL_NONE(rs);
100        ProgramStore blendAdd = SceneManager.BLEND_ADD_DEPTH_NONE(rs);
101        ProgramStore blendNone = ProgramStore.BLEND_NONE_DEPTH_NONE(rs);
102
103        RenderState drawTex = new RenderState(mPV_Blur, mPF_Texture, blendAdd, cullNone);
104        RenderState selectCol = new RenderState(mPV_Blur, mPF_SelectColor, blendNone, cullNone);
105        RenderState hBlur = new RenderState(mPV_Blur, mPF_BlurH, blendNone, cullNone);
106        RenderState vBlur = new RenderState(mPV_Blur, mPF_BlurV, blendNone, cullNone);
107
108        // Renders the scene off screen
109        RenderPass blurSourcePass = addPass(scene, cam,
110                                            sRenderTargetBlur0Color,
111                                            sRenderTargetBlur0Depth);
112        blurSourcePass.setClearColor(new Float4(1.0f, 1.0f, 1.0f, 1.0f));
113        blurSourcePass.setShouldClearColor(true);
114        blurSourcePass.setClearDepth(1.0f);
115        blurSourcePass.setShouldClearDepth(true);
116        for (int i = 0; i < numDraw; i ++) {
117            blurSourcePass.appendRenderable((Renderable)allDraw.get(i));
118        }
119
120        // Pass for selecting bright colors
121        RenderPass selectColorPass = addPass(scene, cam,
122                                             sRenderTargetBlur2Color,
123                                             sRenderTargetBlur2Depth);
124        Renderable quad = sceneManager.getRenderableQuad("ScreenAlignedQuadS", selectCol);
125        quad.appendSourceParams(new TextureParam("color", sRenderTargetBlur0Color));
126        selectColorPass.appendRenderable(quad);
127
128        // Horizontal blur
129        RenderPass horizontalBlurPass = addPass(scene, cam,
130                                                sRenderTargetBlur1Color,
131                                                sRenderTargetBlur1Depth);
132        quad = sceneManager.getRenderableQuad("ScreenAlignedQuadH", hBlur);
133        quad.appendSourceParams(new TextureParam("color", sRenderTargetBlur2Color));
134        addOffsets(quad, 1.0f / (float)targetWidth);
135        horizontalBlurPass.appendRenderable(quad);
136
137        // Vertical Blur
138        RenderPass verticalBlurPass = addPass(scene, cam,
139                                              sRenderTargetBlur2Color,
140                                              sRenderTargetBlur2Depth);
141        quad = sceneManager.getRenderableQuad("ScreenAlignedQuadV", vBlur);
142        quad.appendSourceParams(new TextureParam("color", sRenderTargetBlur1Color));
143        addOffsets(quad, 1.0f / (float)targetHeight);
144        verticalBlurPass.appendRenderable(quad);
145    }
146
147    // Additively renders the blurred colors on top of the scene
148    static void addCompositePass(Scene scene, RenderScriptGL rs, Camera cam) {
149        SceneManager sceneManager = SceneManager.getInstance();
150        RenderState drawTex = new RenderState(mPV_Blur, mPF_Texture,
151                                              SceneManager.BLEND_ADD_DEPTH_NONE(rs),
152                                              ProgramRaster.CULL_NONE(rs));
153
154        RenderPass compositePass = addPass(scene, cam, null, null);
155        Renderable quad = sceneManager.getRenderableQuad("ScreenAlignedQuadComposite", drawTex);
156        quad.appendSourceParams(new TextureParam("color", sRenderTargetBlur2Color));
157        compositePass.appendRenderable(quad);
158    }
159
160    static private FragmentShader getShader(Resources res, RenderScriptGL rs,
161                                            int resID, Type constants) {
162        FragmentShader.Builder fb = new FragmentShader.Builder(rs);
163        fb.setShader(res, resID);
164        fb.addTexture(TextureType.TEXTURE_2D, "color");
165        if (constants != null) {
166            fb.setObjectConst(constants);
167        }
168        FragmentShader prog = fb.create();
169        prog.getProgram().bindSampler(Sampler.CLAMP_LINEAR(rs), 0);
170        return prog;
171    }
172
173    static void initShaders(Resources res, RenderScriptGL rs) {
174        ScriptField_BlurOffsets blurConst = new ScriptField_BlurOffsets(rs, 1);
175        VertexShader.Builder vb = new VertexShader.Builder(rs);
176        vb.addInput(ScriptField_VertexShaderInputs.createElement(rs));
177        vb.setShader(res, R.raw.blur_vertex);
178        mPV_Blur = vb.create();
179
180        mPF_Texture = getShader(res, rs, R.raw.texture, null);
181        mPF_Texture.getProgram().bindSampler(Sampler.WRAP_LINEAR_MIP_LINEAR(rs), 0);
182        mPF_BlurH = getShader(res, rs, R.raw.blur_h, blurConst.getAllocation().getType());
183        mPF_BlurV = getShader(res, rs, R.raw.blur_v, blurConst.getAllocation().getType());
184        mPF_SelectColor = getShader(res, rs, R.raw.select_color, null);
185    }
186
187}
188
189
190
191
192
193