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