Home | History | Annotate | Download | only in rs
      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 #include "rsContext.h"
     18 #include "rsProgramVertex.h"
     19 
     20 using namespace android;
     21 using namespace android::renderscript;
     22 
     23 
     24 ProgramVertex::ProgramVertex(Context *rsc, const char * shaderText,
     25                              uint32_t shaderLength, const uint32_t * params,
     26                              uint32_t paramLength)
     27     : Program(rsc, shaderText, shaderLength, params, paramLength) {
     28     mRSC->mHal.funcs.vertex.init(mRSC, this, mUserShader.string(), mUserShader.length());
     29 }
     30 
     31 ProgramVertex::~ProgramVertex() {
     32     mRSC->mHal.funcs.vertex.destroy(mRSC, this);
     33 }
     34 
     35 void ProgramVertex::setup(Context *rsc, ProgramVertexState *state) {
     36     if ((state->mLast.get() == this) && !mDirty) {
     37         return;
     38     }
     39 
     40     if (!isUserProgram()) {
     41         if (mHal.state.constants[0] == NULL) {
     42             rsc->setError(RS_ERROR_FATAL_UNKNOWN,
     43                           "Unable to set fixed function emulation matrices because allocation is missing");
     44             return;
     45         }
     46         float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
     47         Matrix4x4 mvp;
     48         mvp.load(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
     49         Matrix4x4 t;
     50         t.load(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET]);
     51         mvp.multiply(&t);
     52         for (uint32_t i = 0; i < 16; i ++) {
     53             f[RS_PROGRAM_VERTEX_MVP_OFFSET + i] = mvp.m[i];
     54         }
     55     }
     56 
     57     state->mLast.set(this);
     58 
     59     rsc->mHal.funcs.vertex.setActive(rsc, this);
     60 }
     61 
     62 void ProgramVertex::setProjectionMatrix(Context *rsc, const rsc_Matrix *m) const {
     63     if (isUserProgram()) {
     64         rsc->setError(RS_ERROR_FATAL_UNKNOWN,
     65                       "Attempting to set fixed function emulation matrix projection on user program");
     66         return;
     67     }
     68     if (mHal.state.constants[0] == NULL) {
     69         rsc->setError(RS_ERROR_FATAL_UNKNOWN,
     70                       "Unable to set fixed function emulation matrix projection because allocation is missing");
     71         return;
     72     }
     73     float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
     74     memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m, sizeof(rsc_Matrix));
     75     mDirty = true;
     76 }
     77 
     78 void ProgramVertex::setModelviewMatrix(Context *rsc, const rsc_Matrix *m) const {
     79     if (isUserProgram()) {
     80         rsc->setError(RS_ERROR_FATAL_UNKNOWN,
     81                       "Attempting to set fixed function emulation matrix modelview on user program");
     82         return;
     83     }
     84     if (mHal.state.constants[0] == NULL) {
     85         rsc->setError(RS_ERROR_FATAL_UNKNOWN,
     86                       "Unable to set fixed function emulation matrix modelview because allocation is missing");
     87         return;
     88     }
     89     float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
     90     memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m, sizeof(rsc_Matrix));
     91     mDirty = true;
     92 }
     93 
     94 void ProgramVertex::setTextureMatrix(Context *rsc, const rsc_Matrix *m) const {
     95     if (isUserProgram()) {
     96         rsc->setError(RS_ERROR_FATAL_UNKNOWN,
     97                       "Attempting to set fixed function emulation matrix texture on user program");
     98         return;
     99     }
    100     if (mHal.state.constants[0] == NULL) {
    101         rsc->setError(RS_ERROR_FATAL_UNKNOWN,
    102                       "Unable to set fixed function emulation matrix texture because allocation is missing");
    103         return;
    104     }
    105     float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
    106     memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m, sizeof(rsc_Matrix));
    107     mDirty = true;
    108 }
    109 
    110 void ProgramVertex::getProjectionMatrix(Context *rsc, rsc_Matrix *m) const {
    111     if (isUserProgram()) {
    112         rsc->setError(RS_ERROR_FATAL_UNKNOWN,
    113                       "Attempting to get fixed function emulation matrix projection on user program");
    114         return;
    115     }
    116     if (mHal.state.constants[0] == NULL) {
    117         rsc->setError(RS_ERROR_FATAL_UNKNOWN,
    118                       "Unable to get fixed function emulation matrix projection because allocation is missing");
    119         return;
    120     }
    121     float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
    122     memcpy(m, &f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], sizeof(rsc_Matrix));
    123 }
    124 
    125 void ProgramVertex::transformToScreen(Context *rsc, float *v4out, const float *v3in) const {
    126     if (isUserProgram()) {
    127         return;
    128     }
    129     float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
    130     Matrix4x4 mvp;
    131     mvp.loadMultiply((Matrix4x4 *)&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET],
    132                      (Matrix4x4 *)&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
    133     mvp.vectorMultiply(v4out, v3in);
    134 }
    135 
    136 void ProgramVertex::serialize(OStream *stream) const {
    137 }
    138 
    139 ProgramVertex *ProgramVertex::createFromStream(Context *rsc, IStream *stream) {
    140     return NULL;
    141 }
    142 
    143 
    144 ///////////////////////////////////////////////////////////////////////
    145 
    146 ProgramVertexState::ProgramVertexState() {
    147 }
    148 
    149 ProgramVertexState::~ProgramVertexState() {
    150 }
    151 
    152 void ProgramVertexState::init(Context *rsc) {
    153     ObjectBaseRef<const Element> matrixElem = Element::createRef(rsc, RS_TYPE_MATRIX_4X4,
    154                                                                  RS_KIND_USER, false, 1);
    155     ObjectBaseRef<const Element> f2Elem = Element::createRef(rsc, RS_TYPE_FLOAT_32,
    156                                                              RS_KIND_USER, false, 2);
    157     ObjectBaseRef<const Element> f3Elem = Element::createRef(rsc, RS_TYPE_FLOAT_32,
    158                                                              RS_KIND_USER, false, 3);
    159     ObjectBaseRef<const Element> f4Elem = Element::createRef(rsc, RS_TYPE_FLOAT_32,
    160                                                              RS_KIND_USER, false, 4);
    161 
    162     Element::Builder constBuilder;
    163     constBuilder.add(matrixElem.get(), "MV", 1);
    164     constBuilder.add(matrixElem.get(), "P", 1);
    165     constBuilder.add(matrixElem.get(), "TexMatrix", 1);
    166     constBuilder.add(matrixElem.get(), "MVP", 1);
    167     ObjectBaseRef<const Element> constInput = constBuilder.create(rsc);
    168 
    169     Element::Builder inputBuilder;
    170     inputBuilder.add(f4Elem.get(), "position", 1);
    171     inputBuilder.add(f4Elem.get(), "color", 1);
    172     inputBuilder.add(f3Elem.get(), "normal", 1);
    173     inputBuilder.add(f2Elem.get(), "texture0", 1);
    174     ObjectBaseRef<const Element> attrElem = inputBuilder.create(rsc);
    175 
    176     ObjectBaseRef<Type> inputType = Type::getTypeRef(rsc, constInput.get(), 1, 0, 0, false, false);
    177 
    178     String8 shaderString(RS_SHADER_INTERNAL);
    179     shaderString.append("varying vec4 varColor;\n");
    180     shaderString.append("varying vec2 varTex0;\n");
    181     shaderString.append("void main() {\n");
    182     shaderString.append("  gl_Position = UNI_MVP * ATTRIB_position;\n");
    183     shaderString.append("  gl_PointSize = 1.0;\n");
    184     shaderString.append("  varColor = ATTRIB_color;\n");
    185     shaderString.append("  varTex0 = ATTRIB_texture0;\n");
    186     shaderString.append("}\n");
    187 
    188     uint32_t tmp[4];
    189     tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
    190     tmp[1] = (uint32_t)inputType.get();
    191     tmp[2] = RS_PROGRAM_PARAM_INPUT;
    192     tmp[3] = (uint32_t)attrElem.get();
    193 
    194     ProgramVertex *pv = new ProgramVertex(rsc, shaderString.string(),
    195                                           shaderString.length(), tmp, 4);
    196     Allocation *alloc = Allocation::createAllocation(rsc, inputType.get(),
    197                               RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS);
    198     pv->bindAllocation(rsc, alloc, 0);
    199 
    200     mDefaultAlloc.set(alloc);
    201     mDefault.set(pv);
    202 
    203     updateSize(rsc);
    204 }
    205 
    206 void ProgramVertexState::updateSize(Context *rsc) {
    207     float *f = static_cast<float *>(mDefaultAlloc->getPtr());
    208 
    209     Matrix4x4 m;
    210     m.loadOrtho(0,rsc->getWidth(), rsc->getHeight(),0, -1,1);
    211     memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m.m, sizeof(m));
    212     memcpy(&f[RS_PROGRAM_VERTEX_MVP_OFFSET], m.m, sizeof(m));
    213 
    214     m.loadIdentity();
    215     memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m.m, sizeof(m));
    216     memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m.m, sizeof(m));
    217 }
    218 
    219 void ProgramVertexState::deinit(Context *rsc) {
    220     mDefaultAlloc.clear();
    221     mDefault.clear();
    222     mLast.clear();
    223 }
    224 
    225 
    226 namespace android {
    227 namespace renderscript {
    228 
    229 RsProgramVertex rsi_ProgramVertexCreate(Context *rsc, const char * shaderText,
    230                              size_t shaderLength, const uint32_t * params,
    231                              size_t paramLength) {
    232     ProgramVertex *pv = new ProgramVertex(rsc, shaderText, shaderLength, params, paramLength);
    233     pv->incUserRef();
    234     return pv;
    235 }
    236 
    237 }
    238 }
    239