rsProgram.cpp revision 8492a70e1265925903c5e2389fd1d185d82c7047
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 "rsProgram.h"
19
20#include <GLES2/gl2.h>
21#include <GLES2/gl2ext.h>
22
23using namespace android;
24using namespace android::renderscript;
25
26
27Program::Program(Context *rsc) : ObjectBase(rsc)
28{
29    mAllocFile = __FILE__;
30    mAllocLine = __LINE__;
31    mDirty = true;
32    mShaderID = 0;
33    mAttribCount = 0;
34    mUniformCount = 0;
35
36    mInputElements = NULL;
37    mOutputElements = NULL;
38    mConstantTypes = NULL;
39    mInputCount = 0;
40    mOutputCount = 0;
41    mConstantCount = 0;
42    mIsValid = false;
43}
44
45Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
46                 const uint32_t * params, uint32_t paramLength) :
47    ObjectBase(rsc)
48{
49    mAllocFile = __FILE__;
50    mAllocLine = __LINE__;
51    mDirty = true;
52    mShaderID = 0;
53    mAttribCount = 0;
54    mUniformCount = 0;
55    mTextureCount = 0;
56
57    mInputCount = 0;
58    mOutputCount = 0;
59    mConstantCount = 0;
60
61    for (uint32_t ct=0; ct < paramLength; ct+=2) {
62        if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
63            mInputCount++;
64        }
65        if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
66            mOutputCount++;
67        }
68        if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
69            mConstantCount++;
70        }
71        if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_COUNT) {
72            mTextureCount = params[ct+1];
73        }
74    }
75
76    mInputElements = new ObjectBaseRef<Element>[mInputCount];
77    mOutputElements = new ObjectBaseRef<Element>[mOutputCount];
78    mConstantTypes = new ObjectBaseRef<Type>[mConstantCount];
79
80    uint32_t input = 0;
81    uint32_t output = 0;
82    uint32_t constant = 0;
83    for (uint32_t ct=0; ct < paramLength; ct+=2) {
84        if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
85            mInputElements[input++].set(reinterpret_cast<Element *>(params[ct+1]));
86        }
87        if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
88            mOutputElements[output++].set(reinterpret_cast<Element *>(params[ct+1]));
89        }
90        if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
91            mConstantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1]));
92        }
93    }
94    mUserShader.setTo(shaderText, shaderLength);
95}
96
97Program::~Program()
98{
99    for (uint32_t ct=0; ct < MAX_UNIFORMS; ct++) {
100        bindAllocation(NULL, ct);
101    }
102
103    delete[] mInputElements;
104    delete[] mOutputElements;
105    delete[] mConstantTypes;
106    mInputCount = 0;
107    mOutputCount = 0;
108    mConstantCount = 0;
109}
110
111
112void Program::bindAllocation(Allocation *alloc, uint32_t slot)
113{
114    if (mConstants[slot].get() == alloc) {
115        return;
116    }
117    if (mConstants[slot].get()) {
118        mConstants[slot].get()->removeProgramToDirty(this);
119    }
120    mConstants[slot].set(alloc);
121    if (alloc) {
122        alloc->addProgramToDirty(this);
123    }
124    mDirty = true;
125}
126
127void Program::bindTexture(uint32_t slot, Allocation *a)
128{
129    if (slot >= MAX_TEXTURE) {
130        LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE");
131        return;
132    }
133
134    //LOGE("bindtex %i %p", slot, a);
135    mTextures[slot].set(a);
136    mDirty = true;
137}
138
139void Program::bindSampler(uint32_t slot, Sampler *s)
140{
141    if (slot >= MAX_TEXTURE) {
142        LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE");
143        return;
144    }
145
146    mSamplers[slot].set(s);
147    mDirty = true;
148}
149
150String8 Program::getGLSLInputString() const
151{
152    String8 s;
153    for (uint32_t ct=0; ct < mInputCount; ct++) {
154        const Element *e = mInputElements[ct].get();
155        for (uint32_t field=0; field < e->getFieldCount(); field++) {
156            const Element *f = e->getField(field);
157
158            // Cannot be complex
159            rsAssert(!f->getFieldCount());
160            switch(f->getComponent().getVectorSize()) {
161            case 1: s.append("attribute float ATTRIB_"); break;
162            case 2: s.append("attribute vec2 ATTRIB_"); break;
163            case 3: s.append("attribute vec3 ATTRIB_"); break;
164            case 4: s.append("attribute vec4 ATTRIB_"); break;
165            default:
166                rsAssert(0);
167            }
168
169            s.append(e->getFieldName(field));
170            s.append(";\n");
171        }
172    }
173    return s;
174}
175
176String8 Program::getGLSLOutputString() const
177{
178    return String8();
179}
180
181String8 Program::getGLSLConstantString() const
182{
183    return String8();
184}
185
186
187void Program::createShader()
188{
189}
190
191bool Program::loadShader(Context *rsc, uint32_t type)
192{
193    mShaderID = glCreateShader(type);
194    rsAssert(mShaderID);
195
196    if (rsc->props.mLogShaders) {
197        LOGV("Loading shader type %x, ID %i", type, mShaderID);
198        LOGV("%s", mShader.string());
199    }
200
201    if (mShaderID) {
202        const char * ss = mShader.string();
203        glShaderSource(mShaderID, 1, &ss, NULL);
204        glCompileShader(mShaderID);
205
206        GLint compiled = 0;
207        glGetShaderiv(mShaderID, GL_COMPILE_STATUS, &compiled);
208        if (!compiled) {
209            GLint infoLen = 0;
210            glGetShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
211            if (infoLen) {
212                char* buf = (char*) malloc(infoLen);
213                if (buf) {
214                    glGetShaderInfoLog(mShaderID, infoLen, NULL, buf);
215                    LOGE("Could not compile shader \n%s\n", buf);
216                    free(buf);
217                }
218                glDeleteShader(mShaderID);
219                mShaderID = 0;
220                rsc->setError(RS_ERROR_BAD_SHADER, "Error returned from GL driver loading shader text,");
221                return false;
222            }
223        }
224    }
225
226    if (rsc->props.mLogShaders) {
227        LOGV("--Shader load result %x ", glGetError());
228    }
229    mIsValid = true;
230    return true;
231}
232
233void Program::setShader(const char *txt, uint32_t len)
234{
235    mUserShader.setTo(txt, len);
236}
237
238
239
240namespace android {
241namespace renderscript {
242
243
244void rsi_ProgramBindConstants(Context *rsc, RsProgram vp, uint32_t slot, RsAllocation constants)
245{
246    Program *p = static_cast<Program *>(vp);
247    p->bindAllocation(static_cast<Allocation *>(constants), slot);
248}
249
250void rsi_ProgramBindTexture(Context *rsc, RsProgram vpf, uint32_t slot, RsAllocation a)
251{
252    Program *p = static_cast<Program *>(vpf);
253    p->bindTexture(slot, static_cast<Allocation *>(a));
254}
255
256void rsi_ProgramBindSampler(Context *rsc, RsProgram vpf, uint32_t slot, RsSampler s)
257{
258    Program *p = static_cast<Program *>(vpf);
259    p->bindSampler(slot, static_cast<Sampler *>(s));
260}
261
262}
263}
264
265