blob: 39b85e39ed3f72215171ca8b717ccda073ba81f4 [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
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080032Program::Program(Context *rsc) : ObjectBase(rsc) {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -080033 initMemberVars();
Jason Sams4815c0d2009-12-15 12:58:36 -080034}
35
36Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080037 const uint32_t * params, uint32_t paramLength)
38 : ObjectBase(rsc) {
Jason Sams4815c0d2009-12-15 12:58:36 -080039
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080040 initMemberVars();
Jason Sams4815c0d2009-12-15 12:58:36 -080041 for (uint32_t ct=0; ct < paramLength; ct+=2) {
42 if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
43 mInputCount++;
44 }
45 if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
46 mOutputCount++;
47 }
48 if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
49 mConstantCount++;
50 }
Alex Sakhartchouk84e40272010-11-18 15:22:43 -080051 if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_TYPE) {
52 mTextureCount++;
Jason Samsf2e4fa22009-12-15 13:27:04 -080053 }
Jason Sams4815c0d2009-12-15 12:58:36 -080054 }
55
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -070056 mTextures = new ObjectBaseRef<Allocation>[mTextureCount];
57 mSamplers = new ObjectBaseRef<Sampler>[mTextureCount];
Alex Sakhartchouk84e40272010-11-18 15:22:43 -080058 mTextureTargets = new RsTextureTarget[mTextureCount];
Jason Sams4815c0d2009-12-15 12:58:36 -080059 mInputElements = new ObjectBaseRef<Element>[mInputCount];
60 mOutputElements = new ObjectBaseRef<Element>[mOutputCount];
61 mConstantTypes = new ObjectBaseRef<Type>[mConstantCount];
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -080062 mConstants = new ObjectBaseRef<Allocation>[mConstantCount];
Jason Sams4815c0d2009-12-15 12:58:36 -080063
64 uint32_t input = 0;
65 uint32_t output = 0;
66 uint32_t constant = 0;
Alex Sakhartchouk84e40272010-11-18 15:22:43 -080067 uint32_t texture = 0;
Jason Sams4815c0d2009-12-15 12:58:36 -080068 for (uint32_t ct=0; ct < paramLength; ct+=2) {
69 if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
70 mInputElements[input++].set(reinterpret_cast<Element *>(params[ct+1]));
71 }
72 if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
73 mOutputElements[output++].set(reinterpret_cast<Element *>(params[ct+1]));
74 }
75 if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
76 mConstantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1]));
77 }
Alex Sakhartchouk84e40272010-11-18 15:22:43 -080078 if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_TYPE) {
79 mTextureTargets[texture++] = (RsTextureTarget)params[ct+1];
80 }
Jason Sams4815c0d2009-12-15 12:58:36 -080081 }
Alex Sakhartchouke7ae69f2010-09-14 09:50:43 -070082 mIsInternal = false;
83 uint32_t internalTokenLen = strlen(RS_SHADER_INTERNAL);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080084 if (shaderLength > internalTokenLen &&
Alex Sakhartchouke7ae69f2010-09-14 09:50:43 -070085 strncmp(RS_SHADER_INTERNAL, shaderText, internalTokenLen) == 0) {
86 mIsInternal = true;
87 shaderText += internalTokenLen;
88 shaderLength -= internalTokenLen;
89 }
Jason Sams4815c0d2009-12-15 12:58:36 -080090 mUserShader.setTo(shaderText, shaderLength);
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -080091
92 initAttribAndUniformArray();
Jason Sams326e0dd2009-05-22 14:03:28 -070093}
94
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080095Program::~Program() {
96 if (mRSC->props.mLogShaders) {
Alex Sakhartchouk889fe502010-10-01 10:54:06 -070097 LOGV("Program::~Program with shader id %u", mShaderID);
98 }
99
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800100 if (mShaderID) {
Alex Sakhartchouk889fe502010-10-01 10:54:06 -0700101 glDeleteShader(mShaderID);
102 }
103
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800104 for (uint32_t ct=0; ct < mConstantCount; ct++) {
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700105 bindAllocation(NULL, NULL, ct);
Jason Sams9ebb0c42010-01-12 12:12:28 -0800106 }
Jason Sams4815c0d2009-12-15 12:58:36 -0800107
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700108 for (uint32_t ct=0; ct < mTextureCount; ct++) {
109 bindTexture(NULL, ct, NULL);
110 bindSampler(NULL, ct, NULL);
111 }
112 delete[] mTextures;
113 delete[] mSamplers;
Alex Sakhartchouk84e40272010-11-18 15:22:43 -0800114 delete[] mTextureTargets;
Jason Sams4815c0d2009-12-15 12:58:36 -0800115 delete[] mInputElements;
116 delete[] mOutputElements;
117 delete[] mConstantTypes;
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800118 delete[] mConstants;
119 delete[] mAttribNames;
120 delete[] mUniformNames;
121 delete[] mUniformArraySizes;
Jason Sams4815c0d2009-12-15 12:58:36 -0800122 mInputCount = 0;
123 mOutputCount = 0;
124 mConstantCount = 0;
Jason Sams326e0dd2009-05-22 14:03:28 -0700125}
126
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800127void Program::initMemberVars() {
128 mDirty = true;
129 mShaderID = 0;
130 mAttribCount = 0;
131 mUniformCount = 0;
132 mTextureCount = 0;
133
134 mTextures = NULL;
135 mSamplers = NULL;
Alex Sakhartchouk84e40272010-11-18 15:22:43 -0800136 mTextureTargets = NULL;
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800137 mInputElements = NULL;
138 mOutputElements = NULL;
139 mConstantTypes = NULL;
140 mConstants = NULL;
141 mAttribNames = NULL;
142 mUniformNames = NULL;
143 mUniformArraySizes = NULL;
144 mInputCount = 0;
145 mOutputCount = 0;
146 mConstantCount = 0;
147 mIsValid = false;
148 mIsInternal = false;
149}
Jason Sams326e0dd2009-05-22 14:03:28 -0700150
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800151void Program::bindAllocation(Context *rsc, Allocation *alloc, uint32_t slot) {
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700152 if (alloc != NULL) {
153 if (slot >= mConstantCount) {
154 LOGE("Attempt to bind alloc at slot %u, on shader id %u, but const count is %u",
155 slot, (uint32_t)this, mConstantCount);
156 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation");
157 return;
158 }
159 if (!alloc->getType()->isEqual(mConstantTypes[slot].get())) {
160 LOGE("Attempt to bind alloc at slot %u, on shader id %u, but types mismatch",
161 slot, (uint32_t)this);
162 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation");
163 return;
164 }
165 }
Jason Sams9ebb0c42010-01-12 12:12:28 -0800166 if (mConstants[slot].get() == alloc) {
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700167 return;
168 }
Jason Sams9ebb0c42010-01-12 12:12:28 -0800169 if (mConstants[slot].get()) {
170 mConstants[slot].get()->removeProgramToDirty(this);
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700171 }
Jason Sams9ebb0c42010-01-12 12:12:28 -0800172 mConstants[slot].set(alloc);
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700173 if (alloc) {
174 alloc->addProgramToDirty(this);
175 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700176 mDirty = true;
177}
178
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800179void Program::bindTexture(Context *rsc, uint32_t slot, Allocation *a) {
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700180 if (slot >= mTextureCount) {
181 LOGE("Attempt to bind texture to slot %u but tex count is %u", slot, mTextureCount);
182 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind texture");
Jason Sams7dad9c32009-12-17 16:55:08 -0800183 return;
184 }
185
Alex Sakhartchouk84e40272010-11-18 15:22:43 -0800186 if (a && a->getType()->getDimFaces() && mTextureTargets[slot] != RS_TEXTURE_CUBE) {
187 LOGE("Attempt to bind cubemap to slot %u but 2d texture needed", slot);
188 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind cubemap to 2d texture slot");
189 return;
190 }
191
Jason Sams7dad9c32009-12-17 16:55:08 -0800192 //LOGE("bindtex %i %p", slot, a);
193 mTextures[slot].set(a);
194 mDirty = true;
195}
196
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800197void Program::bindSampler(Context *rsc, uint32_t slot, Sampler *s) {
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700198 if (slot >= mTextureCount) {
199 LOGE("Attempt to bind sampler to slot %u but tex count is %u", slot, mTextureCount);
200 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind sampler");
Jason Sams7dad9c32009-12-17 16:55:08 -0800201 return;
202 }
203
204 mSamplers[slot].set(s);
205 mDirty = true;
206}
207
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800208String8 Program::getGLSLInputString() const {
Jason Samsb4d35682010-01-04 16:52:27 -0800209 String8 s;
210 for (uint32_t ct=0; ct < mInputCount; ct++) {
211 const Element *e = mInputElements[ct].get();
212 for (uint32_t field=0; field < e->getFieldCount(); field++) {
213 const Element *f = e->getField(field);
214
215 // Cannot be complex
216 rsAssert(!f->getFieldCount());
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800217 switch (f->getComponent().getVectorSize()) {
Jason Samsb4d35682010-01-04 16:52:27 -0800218 case 1: s.append("attribute float ATTRIB_"); break;
219 case 2: s.append("attribute vec2 ATTRIB_"); break;
220 case 3: s.append("attribute vec3 ATTRIB_"); break;
221 case 4: s.append("attribute vec4 ATTRIB_"); break;
222 default:
223 rsAssert(0);
224 }
225
226 s.append(e->getFieldName(field));
227 s.append(";\n");
228 }
229 }
230 return s;
231}
232
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800233String8 Program::getGLSLOutputString() const {
Jason Samsb4d35682010-01-04 16:52:27 -0800234 return String8();
235}
236
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800237String8 Program::getGLSLConstantString() const {
Jason Samsb4d35682010-01-04 16:52:27 -0800238 return String8();
239}
240
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800241void Program::createShader() {
Jason Samsc460e552009-11-25 13:22:07 -0800242}
Jason Samscfb1d112009-08-05 13:57:03 -0700243
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800244bool Program::loadShader(Context *rsc, uint32_t type) {
Jason Samsc460e552009-11-25 13:22:07 -0800245 mShaderID = glCreateShader(type);
246 rsAssert(mShaderID);
247
Jason Samscd506532009-12-15 19:10:11 -0800248 if (rsc->props.mLogShaders) {
249 LOGV("Loading shader type %x, ID %i", type, mShaderID);
Nick Kralevich8492a702010-05-13 14:46:27 -0700250 LOGV("%s", mShader.string());
Jason Samscd506532009-12-15 19:10:11 -0800251 }
Jason Samsc460e552009-11-25 13:22:07 -0800252
253 if (mShaderID) {
254 const char * ss = mShader.string();
255 glShaderSource(mShaderID, 1, &ss, NULL);
256 glCompileShader(mShaderID);
257
258 GLint compiled = 0;
259 glGetShaderiv(mShaderID, GL_COMPILE_STATUS, &compiled);
260 if (!compiled) {
261 GLint infoLen = 0;
262 glGetShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
263 if (infoLen) {
264 char* buf = (char*) malloc(infoLen);
265 if (buf) {
266 glGetShaderInfoLog(mShaderID, infoLen, NULL, buf);
267 LOGE("Could not compile shader \n%s\n", buf);
268 free(buf);
269 }
270 glDeleteShader(mShaderID);
271 mShaderID = 0;
Jason Samsa2cf7552010-03-03 13:03:18 -0800272 rsc->setError(RS_ERROR_BAD_SHADER, "Error returned from GL driver loading shader text,");
Jason Samsc460e552009-11-25 13:22:07 -0800273 return false;
274 }
275 }
276 }
Jason Samscd506532009-12-15 19:10:11 -0800277
278 if (rsc->props.mLogShaders) {
279 LOGV("--Shader load result %x ", glGetError());
280 }
Jason Samsa2cf7552010-03-03 13:03:18 -0800281 mIsValid = true;
Jason Samsc460e552009-11-25 13:22:07 -0800282 return true;
283}
Jason Samsf2a5d732009-11-30 14:49:55 -0800284
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800285void Program::setShader(const char *txt, uint32_t len) {
Jason Samsf2a5d732009-11-30 14:49:55 -0800286 mUserShader.setTo(txt, len);
287}
288
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700289void Program::appendUserConstants() {
290 for (uint32_t ct=0; ct < mConstantCount; ct++) {
291 const Element *e = mConstantTypes[ct]->getElement();
292 for (uint32_t field=0; field < e->getFieldCount(); field++) {
293 const Element *f = e->getField(field);
294 const char *fn = e->getFieldName(field);
Jason Sams4815c0d2009-12-15 12:58:36 -0800295
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700296 if (fn[0] == '#') {
297 continue;
298 }
299
300 // Cannot be complex
301 rsAssert(!f->getFieldCount());
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800302 if (f->getType() == RS_TYPE_MATRIX_4X4) {
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700303 mShader.append("uniform mat4 UNI_");
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800304 } else if (f->getType() == RS_TYPE_MATRIX_3X3) {
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700305 mShader.append("uniform mat3 UNI_");
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800306 } else if (f->getType() == RS_TYPE_MATRIX_2X2) {
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700307 mShader.append("uniform mat2 UNI_");
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800308 } else {
309 switch (f->getComponent().getVectorSize()) {
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700310 case 1: mShader.append("uniform float UNI_"); break;
311 case 2: mShader.append("uniform vec2 UNI_"); break;
312 case 3: mShader.append("uniform vec3 UNI_"); break;
313 case 4: mShader.append("uniform vec4 UNI_"); break;
314 default:
315 rsAssert(0);
316 }
317 }
318
319 mShader.append(fn);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800320 if (e->getFieldArraySize(field) > 1) {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800321 mShader.appendFormat("[%d]", e->getFieldArraySize(field));
322 }
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700323 mShader.append(";\n");
324 }
325 }
326}
327
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800328void Program::logUniform(const Element *field, const float *fd, uint32_t arraySize ) {
329 RsDataType dataType = field->getType();
330 uint32_t elementSize = field->getSizeBytes() / sizeof(float);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800331 for (uint32_t i = 0; i < arraySize; i ++) {
332 if (arraySize > 1) {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800333 LOGV("Array Element [%u]", i);
334 }
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800335 if (dataType == RS_TYPE_MATRIX_4X4) {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800336 LOGV("Matrix4x4");
337 LOGV("{%f, %f, %f, %f", fd[0], fd[4], fd[8], fd[12]);
338 LOGV(" %f, %f, %f, %f", fd[1], fd[5], fd[9], fd[13]);
339 LOGV(" %f, %f, %f, %f", fd[2], fd[6], fd[10], fd[14]);
340 LOGV(" %f, %f, %f, %f}", fd[3], fd[7], fd[11], fd[15]);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800341 } else if (dataType == RS_TYPE_MATRIX_3X3) {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800342 LOGV("Matrix3x3");
343 LOGV("{%f, %f, %f", fd[0], fd[3], fd[6]);
344 LOGV(" %f, %f, %f", fd[1], fd[4], fd[7]);
345 LOGV(" %f, %f, %f}", fd[2], fd[5], fd[8]);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800346 } else if (dataType == RS_TYPE_MATRIX_2X2) {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800347 LOGV("Matrix2x2");
348 LOGV("{%f, %f", fd[0], fd[2]);
349 LOGV(" %f, %f}", fd[1], fd[3]);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800350 } else {
351 switch (field->getComponent().getVectorSize()) {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800352 case 1:
353 LOGV("Uniform 1 = %f", fd[0]);
354 break;
355 case 2:
356 LOGV("Uniform 2 = %f %f", fd[0], fd[1]);
357 break;
358 case 3:
359 LOGV("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
360 break;
361 case 4:
362 LOGV("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
363 break;
364 default:
365 rsAssert(0);
366 }
367 }
368 LOGE("Element size %u data=%p", elementSize, fd);
369 fd += elementSize;
370 LOGE("New data=%p", fd);
371 }
372}
373
374void Program::setUniform(Context *rsc, const Element *field, const float *fd,
375 int32_t slot, uint32_t arraySize ) {
376 RsDataType dataType = field->getType();
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800377 if (dataType == RS_TYPE_MATRIX_4X4) {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800378 glUniformMatrix4fv(slot, arraySize, GL_FALSE, fd);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800379 } else if (dataType == RS_TYPE_MATRIX_3X3) {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800380 glUniformMatrix3fv(slot, arraySize, GL_FALSE, fd);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800381 } else if (dataType == RS_TYPE_MATRIX_2X2) {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800382 glUniformMatrix2fv(slot, arraySize, GL_FALSE, fd);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800383 } else {
384 switch (field->getComponent().getVectorSize()) {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800385 case 1:
386 glUniform1fv(slot, arraySize, fd);
387 break;
388 case 2:
389 glUniform2fv(slot, arraySize, fd);
390 break;
391 case 3:
392 glUniform3fv(slot, arraySize, fd);
393 break;
394 case 4:
395 glUniform4fv(slot, arraySize, fd);
396 break;
397 default:
398 rsAssert(0);
399 }
400 }
401}
402
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700403void Program::setupUserConstants(Context *rsc, ShaderCache *sc, bool isFragment) {
Alex Sakhartchouke7ae69f2010-09-14 09:50:43 -0700404 uint32_t uidx = 0;
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700405 for (uint32_t ct=0; ct < mConstantCount; ct++) {
Alex Sakhartchouke7ae69f2010-09-14 09:50:43 -0700406 Allocation *alloc = mConstants[ct].get();
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700407 if (!alloc) {
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700408 LOGE("Attempting to set constants on shader id %u, but alloc at slot %u is not set", (uint32_t)this, ct);
409 rsc->setError(RS_ERROR_BAD_SHADER, "No constant allocation bound");
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700410 continue;
411 }
412
413 const uint8_t *data = static_cast<const uint8_t *>(alloc->getPtr());
414 const Element *e = mConstantTypes[ct]->getElement();
415 for (uint32_t field=0; field < e->getFieldCount(); field++) {
416 const Element *f = e->getField(field);
417 const char *fieldName = e->getFieldName(field);
418 // If this field is padding, skip it
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800419 if (fieldName[0] == '#') {
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700420 continue;
421 }
422
423 uint32_t offset = e->getFieldOffsetBytes(field);
424 const float *fd = reinterpret_cast<const float *>(&data[offset]);
425
426 int32_t slot = -1;
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800427 uint32_t arraySize = 1;
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800428 if (!isFragment) {
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700429 slot = sc->vtxUniformSlot(uidx);
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800430 arraySize = sc->vtxUniformSize(uidx);
431 } else {
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700432 slot = sc->fragUniformSlot(uidx);
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800433 arraySize = sc->fragUniformSize(uidx);
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700434 }
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800435 if (rsc->props.mLogShadersUniforms) {
Alex Sakhartchouk886f11a2010-09-29 09:49:13 -0700436 LOGV("Uniform slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s", slot, offset, ct, field, uidx, fieldName);
437 }
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700438 uidx ++;
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800439 if (slot < 0) {
440 continue;
441 }
442
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800443 if (rsc->props.mLogShadersUniforms) {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800444 logUniform(f, fd, arraySize);
445 }
446 setUniform(rsc, f, fd, slot, arraySize);
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700447 }
448 }
449}
450
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800451void Program::initAttribAndUniformArray() {
452 mAttribCount = 0;
453 for (uint32_t ct=0; ct < mInputCount; ct++) {
454 const Element *elem = mInputElements[ct].get();
455 for (uint32_t field=0; field < elem->getFieldCount(); field++) {
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800456 if (elem->getFieldName(field)[0] != '#') {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800457 mAttribCount ++;
458 }
459 }
460 }
461
462 mUniformCount = 0;
463 for (uint32_t ct=0; ct < mConstantCount; ct++) {
464 const Element *elem = mConstantTypes[ct]->getElement();
465
466 for (uint32_t field=0; field < elem->getFieldCount(); field++) {
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800467 if (elem->getFieldName(field)[0] != '#') {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800468 mUniformCount ++;
469 }
470 }
471 }
472 mUniformCount += mTextureCount;
473
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800474 if (mAttribCount) {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800475 mAttribNames = new String8[mAttribCount];
476 }
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800477 if (mUniformCount) {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800478 mUniformNames = new String8[mUniformCount];
479 mUniformArraySizes = new uint32_t[mUniformCount];
480 }
481}
482
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800483void Program::initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths, uint32_t *count, const char *prefix) {
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700484 rsAssert(e->getFieldCount());
485 for (uint32_t ct=0; ct < e->getFieldCount(); ct++) {
486 const Element *ce = e->getField(ct);
487 if (ce->getFieldCount()) {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800488 initAddUserElement(ce, names, arrayLengths, count, prefix);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800489 } else if (e->getFieldName(ct)[0] != '#') {
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700490 String8 tmp(prefix);
491 tmp.append(e->getFieldName(ct));
492 names[*count].setTo(tmp.string());
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800493 if (arrayLengths) {
Alex Sakhartchouk54929cc2010-11-08 15:10:52 -0800494 arrayLengths[*count] = e->getFieldArraySize(ct);
495 }
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700496 (*count)++;
497 }
498 }
499}
Jason Sams4815c0d2009-12-15 12:58:36 -0800500
501namespace android {
502namespace renderscript {
503
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800504void rsi_ProgramBindConstants(Context *rsc, RsProgram vp, uint32_t slot, RsAllocation constants) {
Jason Sams4815c0d2009-12-15 12:58:36 -0800505 Program *p = static_cast<Program *>(vp);
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700506 p->bindAllocation(rsc, static_cast<Allocation *>(constants), slot);
Jason Sams4815c0d2009-12-15 12:58:36 -0800507}
508
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800509void rsi_ProgramBindTexture(Context *rsc, RsProgram vpf, uint32_t slot, RsAllocation a) {
Jason Sams7dad9c32009-12-17 16:55:08 -0800510 Program *p = static_cast<Program *>(vpf);
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700511 p->bindTexture(rsc, slot, static_cast<Allocation *>(a));
Jason Sams7dad9c32009-12-17 16:55:08 -0800512}
513
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800514void rsi_ProgramBindSampler(Context *rsc, RsProgram vpf, uint32_t slot, RsSampler s) {
Jason Sams7dad9c32009-12-17 16:55:08 -0800515 Program *p = static_cast<Program *>(vpf);
Alex Sakhartchouk383e5b12010-09-23 16:16:33 -0700516 p->bindSampler(rsc, slot, static_cast<Sampler *>(s));
Jason Sams7dad9c32009-12-17 16:55:08 -0800517}
Jason Sams4815c0d2009-12-15 12:58:36 -0800518
519}
520}
521