Home | History | Annotate | Download | only in rs
      1 /*
      2  * Copyright (C) 2009 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 #include <GLES/gl.h>
     21 #include <GLES/glext.h>
     22 #include <GLES2/gl2.h>
     23 #include <GLES2/gl2ext.h>
     24 
     25 using namespace android;
     26 using namespace android::renderscript;
     27 
     28 
     29 ProgramVertex::ProgramVertex(Context *rsc, bool texMat) :
     30     Program(rsc)
     31 {
     32     mAllocFile = __FILE__;
     33     mAllocLine = __LINE__;
     34     mTextureMatrixEnable = texMat;
     35     mLightCount = 0;
     36     init(rsc);
     37 }
     38 
     39 ProgramVertex::ProgramVertex(Context *rsc, const char * shaderText,
     40                              uint32_t shaderLength, const uint32_t * params,
     41                              uint32_t paramLength) :
     42     Program(rsc, shaderText, shaderLength, params, paramLength)
     43 {
     44     mAllocFile = __FILE__;
     45     mAllocLine = __LINE__;
     46     mTextureMatrixEnable = false;
     47     mLightCount = 0;
     48 
     49     init(rsc);
     50 }
     51 
     52 ProgramVertex::~ProgramVertex()
     53 {
     54 }
     55 
     56 static void logMatrix(const char *txt, const float *f)
     57 {
     58     LOGV("Matrix %s, %p", txt, f);
     59     LOGV("%6.4f, %6.4f, %6.4f, %6.4f", f[0], f[4], f[8], f[12]);
     60     LOGV("%6.4f, %6.4f, %6.4f, %6.4f", f[1], f[5], f[9], f[13]);
     61     LOGV("%6.4f, %6.4f, %6.4f, %6.4f", f[2], f[6], f[10], f[14]);
     62     LOGV("%6.4f, %6.4f, %6.4f, %6.4f", f[3], f[7], f[11], f[15]);
     63 }
     64 
     65 void ProgramVertex::setupGL(const Context *rsc, ProgramVertexState *state)
     66 {
     67     if ((state->mLast.get() == this) && !mDirty) {
     68         return;
     69     }
     70     state->mLast.set(this);
     71 
     72     const float *f = static_cast<const float *>(mConstants[0]->getPtr());
     73 
     74     glMatrixMode(GL_TEXTURE);
     75     if (mTextureMatrixEnable) {
     76         glLoadMatrixf(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET]);
     77     } else {
     78         glLoadIdentity();
     79     }
     80 
     81     glMatrixMode(GL_MODELVIEW);
     82     glLoadIdentity();
     83     if (mLightCount) {
     84         int v = 0;
     85         glEnable(GL_LIGHTING);
     86         glLightModelxv(GL_LIGHT_MODEL_TWO_SIDE, &v);
     87         for (uint32_t ct = 0; ct < mLightCount; ct++) {
     88             const Light *l = mLights[ct].get();
     89             glEnable(GL_LIGHT0 + ct);
     90             l->setupGL(ct);
     91         }
     92         for (uint32_t ct = mLightCount; ct < MAX_LIGHTS; ct++) {
     93             glDisable(GL_LIGHT0 + ct);
     94         }
     95     } else {
     96         glDisable(GL_LIGHTING);
     97     }
     98 
     99     if (!f) {
    100         LOGE("Must bind constants to vertex program");
    101     }
    102 
    103     glMatrixMode(GL_PROJECTION);
    104     glLoadMatrixf(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
    105     glMatrixMode(GL_MODELVIEW);
    106     glLoadMatrixf(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET]);
    107 
    108     mDirty = false;
    109 }
    110 
    111 void ProgramVertex::loadShader(Context *rsc) {
    112     Program::loadShader(rsc, GL_VERTEX_SHADER);
    113 }
    114 
    115 void ProgramVertex::createShader()
    116 {
    117     mShader.setTo("");
    118 
    119     mShader.append("varying vec4 varColor;\n");
    120     mShader.append("varying vec4 varTex0;\n");
    121 
    122     if (mUserShader.length() > 1) {
    123         mShader.append("uniform mat4 ");
    124         mShader.append(mUniformNames[0]);
    125         mShader.append(";\n");
    126 
    127         for (uint32_t ct=0; ct < mConstantCount; ct++) {
    128             const Element *e = mConstantTypes[ct]->getElement();
    129             for (uint32_t field=0; field < e->getFieldCount(); field++) {
    130                 const Element *f = e->getField(field);
    131 
    132                 // Cannot be complex
    133                 rsAssert(!f->getFieldCount());
    134                 switch(f->getComponent().getVectorSize()) {
    135                 case 1: mShader.append("uniform float UNI_"); break;
    136                 case 2: mShader.append("uniform vec2 UNI_"); break;
    137                 case 3: mShader.append("uniform vec3 UNI_"); break;
    138                 case 4: mShader.append("uniform vec4 UNI_"); break;
    139                 default:
    140                     rsAssert(0);
    141                 }
    142 
    143                 mShader.append(e->getFieldName(field));
    144                 mShader.append(";\n");
    145             }
    146         }
    147 
    148 
    149         for (uint32_t ct=0; ct < mInputCount; ct++) {
    150             const Element *e = mInputElements[ct].get();
    151             for (uint32_t field=0; field < e->getFieldCount(); field++) {
    152                 const Element *f = e->getField(field);
    153 
    154                 // Cannot be complex
    155                 rsAssert(!f->getFieldCount());
    156                 switch(f->getComponent().getVectorSize()) {
    157                 case 1: mShader.append("attribute float ATTRIB_"); break;
    158                 case 2: mShader.append("attribute vec2 ATTRIB_"); break;
    159                 case 3: mShader.append("attribute vec3 ATTRIB_"); break;
    160                 case 4: mShader.append("attribute vec4 ATTRIB_"); break;
    161                 default:
    162                     rsAssert(0);
    163                 }
    164 
    165                 mShader.append(e->getFieldName(field));
    166                 mShader.append(";\n");
    167             }
    168         }
    169         mShader.append(mUserShader);
    170     } else {
    171         mShader.append("attribute vec4 ATTRIB_LegacyPosition;\n");
    172         mShader.append("attribute vec4 ATTRIB_LegacyColor;\n");
    173         mShader.append("attribute vec3 ATTRIB_LegacyNormal;\n");
    174         mShader.append("attribute float ATTRIB_LegacyPointSize;\n");
    175         mShader.append("attribute vec4 ATTRIB_LegacyTexture;\n");
    176 
    177         for (uint32_t ct=0; ct < mUniformCount; ct++) {
    178             mShader.append("uniform mat4 ");
    179             mShader.append(mUniformNames[ct]);
    180             mShader.append(";\n");
    181         }
    182 
    183         mShader.append("void main() {\n");
    184         mShader.append("  gl_Position = UNI_MVP * ATTRIB_LegacyPosition;\n");
    185         mShader.append("  gl_PointSize = ATTRIB_LegacyPointSize;\n");
    186 
    187         mShader.append("  varColor = ATTRIB_LegacyColor;\n");
    188         if (mTextureMatrixEnable) {
    189             mShader.append("  varTex0 = UNI_TexMatrix * ATTRIB_LegacyTexture;\n");
    190         } else {
    191             mShader.append("  varTex0 = ATTRIB_LegacyTexture;\n");
    192         }
    193         //mShader.append("  pos.x = pos.x / 480.0;\n");
    194         //mShader.append("  pos.y = pos.y / 800.0;\n");
    195         //mShader.append("  gl_Position = pos;\n");
    196         mShader.append("}\n");
    197     }
    198 }
    199 
    200 void ProgramVertex::setupGL2(const Context *rsc, ProgramVertexState *state, ShaderCache *sc)
    201 {
    202     //LOGE("sgl2 vtx1 %x", glGetError());
    203     if ((state->mLast.get() == this) && !mDirty) {
    204         //return;
    205     }
    206 
    207     rsc->checkError("ProgramVertex::setupGL2 start");
    208     glVertexAttrib4f(1, state->color[0], state->color[1], state->color[2], state->color[3]);
    209 
    210     const float *f = static_cast<const float *>(mConstants[0]->getPtr());
    211 
    212     Matrix mvp;
    213     mvp.load(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
    214     Matrix t;
    215     t.load(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET]);
    216     mvp.multiply(&t);
    217 
    218     glUniformMatrix4fv(sc->vtxUniformSlot(0), 1, GL_FALSE, mvp.m);
    219     if (mTextureMatrixEnable) {
    220         glUniformMatrix4fv(sc->vtxUniformSlot(1), 1, GL_FALSE,
    221                            &f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET]);
    222     }
    223 
    224     rsc->checkError("ProgramVertex::setupGL2 begin uniforms");
    225     uint32_t uidx = 1;
    226     for (uint32_t ct=0; ct < mConstantCount; ct++) {
    227         Allocation *alloc = mConstants[ct+1].get();
    228         if (!alloc) {
    229             continue;
    230         }
    231 
    232         const uint8_t *data = static_cast<const uint8_t *>(alloc->getPtr());
    233         const Element *e = mConstantTypes[ct]->getElement();
    234         for (uint32_t field=0; field < e->getFieldCount(); field++) {
    235             const Element *f = e->getField(field);
    236             uint32_t offset = e->getFieldOffsetBytes(field);
    237             int32_t slot = sc->vtxUniformSlot(uidx);
    238 
    239             const float *fd = reinterpret_cast<const float *>(&data[offset]);
    240 
    241             //LOGE("Uniform  slot=%i, offset=%i, constant=%i, field=%i, uidx=%i", slot, offset, ct, field, uidx);
    242             if (slot >= 0) {
    243                 switch(f->getComponent().getVectorSize()) {
    244                 case 1:
    245                     //LOGE("Uniform 1 = %f", fd[0]);
    246                     glUniform1fv(slot, 1, fd);
    247                     break;
    248                 case 2:
    249                     //LOGE("Uniform 2 = %f %f", fd[0], fd[1]);
    250                     glUniform2fv(slot, 1, fd);
    251                     break;
    252                 case 3:
    253                     //LOGE("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
    254                     glUniform3fv(slot, 1, fd);
    255                     break;
    256                 case 4:
    257                     //LOGE("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
    258                     glUniform4fv(slot, 1, fd);
    259                     break;
    260                 default:
    261                     rsAssert(0);
    262                 }
    263             }
    264             uidx ++;
    265         }
    266     }
    267 
    268     for (uint32_t ct=0; ct < mConstantCount; ct++) {
    269         uint32_t glSlot = sc->vtxUniformSlot(ct + 1);
    270 
    271     }
    272 
    273     state->mLast.set(this);
    274     rsc->checkError("ProgramVertex::setupGL2");
    275 }
    276 
    277 void ProgramVertex::addLight(const Light *l)
    278 {
    279     if (mLightCount < MAX_LIGHTS) {
    280         mLights[mLightCount].set(l);
    281         mLightCount++;
    282     }
    283 }
    284 
    285 void ProgramVertex::setProjectionMatrix(const rsc_Matrix *m) const
    286 {
    287     float *f = static_cast<float *>(mConstants[0]->getPtr());
    288     memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m, sizeof(rsc_Matrix));
    289     mDirty = true;
    290 }
    291 
    292 void ProgramVertex::setModelviewMatrix(const rsc_Matrix *m) const
    293 {
    294     float *f = static_cast<float *>(mConstants[0]->getPtr());
    295     memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m, sizeof(rsc_Matrix));
    296     mDirty = true;
    297 }
    298 
    299 void ProgramVertex::setTextureMatrix(const rsc_Matrix *m) const
    300 {
    301     float *f = static_cast<float *>(mConstants[0]->getPtr());
    302     memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m, sizeof(rsc_Matrix));
    303     mDirty = true;
    304 }
    305 
    306 void ProgramVertex::transformToScreen(const Context *rsc, float *v4out, const float *v3in) const
    307 {
    308     float *f = static_cast<float *>(mConstants[0]->getPtr());
    309     Matrix mvp;
    310     mvp.loadMultiply((Matrix *)&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET],
    311                      (Matrix *)&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
    312     mvp.vectorMultiply(v4out, v3in);
    313 }
    314 
    315 void ProgramVertex::initAddUserElement(const Element *e, String8 *names, uint32_t *count, const char *prefix)
    316 {
    317     rsAssert(e->getFieldCount());
    318     for (uint32_t ct=0; ct < e->getFieldCount(); ct++) {
    319         const Element *ce = e->getField(ct);
    320         if (ce->getFieldCount()) {
    321             initAddUserElement(ce, names, count, prefix);
    322         } else {
    323             String8 tmp(prefix);
    324             tmp.append(e->getFieldName(ct));
    325             names[*count].setTo(tmp.string());
    326             (*count)++;
    327         }
    328     }
    329 }
    330 
    331 
    332 void ProgramVertex::init(Context *rsc)
    333 {
    334     mAttribCount = 0;
    335     if (mUserShader.size() > 0) {
    336         for (uint32_t ct=0; ct < mInputCount; ct++) {
    337             initAddUserElement(mInputElements[ct].get(), mAttribNames, &mAttribCount, "ATTRIB_");
    338         }
    339 
    340         mUniformCount = 1;
    341         mUniformNames[0].setTo("UNI_MVP");
    342         for (uint32_t ct=0; ct < mConstantCount; ct++) {
    343             initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, &mUniformCount, "UNI_");
    344         }
    345     } else {
    346         mUniformCount = 2;
    347         mUniformNames[0].setTo("UNI_MVP");
    348         mUniformNames[1].setTo("UNI_TexMatrix");
    349     }
    350 
    351     createShader();
    352 }
    353 
    354 
    355 ///////////////////////////////////////////////////////////////////////
    356 
    357 ProgramVertexState::ProgramVertexState()
    358 {
    359 }
    360 
    361 ProgramVertexState::~ProgramVertexState()
    362 {
    363 }
    364 
    365 void ProgramVertexState::init(Context *rsc, int32_t w, int32_t h)
    366 {
    367     RsElement e = (RsElement) Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1);
    368 
    369     rsi_TypeBegin(rsc, e);
    370     rsi_TypeAdd(rsc, RS_DIMENSION_X, 48);
    371     mAllocType.set((Type *)rsi_TypeCreate(rsc));
    372 
    373     ProgramVertex *pv = new ProgramVertex(rsc, false);
    374     Allocation *alloc = (Allocation *)rsi_AllocationCreateTyped(rsc, mAllocType.get());
    375     mDefaultAlloc.set(alloc);
    376     mDefault.set(pv);
    377     pv->init(rsc);
    378     pv->bindAllocation(alloc, 0);
    379 
    380     color[0] = 1.f;
    381     color[1] = 1.f;
    382     color[2] = 1.f;
    383     color[3] = 1.f;
    384 
    385     updateSize(rsc, w, h);
    386 }
    387 
    388 void ProgramVertexState::updateSize(Context *rsc, int32_t w, int32_t h)
    389 {
    390     Matrix m;
    391     m.loadOrtho(0,w, h,0, -1,1);
    392     mDefaultAlloc->subData(RS_PROGRAM_VERTEX_PROJECTION_OFFSET, 16, &m.m[0], 16*4);
    393 
    394     m.loadIdentity();
    395     mDefaultAlloc->subData(RS_PROGRAM_VERTEX_MODELVIEW_OFFSET, 16, &m.m[0], 16*4);
    396 }
    397 
    398 void ProgramVertexState::deinit(Context *rsc)
    399 {
    400     mDefaultAlloc.clear();
    401     mDefault.clear();
    402     mAllocType.clear();
    403     mLast.clear();
    404 }
    405 
    406 
    407 namespace android {
    408 namespace renderscript {
    409 
    410 
    411 RsProgramVertex rsi_ProgramVertexCreate(Context *rsc, bool texMat)
    412 {
    413     ProgramVertex *pv = new ProgramVertex(rsc, texMat);
    414     pv->incUserRef();
    415     return pv;
    416 }
    417 
    418 RsProgramVertex rsi_ProgramVertexCreate2(Context *rsc, const char * shaderText,
    419                              uint32_t shaderLength, const uint32_t * params,
    420                              uint32_t paramLength)
    421 {
    422     ProgramVertex *pv = new ProgramVertex(rsc, shaderText, shaderLength, params, paramLength);
    423     pv->incUserRef();
    424     return pv;
    425 }
    426 
    427 
    428 }
    429 }
    430