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 
18 package com.android.testapp;
19 
20 import java.util.ArrayList;
21 
22 import com.android.scenegraph.*;
23 
24 import android.content.res.Resources;
25 import android.graphics.Bitmap;
26 import android.graphics.BitmapFactory;
27 import android.os.AsyncTask;
28 import android.renderscript.*;
29 import android.renderscript.Allocation.MipmapControl;
30 import android.renderscript.Element.Builder;
31 import android.renderscript.Font.Style;
32 import android.renderscript.Program.TextureType;
33 import android.renderscript.ProgramStore.DepthFunc;
34 import android.util.Log;
35 
36 class 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
createRenderTargets(RenderScriptGL rs, int w, int h)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 
addOffsets(Renderable quad, float advance)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 
addPass(Scene scene, Camera cam, TextureRenderTarget color, TextureRenderTarget depth)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 
addBlurPasses(Scene scene, RenderScriptGL rs, Camera cam)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
addCompositePass(Scene scene, RenderScriptGL rs, Camera cam)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 
getShader(Resources res, RenderScriptGL rs, int resID, Type constants)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 
initShaders(Resources res, RenderScriptGL rs)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