Home | History | Annotate | Download | only in renderscript
      1 /*
      2  * Copyright (C) 2008 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 package android.renderscript;
     18 
     19 
     20 import android.graphics.Matrix;
     21 import android.util.Log;
     22 
     23 
     24 /**
     25  * ProgramVertexFixedFunction is a helper class that provides a
     26  * simple way to create a fixed function emulation vertex shader
     27  * without writing any GLSL code.
     28  *
     29  **/
     30 public class ProgramVertexFixedFunction extends ProgramVertex {
     31 
     32     ProgramVertexFixedFunction(int id, RenderScript rs) {
     33         super(id, rs);
     34     }
     35 
     36     /**
     37      * Binds the constant buffer containing fixed function emulation
     38      * matrices
     39      *
     40      * @param va allocation containing fixed function matrices
     41      */
     42     public void bindConstants(Constants va) {
     43         mRS.validate();
     44         bindConstants(va.getAllocation(), 0);
     45     }
     46 
     47     static class InternalBuilder extends BaseProgramBuilder {
     48         public InternalBuilder(RenderScript rs) {
     49             super(rs);
     50         }
     51 
     52         public InternalBuilder addInput(Element e) throws IllegalStateException {
     53             // Should check for consistant and non-conflicting names...
     54             if(mInputCount >= MAX_INPUT) {
     55                 throw new RSIllegalArgumentException("Max input count exceeded.");
     56             }
     57             if (e.isComplex()) {
     58                 throw new RSIllegalArgumentException("Complex elements not allowed.");
     59             }
     60             mInputs[mInputCount++] = e;
     61             return this;
     62         }
     63 
     64         /**
     65          * Creates ProgramVertexFixedFunction from the current state of
     66          * the builder
     67          *
     68          * @return  ProgramVertexFixedFunction
     69          */
     70         public ProgramVertexFixedFunction create() {
     71             mRS.validate();
     72             int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
     73             int idx = 0;
     74 
     75             for (int i=0; i < mInputCount; i++) {
     76                 tmp[idx++] = ProgramParam.INPUT.mID;
     77                 tmp[idx++] = mInputs[i].getID();
     78             }
     79             for (int i=0; i < mOutputCount; i++) {
     80                 tmp[idx++] = ProgramParam.OUTPUT.mID;
     81                 tmp[idx++] = mOutputs[i].getID();
     82             }
     83             for (int i=0; i < mConstantCount; i++) {
     84                 tmp[idx++] = ProgramParam.CONSTANT.mID;
     85                 tmp[idx++] = mConstants[i].getID();
     86             }
     87             for (int i=0; i < mTextureCount; i++) {
     88                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
     89                 tmp[idx++] = mTextureTypes[i].mID;
     90             }
     91 
     92             int id = mRS.nProgramVertexCreate(mShader, tmp);
     93             ProgramVertexFixedFunction pv = new ProgramVertexFixedFunction(id, mRS);
     94             initProgram(pv);
     95             return pv;
     96         }
     97     }
     98 
     99     public static class Builder {
    100         boolean mTextureMatrixEnable;
    101         String mShader;
    102         RenderScript mRS;
    103 
    104         /**
    105          * Creates a builder for fixed function vertex program
    106          *
    107          * @param rs Context to which the program will belong.
    108          */
    109         public Builder(RenderScript rs) {
    110             mRS = rs;
    111         }
    112 
    113         /**
    114          * Specifies whether texture matrix calculations are to be added
    115          * to the shader
    116          *
    117          */
    118         public Builder setTextureMatrixEnable(boolean enable) {
    119             mTextureMatrixEnable = enable;
    120             return this;
    121         }
    122         static Type getConstantInputType(RenderScript rs) {
    123             Element.Builder b = new Element.Builder(rs);
    124             b.add(Element.MATRIX4X4(rs), "MV");
    125             b.add(Element.MATRIX4X4(rs), "P");
    126             b.add(Element.MATRIX4X4(rs), "TexMatrix");
    127             b.add(Element.MATRIX4X4(rs), "MVP");
    128 
    129             Type.Builder typeBuilder = new Type.Builder(rs, b.create());
    130             typeBuilder.setX(1);
    131             return typeBuilder.create();
    132         }
    133 
    134         private void buildShaderString() {
    135 
    136             mShader  = "//rs_shader_internal\n";
    137             mShader += "varying vec4 varColor;\n";
    138             mShader += "varying vec2 varTex0;\n";
    139 
    140             mShader += "void main() {\n";
    141             mShader += "  gl_Position = UNI_MVP * ATTRIB_position;\n";
    142             mShader += "  gl_PointSize = 1.0;\n";
    143 
    144             mShader += "  varColor = ATTRIB_color;\n";
    145             if (mTextureMatrixEnable) {
    146                 mShader += "  varTex0 = (UNI_TexMatrix * vec4(ATTRIB_texture0, 0.0, 1.0)).xy;\n";
    147             } else {
    148                 mShader += "  varTex0 = ATTRIB_texture0;\n";
    149             }
    150             mShader += "}\n";
    151         }
    152 
    153         /**
    154          * Creates ProgramVertexFixedFunction from the current state of
    155          * the builder
    156          *
    157          * @return Fixed function emulation ProgramVertex
    158          */
    159         public ProgramVertexFixedFunction create() {
    160             buildShaderString();
    161 
    162             InternalBuilder sb = new InternalBuilder(mRS);
    163             sb.setShader(mShader);
    164             sb.addConstant(getConstantInputType(mRS));
    165 
    166             Element.Builder b = new Element.Builder(mRS);
    167             b.add(Element.F32_4(mRS), "position");
    168             b.add(Element.F32_4(mRS), "color");
    169             b.add(Element.F32_3(mRS), "normal");
    170             b.add(Element.F32_2(mRS), "texture0");
    171             sb.addInput(b.create());
    172 
    173             return sb.create();
    174         }
    175     }
    176 
    177     /**
    178      * Helper class to store modelview, projection and texture
    179      * matrices for ProgramVertexFixedFunction
    180      *
    181      */
    182     public static class Constants {
    183         static final int MODELVIEW_OFFSET = 0;
    184         static final int PROJECTION_OFFSET = 16;
    185         static final int TEXTURE_OFFSET = 32;
    186 
    187         Matrix4f mModel;
    188         Matrix4f mProjection;
    189         Matrix4f mTexture;
    190 
    191         Allocation mAlloc;
    192         Allocation getAllocation() {
    193             return mAlloc;
    194         }
    195         private FieldPacker mIOBuffer;
    196 
    197         /**
    198         * Creates a buffer to store fixed function emulation matrices
    199         *
    200         * @param rs Context to which the allocation will belong.
    201         **/
    202         public Constants(RenderScript rs) {
    203             Type constInputType = ProgramVertexFixedFunction.Builder.getConstantInputType(rs);
    204             mAlloc = Allocation.createTyped(rs, constInputType);
    205             int bufferSize = constInputType.getElement().getSizeBytes()*
    206                              constInputType.getCount();
    207             mIOBuffer = new FieldPacker(bufferSize);
    208             mModel = new Matrix4f();
    209             mProjection = new Matrix4f();
    210             mTexture = new Matrix4f();
    211             setModelview(new Matrix4f());
    212             setProjection(new Matrix4f());
    213             setTexture(new Matrix4f());
    214         }
    215 
    216         /**
    217         * Forces deallocation of memory backing the contant matrices.
    218         * Normally, this is unnecessary and will be garbage collected
    219         *
    220         */
    221         public void destroy() {
    222             mAlloc.destroy();
    223             mAlloc = null;
    224         }
    225 
    226         private void addToBuffer(int offset, Matrix4f m) {
    227             mIOBuffer.reset(offset);
    228             for(int i = 0; i < 16; i ++) {
    229                 mIOBuffer.addF32(m.mMat[i]);
    230             }
    231             mAlloc.setFromFieldPacker(0, mIOBuffer);
    232         }
    233 
    234         /**
    235         * Sets the modelview matrix in the fixed function matrix buffer
    236         *
    237         * @param m modelview matrix
    238         */
    239         public void setModelview(Matrix4f m) {
    240             mModel.load(m);
    241             addToBuffer(MODELVIEW_OFFSET*4, m);
    242         }
    243 
    244         /**
    245         * Sets the projection matrix in the fixed function matrix buffer
    246         *
    247         * @param m projection matrix
    248         */
    249         public void setProjection(Matrix4f m) {
    250             mProjection.load(m);
    251             addToBuffer(PROJECTION_OFFSET*4, m);
    252         }
    253 
    254         /**
    255         * Sets the texture matrix in the fixed function matrix buffer.
    256         * Texture matrix must be enabled in the
    257         * ProgramVertexFixedFunction builder for the shader to utilize
    258         * it.
    259         *
    260         * @param m modelview matrix
    261         */
    262         public void setTexture(Matrix4f m) {
    263             mTexture.load(m);
    264             addToBuffer(TEXTURE_OFFSET*4, m);
    265         }
    266     }
    267 }
    268