rsProgramVertex.cpp revision f0c1df480304a72ce41e7d4b088319cbd7f0938a
1e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk/*
2e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Copyright (C) 2009 The Android Open Source Project
3e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk *
4e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License");
5e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * you may not use this file except in compliance with the License.
6e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * You may obtain a copy of the License at
7e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk *
8e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk *      http://www.apache.org/licenses/LICENSE-2.0
9e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk *
10e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Unless required by applicable law or agreed to in writing, software
11e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS,
12e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * See the License for the specific language governing permissions and
14e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * limitations under the License.
15e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk */
16e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
17e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#ifndef ANDROID_RS_BUILD_FOR_HOST
18e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include "rsContext.h"
19e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include <GLES/gl.h>
20e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include <GLES/glext.h>
21e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include <GLES2/gl2.h>
22e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include <GLES2/gl2ext.h>
23e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#else
24e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include "rsContextHostStub.h"
25e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include <OpenGL/gl.h>
26e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include <OpenGL/glext.h>
27e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#endif //ANDROID_RS_BUILD_FOR_HOST
28e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
29e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include "rsProgramVertex.h"
30e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
31e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkusing namespace android;
32e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkusing namespace android::renderscript;
33e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
34e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
35e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben BrunkProgramVertex::ProgramVertex(Context *rsc, const char * shaderText,
36e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                             uint32_t shaderLength, const uint32_t * params,
37e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                             uint32_t paramLength) :
38e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    Program(rsc, shaderText, shaderLength, params, paramLength)
39e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk{
40e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    init(rsc);
41e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
42e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
43e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben BrunkProgramVertex::~ProgramVertex()
44e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk{
45    if(mShaderID) {
46        mRSC->mShaderCache.cleanupVertex(mShaderID);
47    }
48}
49
50void ProgramVertex::loadShader(Context *rsc) {
51    Program::loadShader(rsc, GL_VERTEX_SHADER);
52}
53
54void ProgramVertex::createShader()
55{
56    if (mUserShader.length() > 1) {
57
58        appendUserConstants();
59
60        for (uint32_t ct=0; ct < mInputCount; ct++) {
61            const Element *e = mInputElements[ct].get();
62            for (uint32_t field=0; field < e->getFieldCount(); field++) {
63                const Element *f = e->getField(field);
64                const char *fn = e->getFieldName(field);
65
66                if (fn[0] == '#') {
67                    continue;
68                }
69
70                // Cannot be complex
71                rsAssert(!f->getFieldCount());
72                switch(f->getComponent().getVectorSize()) {
73                case 1: mShader.append("attribute float ATTRIB_"); break;
74                case 2: mShader.append("attribute vec2 ATTRIB_"); break;
75                case 3: mShader.append("attribute vec3 ATTRIB_"); break;
76                case 4: mShader.append("attribute vec4 ATTRIB_"); break;
77                default:
78                    rsAssert(0);
79                }
80
81                mShader.append(fn);
82                mShader.append(";\n");
83            }
84        }
85        mShader.append(mUserShader);
86    } else {
87        LOGE("ProgramFragment::createShader cannot create program, shader code not defined");
88        rsAssert(0);
89    }
90}
91
92void ProgramVertex::setupGL2(Context *rsc, ProgramVertexState *state, ShaderCache *sc)
93{
94    //LOGE("sgl2 vtx1 %x", glGetError());
95    if ((state->mLast.get() == this) && !mDirty) {
96        return;
97    }
98
99    rsc->checkError("ProgramVertex::setupGL2 start");
100
101    if(!isUserProgram()) {
102        if(mConstants[0].get() == NULL) {
103            LOGE("Unable to set fixed function emulation matrices because allocation is missing");
104            rsc->setError(RS_ERROR_BAD_SHADER, "Fixed function allocation missing");
105            return;
106        }
107        float *f = static_cast<float *>(mConstants[0]->getPtr());
108        Matrix mvp;
109        mvp.load(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
110        Matrix t;
111        t.load(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET]);
112        mvp.multiply(&t);
113        for(uint32_t i = 0; i < 16; i ++) {
114            f[RS_PROGRAM_VERTEX_MVP_OFFSET + i] = mvp.m[i];
115        }
116    }
117
118    rsc->checkError("ProgramVertex::setupGL2 begin uniforms");
119    setupUserConstants(rsc, sc, false);
120
121    state->mLast.set(this);
122    rsc->checkError("ProgramVertex::setupGL2");
123}
124
125void ProgramVertex::setProjectionMatrix(Context *rsc, const rsc_Matrix *m) const
126{
127    if(isUserProgram()) {
128        LOGE("Attempting to set fixed function emulation matrix projection on user program");
129        rsc->setError(RS_ERROR_BAD_SHADER, "Cannot set emulation matrix on user shader");
130        return;
131    }
132    if(mConstants[0].get() == NULL) {
133        LOGE("Unable to set fixed function emulation matrix projection because allocation is missing");
134        return;
135    }
136    float *f = static_cast<float *>(mConstants[0]->getPtr());
137    memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m, sizeof(rsc_Matrix));
138    mDirty = true;
139}
140
141void ProgramVertex::setModelviewMatrix(Context *rsc, const rsc_Matrix *m) const
142{
143    if(isUserProgram()) {
144        LOGE("Attempting to set fixed function emulation matrix modelview on user program");
145        rsc->setError(RS_ERROR_BAD_SHADER, "Cannot set emulation matrix on user shader");
146        return;
147    }
148    if(mConstants[0].get() == NULL) {
149        LOGE("Unable to set fixed function emulation matrix modelview because allocation is missing");
150        rsc->setError(RS_ERROR_BAD_SHADER, "Fixed function allocation missing");
151        return;
152    }
153    float *f = static_cast<float *>(mConstants[0]->getPtr());
154    memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m, sizeof(rsc_Matrix));
155    mDirty = true;
156}
157
158void ProgramVertex::setTextureMatrix(Context *rsc, const rsc_Matrix *m) const
159{
160    if(isUserProgram()) {
161        LOGE("Attempting to set fixed function emulation matrix texture on user program");
162        rsc->setError(RS_ERROR_BAD_SHADER, "Cannot set emulation matrix on user shader");
163        return;
164    }
165    if(mConstants[0].get() == NULL) {
166        LOGE("Unable to set fixed function emulation matrix texture because allocation is missing");
167        rsc->setError(RS_ERROR_BAD_SHADER, "Fixed function allocation missing");
168        return;
169    }
170    float *f = static_cast<float *>(mConstants[0]->getPtr());
171    memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m, sizeof(rsc_Matrix));
172    mDirty = true;
173}
174
175void ProgramVertex::getProjectionMatrix(Context *rsc, rsc_Matrix *m) const
176{
177    if(isUserProgram()) {
178        LOGE("Attempting to get fixed function emulation matrix projection on user program");
179        rsc->setError(RS_ERROR_BAD_SHADER, "Cannot get emulation matrix on user shader");
180        return;
181    }
182    if(mConstants[0].get() == NULL) {
183        LOGE("Unable to get fixed function emulation matrix projection because allocation is missing");
184        rsc->setError(RS_ERROR_BAD_SHADER, "Fixed function allocation missing");
185        return;
186    }
187    float *f = static_cast<float *>(mConstants[0]->getPtr());
188    memcpy(m, &f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], sizeof(rsc_Matrix));
189}
190
191void ProgramVertex::transformToScreen(Context *rsc, float *v4out, const float *v3in) const
192{
193    if(isUserProgram()) {
194        return;
195    }
196    float *f = static_cast<float *>(mConstants[0]->getPtr());
197    Matrix mvp;
198    mvp.loadMultiply((Matrix *)&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET],
199                     (Matrix *)&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
200    mvp.vectorMultiply(v4out, v3in);
201}
202
203void ProgramVertex::init(Context *rsc)
204{
205    mAttribCount = 0;
206    if (mUserShader.size() > 0) {
207        for (uint32_t ct=0; ct < mInputCount; ct++) {
208            initAddUserElement(mInputElements[ct].get(), mAttribNames, &mAttribCount, RS_SHADER_ATTR);
209        }
210        mUniformCount = 0;
211        for (uint32_t ct=0; ct < mConstantCount; ct++) {
212            initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, &mUniformCount, RS_SHADER_UNI);
213        }
214    }
215    createShader();
216}
217
218void ProgramVertex::serialize(OStream *stream) const
219{
220
221}
222
223ProgramVertex *ProgramVertex::createFromStream(Context *rsc, IStream *stream)
224{
225    return NULL;
226}
227
228
229///////////////////////////////////////////////////////////////////////
230
231ProgramVertexState::ProgramVertexState()
232{
233}
234
235ProgramVertexState::~ProgramVertexState()
236{
237}
238
239void ProgramVertexState::init(Context *rsc)
240{
241    const Element *matrixElem = Element::create(rsc, RS_TYPE_MATRIX_4X4, RS_KIND_USER, false, 1);
242    const Element *f2Elem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2);
243    const Element *f3Elem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3);
244    const Element *f4Elem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4);
245
246    rsc->mStateElement.elementBuilderBegin();
247    rsc->mStateElement.elementBuilderAdd(matrixElem, "MV", 1);
248    rsc->mStateElement.elementBuilderAdd(matrixElem, "P", 1);
249    rsc->mStateElement.elementBuilderAdd(matrixElem, "TexMatrix", 1);
250    rsc->mStateElement.elementBuilderAdd(matrixElem, "MVP", 1);
251    const Element *constInput = rsc->mStateElement.elementBuilderCreate(rsc);
252
253    rsc->mStateElement.elementBuilderBegin();
254    rsc->mStateElement.elementBuilderAdd(f4Elem, "position", 1);
255    rsc->mStateElement.elementBuilderAdd(f4Elem, "color", 1);
256    rsc->mStateElement.elementBuilderAdd(f3Elem, "normal", 1);
257    rsc->mStateElement.elementBuilderAdd(f2Elem, "texture0", 1);
258    const Element *attrElem = rsc->mStateElement.elementBuilderCreate(rsc);
259
260    Type *inputType = Type::getType(rsc, constInput, 1, 0, 0, false, false);
261
262    String8 shaderString(RS_SHADER_INTERNAL);
263    shaderString.append("varying vec4 varColor;\n");
264    shaderString.append("varying vec2 varTex0;\n");
265    shaderString.append("void main() {\n");
266    shaderString.append("  gl_Position = UNI_MVP * ATTRIB_position;\n");
267    shaderString.append("  gl_PointSize = 1.0;\n");
268    shaderString.append("  varColor = ATTRIB_color;\n");
269    shaderString.append("  varTex0 = ATTRIB_texture0;\n");
270    shaderString.append("}\n");
271
272    uint32_t tmp[6];
273    tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
274    tmp[1] = (uint32_t)inputType;
275    tmp[2] = RS_PROGRAM_PARAM_INPUT;
276    tmp[3] = (uint32_t)attrElem;
277    tmp[4] = RS_PROGRAM_PARAM_TEXTURE_COUNT;
278    tmp[5] = 0;
279
280    ProgramVertex *pv = new ProgramVertex(rsc, shaderString.string(),
281                                          shaderString.length(), tmp, 6);
282    Allocation *alloc = new Allocation(rsc, inputType);
283    pv->bindAllocation(rsc, alloc, 0);
284
285    mDefaultAlloc.set(alloc);
286    mDefault.set(pv);
287
288    updateSize(rsc);
289
290}
291
292void ProgramVertexState::updateSize(Context *rsc)
293{
294    float *f = static_cast<float *>(mDefaultAlloc->getPtr());
295
296    Matrix m;
297    m.loadOrtho(0,rsc->getWidth(), rsc->getHeight(),0, -1,1);
298    memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m.m, sizeof(m));
299    memcpy(&f[RS_PROGRAM_VERTEX_MVP_OFFSET], m.m, sizeof(m));
300
301    m.loadIdentity();
302    memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m.m, sizeof(m));
303    memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m.m, sizeof(m));
304}
305
306void ProgramVertexState::deinit(Context *rsc)
307{
308    mDefaultAlloc.clear();
309    mDefault.clear();
310    mLast.clear();
311}
312
313
314namespace android {
315namespace renderscript {
316
317RsProgramVertex rsi_ProgramVertexCreate(Context *rsc, const char * shaderText,
318                             uint32_t shaderLength, const uint32_t * params,
319                             uint32_t paramLength)
320{
321    ProgramVertex *pv = new ProgramVertex(rsc, shaderText, shaderLength, params, paramLength);
322    pv->incUserRef();
323    return pv;
324}
325
326
327}
328}
329