blob: 24414912fbc8a0e3749fe2c8d149d5a1de698c83 [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;
Alex Sakhartchouke7ae69f2010-09-14 09:50:43 -070049 mIsInternal = false;
Jason Sams4815c0d2009-12-15 12:58:36 -080050}
51
52Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
53 const uint32_t * params, uint32_t paramLength) :
54 ObjectBase(rsc)
55{
56 mAllocFile = __FILE__;
57 mAllocLine = __LINE__;
58 mDirty = true;
59 mShaderID = 0;
60 mAttribCount = 0;
61 mUniformCount = 0;
Jason Samsf2e4fa22009-12-15 13:27:04 -080062 mTextureCount = 0;
Jason Sams4815c0d2009-12-15 12:58:36 -080063
64 mInputCount = 0;
65 mOutputCount = 0;
66 mConstantCount = 0;
67
68 for (uint32_t ct=0; ct < paramLength; ct+=2) {
69 if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
70 mInputCount++;
71 }
72 if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
73 mOutputCount++;
74 }
75 if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
76 mConstantCount++;
77 }
Jason Samsf2e4fa22009-12-15 13:27:04 -080078 if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_COUNT) {
79 mTextureCount = params[ct+1];
80 }
Jason Sams4815c0d2009-12-15 12:58:36 -080081 }
82
83 mInputElements = new ObjectBaseRef<Element>[mInputCount];
84 mOutputElements = new ObjectBaseRef<Element>[mOutputCount];
85 mConstantTypes = new ObjectBaseRef<Type>[mConstantCount];
86
87 uint32_t input = 0;
88 uint32_t output = 0;
89 uint32_t constant = 0;
90 for (uint32_t ct=0; ct < paramLength; ct+=2) {
91 if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
92 mInputElements[input++].set(reinterpret_cast<Element *>(params[ct+1]));
93 }
94 if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
95 mOutputElements[output++].set(reinterpret_cast<Element *>(params[ct+1]));
96 }
97 if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
98 mConstantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1]));
99 }
100 }
Alex Sakhartchouke7ae69f2010-09-14 09:50:43 -0700101 mIsInternal = false;
102 uint32_t internalTokenLen = strlen(RS_SHADER_INTERNAL);
103 if(shaderLength > internalTokenLen &&
104 strncmp(RS_SHADER_INTERNAL, shaderText, internalTokenLen) == 0) {
105 mIsInternal = true;
106 shaderText += internalTokenLen;
107 shaderLength -= internalTokenLen;
108 }
Jason Sams4815c0d2009-12-15 12:58:36 -0800109 mUserShader.setTo(shaderText, shaderLength);
Jason Sams326e0dd2009-05-22 14:03:28 -0700110}
111
112Program::~Program()
113{
Jason Sams9ebb0c42010-01-12 12:12:28 -0800114 for (uint32_t ct=0; ct < MAX_UNIFORMS; ct++) {
115 bindAllocation(NULL, ct);
116 }
Jason Sams4815c0d2009-12-15 12:58:36 -0800117
118 delete[] mInputElements;
119 delete[] mOutputElements;
120 delete[] mConstantTypes;
121 mInputCount = 0;
122 mOutputCount = 0;
123 mConstantCount = 0;
Jason Sams326e0dd2009-05-22 14:03:28 -0700124}
125
126
Jason Sams9ebb0c42010-01-12 12:12:28 -0800127void Program::bindAllocation(Allocation *alloc, uint32_t slot)
Jason Sams326e0dd2009-05-22 14:03:28 -0700128{
Jason Sams9ebb0c42010-01-12 12:12:28 -0800129 if (mConstants[slot].get() == alloc) {
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700130 return;
131 }
Jason Sams9ebb0c42010-01-12 12:12:28 -0800132 if (mConstants[slot].get()) {
133 mConstants[slot].get()->removeProgramToDirty(this);
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700134 }
Jason Sams9ebb0c42010-01-12 12:12:28 -0800135 mConstants[slot].set(alloc);
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700136 if (alloc) {
137 alloc->addProgramToDirty(this);
138 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700139 mDirty = true;
140}
141
Jason Sams7dad9c32009-12-17 16:55:08 -0800142void Program::bindTexture(uint32_t slot, Allocation *a)
143{
144 if (slot >= MAX_TEXTURE) {
145 LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE");
146 return;
147 }
148
149 //LOGE("bindtex %i %p", slot, a);
150 mTextures[slot].set(a);
151 mDirty = true;
152}
153
154void Program::bindSampler(uint32_t slot, Sampler *s)
155{
156 if (slot >= MAX_TEXTURE) {
157 LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE");
158 return;
159 }
160
161 mSamplers[slot].set(s);
162 mDirty = true;
163}
164
Jason Samsb4d35682010-01-04 16:52:27 -0800165String8 Program::getGLSLInputString() const
166{
167 String8 s;
168 for (uint32_t ct=0; ct < mInputCount; ct++) {
169 const Element *e = mInputElements[ct].get();
170 for (uint32_t field=0; field < e->getFieldCount(); field++) {
171 const Element *f = e->getField(field);
172
173 // Cannot be complex
174 rsAssert(!f->getFieldCount());
175 switch(f->getComponent().getVectorSize()) {
176 case 1: s.append("attribute float ATTRIB_"); break;
177 case 2: s.append("attribute vec2 ATTRIB_"); break;
178 case 3: s.append("attribute vec3 ATTRIB_"); break;
179 case 4: s.append("attribute vec4 ATTRIB_"); break;
180 default:
181 rsAssert(0);
182 }
183
184 s.append(e->getFieldName(field));
185 s.append(";\n");
186 }
187 }
188 return s;
189}
190
191String8 Program::getGLSLOutputString() const
192{
193 return String8();
194}
195
196String8 Program::getGLSLConstantString() const
197{
198 return String8();
199}
200
Jason Sams7dad9c32009-12-17 16:55:08 -0800201
Jason Samsc460e552009-11-25 13:22:07 -0800202void Program::createShader()
203{
204}
Jason Samscfb1d112009-08-05 13:57:03 -0700205
Jason Samscd506532009-12-15 19:10:11 -0800206bool Program::loadShader(Context *rsc, uint32_t type)
Jason Samsc460e552009-11-25 13:22:07 -0800207{
208 mShaderID = glCreateShader(type);
209 rsAssert(mShaderID);
210
Jason Samscd506532009-12-15 19:10:11 -0800211 if (rsc->props.mLogShaders) {
212 LOGV("Loading shader type %x, ID %i", type, mShaderID);
Nick Kralevich8492a702010-05-13 14:46:27 -0700213 LOGV("%s", mShader.string());
Jason Samscd506532009-12-15 19:10:11 -0800214 }
Jason Samsc460e552009-11-25 13:22:07 -0800215
216 if (mShaderID) {
217 const char * ss = mShader.string();
218 glShaderSource(mShaderID, 1, &ss, NULL);
219 glCompileShader(mShaderID);
220
221 GLint compiled = 0;
222 glGetShaderiv(mShaderID, GL_COMPILE_STATUS, &compiled);
223 if (!compiled) {
224 GLint infoLen = 0;
225 glGetShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
226 if (infoLen) {
227 char* buf = (char*) malloc(infoLen);
228 if (buf) {
229 glGetShaderInfoLog(mShaderID, infoLen, NULL, buf);
230 LOGE("Could not compile shader \n%s\n", buf);
231 free(buf);
232 }
233 glDeleteShader(mShaderID);
234 mShaderID = 0;
Jason Samsa2cf7552010-03-03 13:03:18 -0800235 rsc->setError(RS_ERROR_BAD_SHADER, "Error returned from GL driver loading shader text,");
Jason Samsc460e552009-11-25 13:22:07 -0800236 return false;
237 }
238 }
239 }
Jason Samscd506532009-12-15 19:10:11 -0800240
241 if (rsc->props.mLogShaders) {
242 LOGV("--Shader load result %x ", glGetError());
243 }
Jason Samsa2cf7552010-03-03 13:03:18 -0800244 mIsValid = true;
Jason Samsc460e552009-11-25 13:22:07 -0800245 return true;
246}
Jason Samsf2a5d732009-11-30 14:49:55 -0800247
248void Program::setShader(const char *txt, uint32_t len)
249{
250 mUserShader.setTo(txt, len);
251}
252
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700253void Program::appendUserConstants() {
254 for (uint32_t ct=0; ct < mConstantCount; ct++) {
255 const Element *e = mConstantTypes[ct]->getElement();
256 for (uint32_t field=0; field < e->getFieldCount(); field++) {
257 const Element *f = e->getField(field);
258 const char *fn = e->getFieldName(field);
Jason Sams4815c0d2009-12-15 12:58:36 -0800259
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700260 if (fn[0] == '#') {
261 continue;
262 }
263
264 // Cannot be complex
265 rsAssert(!f->getFieldCount());
266 if(f->getType() == RS_TYPE_MATRIX_4X4) {
267 mShader.append("uniform mat4 UNI_");
268 }
269 else if(f->getType() == RS_TYPE_MATRIX_3X3) {
270 mShader.append("uniform mat3 UNI_");
271 }
272 else if(f->getType() == RS_TYPE_MATRIX_2X2) {
273 mShader.append("uniform mat2 UNI_");
274 }
275 else {
276 switch(f->getComponent().getVectorSize()) {
277 case 1: mShader.append("uniform float UNI_"); break;
278 case 2: mShader.append("uniform vec2 UNI_"); break;
279 case 3: mShader.append("uniform vec3 UNI_"); break;
280 case 4: mShader.append("uniform vec4 UNI_"); break;
281 default:
282 rsAssert(0);
283 }
284 }
285
286 mShader.append(fn);
287 mShader.append(";\n");
288 }
289 }
290}
291
292void Program::setupUserConstants(ShaderCache *sc, bool isFragment) {
Alex Sakhartchouke7ae69f2010-09-14 09:50:43 -0700293 uint32_t uidx = 0;
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700294 for (uint32_t ct=0; ct < mConstantCount; ct++) {
Alex Sakhartchouke7ae69f2010-09-14 09:50:43 -0700295 Allocation *alloc = mConstants[ct].get();
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700296 if (!alloc) {
297 continue;
298 }
299
300 const uint8_t *data = static_cast<const uint8_t *>(alloc->getPtr());
301 const Element *e = mConstantTypes[ct]->getElement();
302 for (uint32_t field=0; field < e->getFieldCount(); field++) {
303 const Element *f = e->getField(field);
304 const char *fieldName = e->getFieldName(field);
305 // If this field is padding, skip it
306 if(fieldName[0] == '#') {
307 continue;
308 }
309
310 uint32_t offset = e->getFieldOffsetBytes(field);
311 const float *fd = reinterpret_cast<const float *>(&data[offset]);
312
313 int32_t slot = -1;
314 if(!isFragment) {
315 slot = sc->vtxUniformSlot(uidx);
316 }
317 else {
318 slot = sc->fragUniformSlot(uidx);
319 }
320
321 //LOGE("Uniform slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s", slot, offset, ct, field, uidx, fieldName);
322 if (slot >= 0) {
323 if(f->getType() == RS_TYPE_MATRIX_4X4) {
324 glUniformMatrix4fv(slot, 1, GL_FALSE, fd);
Alex Sakhartchouke7ae69f2010-09-14 09:50:43 -0700325 /*for(int i = 0; i < 4; i++) {
326 LOGE("Mat = %f %f %f %f", fd[i*4 + 0], fd[i*4 + 1], fd[i*4 + 2], fd[i*4 + 3]);
327 }*/
Alex Sakhartchouk6e934212010-08-31 12:02:01 -0700328 }
329 else if(f->getType() == RS_TYPE_MATRIX_3X3) {
330 glUniformMatrix3fv(slot, 1, GL_FALSE, fd);
331 }
332 else if(f->getType() == RS_TYPE_MATRIX_2X2) {
333 glUniformMatrix2fv(slot, 1, GL_FALSE, fd);
334 }
335 else {
336 switch(f->getComponent().getVectorSize()) {
337 case 1:
338 //LOGE("Uniform 1 = %f", fd[0]);
339 glUniform1fv(slot, 1, fd);
340 break;
341 case 2:
342 //LOGE("Uniform 2 = %f %f", fd[0], fd[1]);
343 glUniform2fv(slot, 1, fd);
344 break;
345 case 3:
346 //LOGE("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
347 glUniform3fv(slot, 1, fd);
348 break;
349 case 4:
350 //LOGE("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
351 glUniform4fv(slot, 1, fd);
352 break;
353 default:
354 rsAssert(0);
355 }
356 }
357 }
358 uidx ++;
359 }
360 }
361}
362
363void Program::initAddUserElement(const Element *e, String8 *names, uint32_t *count, const char *prefix)
364{
365 rsAssert(e->getFieldCount());
366 for (uint32_t ct=0; ct < e->getFieldCount(); ct++) {
367 const Element *ce = e->getField(ct);
368 if (ce->getFieldCount()) {
369 initAddUserElement(ce, names, count, prefix);
370 }
371 else if(e->getFieldName(ct)[0] != '#') {
372 String8 tmp(prefix);
373 tmp.append(e->getFieldName(ct));
374 names[*count].setTo(tmp.string());
375 (*count)++;
376 }
377 }
378}
Jason Sams4815c0d2009-12-15 12:58:36 -0800379
380namespace android {
381namespace renderscript {
382
383
384void rsi_ProgramBindConstants(Context *rsc, RsProgram vp, uint32_t slot, RsAllocation constants)
385{
386 Program *p = static_cast<Program *>(vp);
Jason Sams9ebb0c42010-01-12 12:12:28 -0800387 p->bindAllocation(static_cast<Allocation *>(constants), slot);
Jason Sams4815c0d2009-12-15 12:58:36 -0800388}
389
Jason Sams7dad9c32009-12-17 16:55:08 -0800390void rsi_ProgramBindTexture(Context *rsc, RsProgram vpf, uint32_t slot, RsAllocation a)
391{
392 Program *p = static_cast<Program *>(vpf);
393 p->bindTexture(slot, static_cast<Allocation *>(a));
394}
395
396void rsi_ProgramBindSampler(Context *rsc, RsProgram vpf, uint32_t slot, RsSampler s)
397{
398 Program *p = static_cast<Program *>(vpf);
399 p->bindSampler(slot, static_cast<Sampler *>(s));
400}
Jason Sams4815c0d2009-12-15 12:58:36 -0800401
402}
403}
404