blob: 6041db80b2796d541565661819768a1c75c27087 [file] [log] [blame]
Jason Sams326e0dd2009-05-22 14:03:28 -07001/*
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
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -070017#ifndef ANDROID_RS_BUILD_FOR_HOST
Jason Sams326e0dd2009-05-22 14:03:28 -070018#include "rsContext.h"
Jason Samsc460e552009-11-25 13:22:07 -080019#include <GLES2/gl2.h>
20#include <GLES2/gl2ext.h>
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -070021#else
22#include "rsContextHostStub.h"
23#include <OpenGL/gl.h>
24#include <OpenGL/glext.h>
25#endif //ANDROID_RS_BUILD_FOR_HOST
26
27#include "rsProgram.h"
Jason Samsc460e552009-11-25 13:22:07 -080028
Jason Sams326e0dd2009-05-22 14:03:28 -070029using namespace android;
30using namespace android::renderscript;
31
32
Jason Sams4815c0d2009-12-15 12:58:36 -080033Program::Program(Context *rsc) : ObjectBase(rsc)
Jason Sams326e0dd2009-05-22 14:03:28 -070034{
Jason Samsf2649a92009-09-25 16:37:33 -070035 mAllocFile = __FILE__;
36 mAllocLine = __LINE__;
Jason Samsc460e552009-11-25 13:22:07 -080037 mDirty = true;
38 mShaderID = 0;
39 mAttribCount = 0;
40 mUniformCount = 0;
Jason Samsf2649a92009-09-25 16:37:33 -070041
Jason Sams4815c0d2009-12-15 12:58:36 -080042 mInputElements = NULL;
43 mOutputElements = NULL;
44 mConstantTypes = NULL;
45 mInputCount = 0;
46 mOutputCount = 0;
47 mConstantCount = 0;
Jason Samsa2cf7552010-03-03 13:03:18 -080048 mIsValid = false;
Jason Sams4815c0d2009-12-15 12:58:36 -080049}
50
51Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
52 const uint32_t * params, uint32_t paramLength) :
53 ObjectBase(rsc)
54{
55 mAllocFile = __FILE__;
56 mAllocLine = __LINE__;
57 mDirty = true;
58 mShaderID = 0;
59 mAttribCount = 0;
60 mUniformCount = 0;
Jason Samsf2e4fa22009-12-15 13:27:04 -080061 mTextureCount = 0;
Jason Sams4815c0d2009-12-15 12:58:36 -080062
63 mInputCount = 0;
64 mOutputCount = 0;
65 mConstantCount = 0;
66
67 for (uint32_t ct=0; ct < paramLength; ct+=2) {
68 if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
69 mInputCount++;
70 }
71 if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
72 mOutputCount++;
73 }
74 if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
75 mConstantCount++;
76 }
Jason Samsf2e4fa22009-12-15 13:27:04 -080077 if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_COUNT) {
78 mTextureCount = params[ct+1];
79 }
Jason Sams4815c0d2009-12-15 12:58:36 -080080 }
81
82 mInputElements = new ObjectBaseRef<Element>[mInputCount];
83 mOutputElements = new ObjectBaseRef<Element>[mOutputCount];
84 mConstantTypes = new ObjectBaseRef<Type>[mConstantCount];
85
86 uint32_t input = 0;
87 uint32_t output = 0;
88 uint32_t constant = 0;
89 for (uint32_t ct=0; ct < paramLength; ct+=2) {
90 if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
91 mInputElements[input++].set(reinterpret_cast<Element *>(params[ct+1]));
92 }
93 if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
94 mOutputElements[output++].set(reinterpret_cast<Element *>(params[ct+1]));
95 }
96 if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
97 mConstantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1]));
98 }
99 }
100 mUserShader.setTo(shaderText, shaderLength);
Jason Sams326e0dd2009-05-22 14:03:28 -0700101}
102
103Program::~Program()
104{
Jason Sams9ebb0c42010-01-12 12:12:28 -0800105 for (uint32_t ct=0; ct < MAX_UNIFORMS; ct++) {
106 bindAllocation(NULL, ct);
107 }
Jason Sams4815c0d2009-12-15 12:58:36 -0800108
109 delete[] mInputElements;
110 delete[] mOutputElements;
111 delete[] mConstantTypes;
112 mInputCount = 0;
113 mOutputCount = 0;
114 mConstantCount = 0;
Jason Sams326e0dd2009-05-22 14:03:28 -0700115}
116
117
Jason Sams9ebb0c42010-01-12 12:12:28 -0800118void Program::bindAllocation(Allocation *alloc, uint32_t slot)
Jason Sams326e0dd2009-05-22 14:03:28 -0700119{
Jason Sams9ebb0c42010-01-12 12:12:28 -0800120 if (mConstants[slot].get() == alloc) {
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700121 return;
122 }
Jason Sams9ebb0c42010-01-12 12:12:28 -0800123 if (mConstants[slot].get()) {
124 mConstants[slot].get()->removeProgramToDirty(this);
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700125 }
Jason Sams9ebb0c42010-01-12 12:12:28 -0800126 mConstants[slot].set(alloc);
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700127 if (alloc) {
128 alloc->addProgramToDirty(this);
129 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700130 mDirty = true;
131}
132
Jason Sams7dad9c32009-12-17 16:55:08 -0800133void Program::bindTexture(uint32_t slot, Allocation *a)
134{
135 if (slot >= MAX_TEXTURE) {
136 LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE");
137 return;
138 }
139
140 //LOGE("bindtex %i %p", slot, a);
141 mTextures[slot].set(a);
142 mDirty = true;
143}
144
145void Program::bindSampler(uint32_t slot, Sampler *s)
146{
147 if (slot >= MAX_TEXTURE) {
148 LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE");
149 return;
150 }
151
152 mSamplers[slot].set(s);
153 mDirty = true;
154}
155
Jason Samsb4d35682010-01-04 16:52:27 -0800156String8 Program::getGLSLInputString() const
157{
158 String8 s;
159 for (uint32_t ct=0; ct < mInputCount; ct++) {
160 const Element *e = mInputElements[ct].get();
161 for (uint32_t field=0; field < e->getFieldCount(); field++) {
162 const Element *f = e->getField(field);
163
164 // Cannot be complex
165 rsAssert(!f->getFieldCount());
166 switch(f->getComponent().getVectorSize()) {
167 case 1: s.append("attribute float ATTRIB_"); break;
168 case 2: s.append("attribute vec2 ATTRIB_"); break;
169 case 3: s.append("attribute vec3 ATTRIB_"); break;
170 case 4: s.append("attribute vec4 ATTRIB_"); break;
171 default:
172 rsAssert(0);
173 }
174
175 s.append(e->getFieldName(field));
176 s.append(";\n");
177 }
178 }
179 return s;
180}
181
182String8 Program::getGLSLOutputString() const
183{
184 return String8();
185}
186
187String8 Program::getGLSLConstantString() const
188{
189 return String8();
190}
191
Jason Sams7dad9c32009-12-17 16:55:08 -0800192
Jason Samsc460e552009-11-25 13:22:07 -0800193void Program::createShader()
194{
195}
Jason Samscfb1d112009-08-05 13:57:03 -0700196
Jason Samscd506532009-12-15 19:10:11 -0800197bool Program::loadShader(Context *rsc, uint32_t type)
Jason Samsc460e552009-11-25 13:22:07 -0800198{
199 mShaderID = glCreateShader(type);
200 rsAssert(mShaderID);
201
Jason Samscd506532009-12-15 19:10:11 -0800202 if (rsc->props.mLogShaders) {
203 LOGV("Loading shader type %x, ID %i", type, mShaderID);
Nick Kralevich8492a702010-05-13 14:46:27 -0700204 LOGV("%s", mShader.string());
Jason Samscd506532009-12-15 19:10:11 -0800205 }
Jason Samsc460e552009-11-25 13:22:07 -0800206
207 if (mShaderID) {
208 const char * ss = mShader.string();
209 glShaderSource(mShaderID, 1, &ss, NULL);
210 glCompileShader(mShaderID);
211
212 GLint compiled = 0;
213 glGetShaderiv(mShaderID, GL_COMPILE_STATUS, &compiled);
214 if (!compiled) {
215 GLint infoLen = 0;
216 glGetShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
217 if (infoLen) {
218 char* buf = (char*) malloc(infoLen);
219 if (buf) {
220 glGetShaderInfoLog(mShaderID, infoLen, NULL, buf);
221 LOGE("Could not compile shader \n%s\n", buf);
222 free(buf);
223 }
224 glDeleteShader(mShaderID);
225 mShaderID = 0;
Jason Samsa2cf7552010-03-03 13:03:18 -0800226 rsc->setError(RS_ERROR_BAD_SHADER, "Error returned from GL driver loading shader text,");
Jason Samsc460e552009-11-25 13:22:07 -0800227 return false;
228 }
229 }
230 }
Jason Samscd506532009-12-15 19:10:11 -0800231
232 if (rsc->props.mLogShaders) {
233 LOGV("--Shader load result %x ", glGetError());
234 }
Jason Samsa2cf7552010-03-03 13:03:18 -0800235 mIsValid = true;
Jason Samsc460e552009-11-25 13:22:07 -0800236 return true;
237}
Jason Samsf2a5d732009-11-30 14:49:55 -0800238
239void Program::setShader(const char *txt, uint32_t len)
240{
241 mUserShader.setTo(txt, len);
242}
243
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700244void Program::appendUserConstants() {
245 for (uint32_t ct=0; ct < mConstantCount; ct++) {
246 const Element *e = mConstantTypes[ct]->getElement();
247 for (uint32_t field=0; field < e->getFieldCount(); field++) {
248 const Element *f = e->getField(field);
249 const char *fn = e->getFieldName(field);
Jason Sams4815c0d2009-12-15 12:58:36 -0800250
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700251 if (fn[0] == '#') {
252 continue;
253 }
254
255 // Cannot be complex
256 rsAssert(!f->getFieldCount());
257 if(f->getType() == RS_TYPE_MATRIX_4X4) {
258 mShader.append("uniform mat4 UNI_");
259 }
260 else if(f->getType() == RS_TYPE_MATRIX_3X3) {
261 mShader.append("uniform mat3 UNI_");
262 }
263 else if(f->getType() == RS_TYPE_MATRIX_2X2) {
264 mShader.append("uniform mat2 UNI_");
265 }
266 else {
267 switch(f->getComponent().getVectorSize()) {
268 case 1: mShader.append("uniform float UNI_"); break;
269 case 2: mShader.append("uniform vec2 UNI_"); break;
270 case 3: mShader.append("uniform vec3 UNI_"); break;
271 case 4: mShader.append("uniform vec4 UNI_"); break;
272 default:
273 rsAssert(0);
274 }
275 }
276
277 mShader.append(fn);
278 mShader.append(";\n");
279 }
280 }
281}
282
283void Program::setupUserConstants(ShaderCache *sc, bool isFragment) {
284 uint32_t uidx = 1;
285 for (uint32_t ct=0; ct < mConstantCount; ct++) {
286 Allocation *alloc = mConstants[ct+1].get();
287 if (!alloc) {
288 continue;
289 }
290
291 const uint8_t *data = static_cast<const uint8_t *>(alloc->getPtr());
292 const Element *e = mConstantTypes[ct]->getElement();
293 for (uint32_t field=0; field < e->getFieldCount(); field++) {
294 const Element *f = e->getField(field);
295 const char *fieldName = e->getFieldName(field);
296 // If this field is padding, skip it
297 if(fieldName[0] == '#') {
298 continue;
299 }
300
301 uint32_t offset = e->getFieldOffsetBytes(field);
302 const float *fd = reinterpret_cast<const float *>(&data[offset]);
303
304 int32_t slot = -1;
305 if(!isFragment) {
306 slot = sc->vtxUniformSlot(uidx);
307 }
308 else {
309 slot = sc->fragUniformSlot(uidx);
310 }
311
312 //LOGE("Uniform slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s", slot, offset, ct, field, uidx, fieldName);
313 if (slot >= 0) {
314 if(f->getType() == RS_TYPE_MATRIX_4X4) {
315 glUniformMatrix4fv(slot, 1, GL_FALSE, fd);
316 }
317 else if(f->getType() == RS_TYPE_MATRIX_3X3) {
318 glUniformMatrix3fv(slot, 1, GL_FALSE, fd);
319 }
320 else if(f->getType() == RS_TYPE_MATRIX_2X2) {
321 glUniformMatrix2fv(slot, 1, GL_FALSE, fd);
322 }
323 else {
324 switch(f->getComponent().getVectorSize()) {
325 case 1:
326 //LOGE("Uniform 1 = %f", fd[0]);
327 glUniform1fv(slot, 1, fd);
328 break;
329 case 2:
330 //LOGE("Uniform 2 = %f %f", fd[0], fd[1]);
331 glUniform2fv(slot, 1, fd);
332 break;
333 case 3:
334 //LOGE("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
335 glUniform3fv(slot, 1, fd);
336 break;
337 case 4:
338 //LOGE("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
339 glUniform4fv(slot, 1, fd);
340 break;
341 default:
342 rsAssert(0);
343 }
344 }
345 }
346 uidx ++;
347 }
348 }
349}
350
351void Program::initAddUserElement(const Element *e, String8 *names, uint32_t *count, const char *prefix)
352{
353 rsAssert(e->getFieldCount());
354 for (uint32_t ct=0; ct < e->getFieldCount(); ct++) {
355 const Element *ce = e->getField(ct);
356 if (ce->getFieldCount()) {
357 initAddUserElement(ce, names, count, prefix);
358 }
359 else if(e->getFieldName(ct)[0] != '#') {
360 String8 tmp(prefix);
361 tmp.append(e->getFieldName(ct));
362 names[*count].setTo(tmp.string());
363 (*count)++;
364 }
365 }
366}
Jason Sams4815c0d2009-12-15 12:58:36 -0800367
368namespace android {
369namespace renderscript {
370
371
372void rsi_ProgramBindConstants(Context *rsc, RsProgram vp, uint32_t slot, RsAllocation constants)
373{
374 Program *p = static_cast<Program *>(vp);
Jason Sams9ebb0c42010-01-12 12:12:28 -0800375 p->bindAllocation(static_cast<Allocation *>(constants), slot);
Jason Sams4815c0d2009-12-15 12:58:36 -0800376}
377
Jason Sams7dad9c32009-12-17 16:55:08 -0800378void rsi_ProgramBindTexture(Context *rsc, RsProgram vpf, uint32_t slot, RsAllocation a)
379{
380 Program *p = static_cast<Program *>(vpf);
381 p->bindTexture(slot, static_cast<Allocation *>(a));
382}
383
384void rsi_ProgramBindSampler(Context *rsc, RsProgram vpf, uint32_t slot, RsSampler s)
385{
386 Program *p = static_cast<Program *>(vpf);
387 p->bindSampler(slot, static_cast<Sampler *>(s));
388}
Jason Sams4815c0d2009-12-15 12:58:36 -0800389
390}
391}
392