rsProgramVertex.cpp revision 9ebb0c44ece47531f3d0a98ba52ae448de42032b
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
25using namespace android;
26using namespace android::renderscript;
27
28
29ProgramVertex::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
39ProgramVertex::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
52ProgramVertex::~ProgramVertex()
53{
54}
55
56static 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
65void 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
111void ProgramVertex::loadShader(Context *rsc) {
112    Program::loadShader(rsc, GL_VERTEX_SHADER);
113}
114
115void 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        LOGE("constant %i ", mConstantCount);
128        for (uint32_t ct=0; ct < mConstantCount; ct++) {
129            const Element *e = mConstantTypes[ct]->getElement();
130            for (uint32_t field=0; field < e->getFieldCount(); field++) {
131                const Element *f = e->getField(field);
132
133                // Cannot be complex
134                rsAssert(!f->getFieldCount());
135                switch(f->getComponent().getVectorSize()) {
136                case 1: mShader.append("uniform float UNI_"); break;
137                case 2: mShader.append("uniform vec2 UNI_"); break;
138                case 3: mShader.append("uniform vec3 UNI_"); break;
139                case 4: mShader.append("uniform vec4 UNI_"); break;
140                default:
141                    rsAssert(0);
142                }
143
144                mShader.append(e->getFieldName(field));
145                mShader.append(";\n");
146            }
147        }
148
149
150        for (uint32_t ct=0; ct < mInputCount; ct++) {
151            const Element *e = mInputElements[ct].get();
152            for (uint32_t field=0; field < e->getFieldCount(); field++) {
153                const Element *f = e->getField(field);
154
155                // Cannot be complex
156                rsAssert(!f->getFieldCount());
157                switch(f->getComponent().getVectorSize()) {
158                case 1: mShader.append("attribute float ATTRIB_"); break;
159                case 2: mShader.append("attribute vec2 ATTRIB_"); break;
160                case 3: mShader.append("attribute vec3 ATTRIB_"); break;
161                case 4: mShader.append("attribute vec4 ATTRIB_"); break;
162                default:
163                    rsAssert(0);
164                }
165
166                mShader.append(e->getFieldName(field));
167                mShader.append(";\n");
168            }
169        }
170        mShader.append(mUserShader);
171    } else {
172        for (uint32_t ct=0; ct < mUniformCount; ct++) {
173            mShader.append("uniform mat4 ");
174            mShader.append(mUniformNames[ct]);
175            mShader.append(";\n");
176        }
177
178        for (uint32_t ct=VertexArray::POSITION; ct < mAttribCount; ct++) {
179            mShader.append("attribute vec4 ");
180            mShader.append(mAttribNames[ct]);
181            mShader.append(";\n");
182        }
183
184        mShader.append("void main() {\n");
185        mShader.append("  gl_Position = UNI_MVP * ATTRIB_Position;\n");
186        mShader.append("  gl_PointSize = ATTRIB_PointSize.x;\n");
187
188        mShader.append("  varColor = ATTRIB_Color;\n");
189        if (mTextureMatrixEnable) {
190            mShader.append("  varTex0 = UNI_TexMatrix * ATTRIB_Texture;\n");
191        } else {
192            mShader.append("  varTex0 = ATTRIB_Texture;\n");
193        }
194        //mShader.append("  pos.x = pos.x / 480.0;\n");
195        //mShader.append("  pos.y = pos.y / 800.0;\n");
196        //mShader.append("  gl_Position = pos;\n");
197        mShader.append("}\n");
198    }
199}
200
201void ProgramVertex::setupGL2(const Context *rsc, ProgramVertexState *state, ShaderCache *sc)
202{
203    //LOGE("sgl2 vtx1 %x", glGetError());
204    if ((state->mLast.get() == this) && !mDirty) {
205        //return;
206    }
207
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    uint32_t uidx = 1;
225    for (uint32_t ct=0; ct < mConstantCount; ct++) {
226        Allocation *alloc = mConstants[ct+1].get();
227        if (!alloc) {
228            continue;
229        }
230
231        const uint8_t *data = static_cast<const uint8_t *>(alloc->getPtr());
232        const Element *e = mConstantTypes[ct]->getElement();
233        for (uint32_t field=0; field < e->getFieldCount(); field++) {
234            const Element *f = e->getField(field);
235            uint32_t offset = e->getFieldOffsetBytes(field);
236            int32_t slot = sc->vtxUniformSlot(uidx);
237
238            const float *fd = reinterpret_cast<const float *>(&data[offset]);
239
240            //LOGE("Uniform  slot=%i, offset=%i, constant=%i, field=%i, uidx=%i", slot, offset, ct, field, uidx);
241            if (slot >= 0) {
242                switch(f->getComponent().getVectorSize()) {
243                case 1:
244                    //LOGE("Uniform 1 = %f", fd[0]);
245                    glUniform1fv(slot, 1, fd);
246                    break;
247                case 2:
248                    //LOGE("Uniform 2 = %f %f", fd[0], fd[1]);
249                    glUniform2fv(slot, 1, fd);
250                    break;
251                case 3:
252                    //LOGE("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
253                    glUniform3fv(slot, 1, fd);
254                    break;
255                case 4:
256                    //LOGE("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
257                    glUniform4fv(slot, 1, fd);
258                    break;
259                default:
260                    rsAssert(0);
261                }
262            }
263            uidx ++;
264        }
265    }
266
267    for (uint32_t ct=0; ct < mConstantCount; ct++) {
268        uint32_t glSlot = sc->vtxUniformSlot(ct + 1);
269
270    }
271
272    state->mLast.set(this);
273    rsc->checkError("ProgramVertex::setupGL2");
274}
275
276void ProgramVertex::addLight(const Light *l)
277{
278    if (mLightCount < MAX_LIGHTS) {
279        mLights[mLightCount].set(l);
280        mLightCount++;
281    }
282}
283
284void ProgramVertex::setProjectionMatrix(const rsc_Matrix *m) const
285{
286    float *f = static_cast<float *>(mConstants[0]->getPtr());
287    memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m, sizeof(rsc_Matrix));
288    mDirty = true;
289}
290
291void ProgramVertex::setModelviewMatrix(const rsc_Matrix *m) const
292{
293    float *f = static_cast<float *>(mConstants[0]->getPtr());
294    memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m, sizeof(rsc_Matrix));
295    mDirty = true;
296}
297
298void ProgramVertex::setTextureMatrix(const rsc_Matrix *m) const
299{
300    float *f = static_cast<float *>(mConstants[0]->getPtr());
301    memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m, sizeof(rsc_Matrix));
302    mDirty = true;
303}
304
305void ProgramVertex::transformToScreen(const Context *rsc, float *v4out, const float *v3in) const
306{
307    float *f = static_cast<float *>(mConstants[0]->getPtr());
308    Matrix mvp;
309    mvp.loadMultiply((Matrix *)&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET],
310                     (Matrix *)&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
311    mvp.vectorMultiply(v4out, v3in);
312}
313
314void ProgramVertex::initAddUserElement(const Element *e, String8 *names, uint32_t *count, const char *prefix)
315{
316    rsAssert(e->getFieldCount());
317    for (uint32_t ct=0; ct < e->getFieldCount(); ct++) {
318        const Element *ce = e->getField(ct);
319        if (ce->getFieldCount()) {
320            initAddUserElement(ce, names, count, prefix);
321        } else {
322            String8 tmp(prefix);
323            tmp.append(e->getFieldName(ct));
324            names[*count].setTo(tmp.string());
325            (*count)++;
326        }
327    }
328}
329
330void ProgramVertex::init(Context *rsc)
331{
332    if (mUserShader.size() > 0) {
333        mAttribCount = 0;
334        for (uint32_t ct=0; ct < mInputCount; ct++) {
335            initAddUserElement(mInputElements[ct].get(), mAttribNames, &mAttribCount, "ATTRIB_");
336        }
337
338        mUniformCount = 1;
339        mUniformNames[0].setTo("UNI_MVP");
340        for (uint32_t ct=0; ct < mInputCount; ct++) {
341            initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, &mUniformCount, "UNI_");
342        }
343    } else {
344        mAttribCount = 5;
345        mAttribNames[0].setTo("ATTRIB_Position");
346        mAttribNames[1].setTo("ATTRIB_Color");
347        mAttribNames[2].setTo("ATTRIB_Normal");
348        mAttribNames[3].setTo("ATTRIB_PointSize");
349        mAttribNames[4].setTo("ATTRIB_Texture");
350
351        mUniformCount = 2;
352        mUniformNames[0].setTo("UNI_MVP");
353        mUniformNames[1].setTo("UNI_TexMatrix");
354    }
355
356    createShader();
357}
358
359
360///////////////////////////////////////////////////////////////////////
361
362ProgramVertexState::ProgramVertexState()
363{
364}
365
366ProgramVertexState::~ProgramVertexState()
367{
368}
369
370void ProgramVertexState::init(Context *rsc, int32_t w, int32_t h)
371{
372    RsElement e = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1);
373
374    rsi_TypeBegin(rsc, e);
375    rsi_TypeAdd(rsc, RS_DIMENSION_X, 48);
376    mAllocType.set((Type *)rsi_TypeCreate(rsc));
377
378    ProgramVertex *pv = new ProgramVertex(rsc, false);
379    Allocation *alloc = (Allocation *)rsi_AllocationCreateTyped(rsc, mAllocType.get());
380    mDefaultAlloc.set(alloc);
381    mDefault.set(pv);
382    pv->init(rsc);
383    pv->bindAllocation(alloc, 0);
384
385    color[0] = 1.f;
386    color[1] = 1.f;
387    color[2] = 1.f;
388    color[3] = 1.f;
389
390    updateSize(rsc, w, h);
391}
392
393void ProgramVertexState::updateSize(Context *rsc, int32_t w, int32_t h)
394{
395    Matrix m;
396    m.loadOrtho(0,w, h,0, -1,1);
397    mDefaultAlloc->subData(RS_PROGRAM_VERTEX_PROJECTION_OFFSET, 16, &m.m[0], 16*4);
398
399    m.loadIdentity();
400    mDefaultAlloc->subData(RS_PROGRAM_VERTEX_MODELVIEW_OFFSET, 16, &m.m[0], 16*4);
401}
402
403void ProgramVertexState::deinit(Context *rsc)
404{
405    mDefaultAlloc.clear();
406    mDefault.clear();
407    mAllocType.clear();
408    mLast.clear();
409}
410
411
412namespace android {
413namespace renderscript {
414
415
416RsProgramVertex rsi_ProgramVertexCreate(Context *rsc, bool texMat)
417{
418    ProgramVertex *pv = new ProgramVertex(rsc, texMat);
419    pv->incUserRef();
420    return pv;
421}
422
423RsProgramVertex rsi_ProgramVertexCreate2(Context *rsc, const char * shaderText,
424                             uint32_t shaderLength, const uint32_t * params,
425                             uint32_t paramLength)
426{
427    ProgramVertex *pv = new ProgramVertex(rsc, shaderText, shaderLength, params, paramLength);
428    pv->incUserRef();
429    return pv;
430}
431
432
433}
434}
435