rsProgram.cpp revision 7dad9c30a59c99b57269e1b498807b6f034d56e9
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}
43
44Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
45                 const uint32_t * params, uint32_t paramLength) :
46    ObjectBase(rsc)
47{
48    mAllocFile = __FILE__;
49    mAllocLine = __LINE__;
50    mDirty = true;
51    mShaderID = 0;
52    mAttribCount = 0;
53    mUniformCount = 0;
54    mTextureCount = 0;
55
56    mInputCount = 0;
57    mOutputCount = 0;
58    mConstantCount = 0;
59
60    for (uint32_t ct=0; ct < paramLength; ct+=2) {
61        if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
62            mInputCount++;
63        }
64        if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
65            mOutputCount++;
66        }
67        if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
68            mConstantCount++;
69        }
70        if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_COUNT) {
71            mTextureCount = params[ct+1];
72        }
73    }
74
75    mInputElements = new ObjectBaseRef<Element>[mInputCount];
76    mOutputElements = new ObjectBaseRef<Element>[mOutputCount];
77    mConstantTypes = new ObjectBaseRef<Type>[mConstantCount];
78
79    uint32_t input = 0;
80    uint32_t output = 0;
81    uint32_t constant = 0;
82    for (uint32_t ct=0; ct < paramLength; ct+=2) {
83        if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
84            mInputElements[input++].set(reinterpret_cast<Element *>(params[ct+1]));
85        }
86        if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
87            mOutputElements[output++].set(reinterpret_cast<Element *>(params[ct+1]));
88        }
89        if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
90            mConstantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1]));
91        }
92    }
93    mUserShader.setTo(shaderText, shaderLength);
94}
95
96Program::~Program()
97{
98    bindAllocation(NULL);
99
100    delete[] mInputElements;
101    delete[] mOutputElements;
102    delete[] mConstantTypes;
103    mInputCount = 0;
104    mOutputCount = 0;
105    mConstantCount = 0;
106}
107
108
109void Program::bindAllocation(Allocation *alloc)
110{
111    if (mConstants.get() == alloc) {
112        return;
113    }
114    if (mConstants.get()) {
115        mConstants.get()->removeProgramToDirty(this);
116    }
117    mConstants.set(alloc);
118    if (alloc) {
119        alloc->addProgramToDirty(this);
120    }
121    mDirty = true;
122}
123
124void Program::bindTexture(uint32_t slot, Allocation *a)
125{
126    if (slot >= MAX_TEXTURE) {
127        LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE");
128        return;
129    }
130
131    //LOGE("bindtex %i %p", slot, a);
132    mTextures[slot].set(a);
133    mDirty = true;
134}
135
136void Program::bindSampler(uint32_t slot, Sampler *s)
137{
138    if (slot >= MAX_TEXTURE) {
139        LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE");
140        return;
141    }
142
143    mSamplers[slot].set(s);
144    mDirty = true;
145}
146
147
148void Program::createShader()
149{
150}
151
152bool Program::loadShader(Context *rsc, uint32_t type)
153{
154    mShaderID = glCreateShader(type);
155    rsAssert(mShaderID);
156
157    if (rsc->props.mLogShaders) {
158        LOGV("Loading shader type %x, ID %i", type, mShaderID);
159        LOGV(mShader.string());
160    }
161
162    if (mShaderID) {
163        const char * ss = mShader.string();
164        glShaderSource(mShaderID, 1, &ss, NULL);
165        glCompileShader(mShaderID);
166
167        GLint compiled = 0;
168        glGetShaderiv(mShaderID, GL_COMPILE_STATUS, &compiled);
169        if (!compiled) {
170            GLint infoLen = 0;
171            glGetShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
172            if (infoLen) {
173                char* buf = (char*) malloc(infoLen);
174                if (buf) {
175                    glGetShaderInfoLog(mShaderID, infoLen, NULL, buf);
176                    LOGE("Could not compile shader \n%s\n", buf);
177                    free(buf);
178                }
179                glDeleteShader(mShaderID);
180                mShaderID = 0;
181                return false;
182            }
183        }
184    }
185
186    if (rsc->props.mLogShaders) {
187        LOGV("--Shader load result %x ", glGetError());
188    }
189    return true;
190}
191
192void Program::setShader(const char *txt, uint32_t len)
193{
194    mUserShader.setTo(txt, len);
195}
196
197
198
199namespace android {
200namespace renderscript {
201
202
203void rsi_ProgramBindConstants(Context *rsc, RsProgram vp, uint32_t slot, RsAllocation constants)
204{
205    Program *p = static_cast<Program *>(vp);
206    p->bindAllocation(static_cast<Allocation *>(constants));
207}
208
209void rsi_ProgramBindTexture(Context *rsc, RsProgram vpf, uint32_t slot, RsAllocation a)
210{
211    Program *p = static_cast<Program *>(vpf);
212    p->bindTexture(slot, static_cast<Allocation *>(a));
213}
214
215void rsi_ProgramBindSampler(Context *rsc, RsProgram vpf, uint32_t slot, RsSampler s)
216{
217    Program *p = static_cast<Program *>(vpf);
218    p->bindSampler(slot, static_cast<Sampler *>(s));
219}
220
221}
222}
223
224