blob: c353301fb2913095f5a83e02d79dbd16e159245a [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
17#include "rsContext.h"
18#include "rsProgramFragment.h"
19
Jason Sams1aa5a4e2009-06-22 17:15:15 -070020#include <GLES/gl.h>
21#include <GLES/glext.h>
Jason Samsc460e552009-11-25 13:22:07 -080022#include <GLES2/gl2.h>
23#include <GLES2/gl2ext.h>
Jason Sams1aa5a4e2009-06-22 17:15:15 -070024
Jason Sams326e0dd2009-05-22 14:03:28 -070025using namespace android;
26using namespace android::renderscript;
27
28
Jason Samse514b452009-09-25 14:51:22 -070029ProgramFragment::ProgramFragment(Context *rsc, Element *in, Element *out, bool pointSpriteEnable) :
Jason Sams4815c0d2009-12-15 12:58:36 -080030 Program(rsc)
Jason Sams326e0dd2009-05-22 14:03:28 -070031{
Jason Samsf2649a92009-09-25 16:37:33 -070032 mAllocFile = __FILE__;
33 mAllocLine = __LINE__;
Jason Sams326e0dd2009-05-22 14:03:28 -070034 for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
35 mEnvModes[ct] = RS_TEX_ENV_MODE_REPLACE;
36 mTextureDimensions[ct] = 2;
37 }
38 mTextureEnableMask = 0;
Jason Samse0158412009-08-20 16:10:36 -070039 mPointSpriteEnable = pointSpriteEnable;
Jason Sams334fd9a2009-07-02 15:09:27 -070040 mEnvModes[1] = RS_TEX_ENV_MODE_DECAL;
Jason Sams326e0dd2009-05-22 14:03:28 -070041}
42
Jason Samsf2e4fa22009-12-15 13:27:04 -080043ProgramFragment::ProgramFragment(Context *rsc, const char * shaderText,
44 uint32_t shaderLength, const uint32_t * params,
45 uint32_t paramLength) :
46 Program(rsc, shaderText, shaderLength, params, paramLength)
47{
48 mAllocFile = __FILE__;
49 mAllocLine = __LINE__;
50
51 init(rsc);
52 mTextureEnableMask = (1 << mTextureCount) -1;
53}
54
55
Jason Sams326e0dd2009-05-22 14:03:28 -070056ProgramFragment::~ProgramFragment()
57{
58}
59
Jason Samsafcb25c2009-08-25 11:34:49 -070060void ProgramFragment::setupGL(const Context *rsc, ProgramFragmentState *state)
Jason Sams326e0dd2009-05-22 14:03:28 -070061{
Jason Samscfb1d112009-08-05 13:57:03 -070062 if ((state->mLast.get() == this) && !mDirty) {
63 return;
64 }
65 state->mLast.set(this);
66
Jason Sams326e0dd2009-05-22 14:03:28 -070067 for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
68 glActiveTexture(GL_TEXTURE0 + ct);
Jason Sams334fd9a2009-07-02 15:09:27 -070069 if (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) {
Jason Sams326e0dd2009-05-22 14:03:28 -070070 glDisable(GL_TEXTURE_2D);
71 continue;
72 }
73
74 glEnable(GL_TEXTURE_2D);
Jason Samsafcb25c2009-08-25 11:34:49 -070075 if (rsc->checkVersion1_1()) {
Romain Guye62cc902009-09-04 17:55:41 -070076 if (mPointSpriteEnable) {
77 glEnable(GL_POINT_SPRITE_OES);
78 } else {
79 glDisable(GL_POINT_SPRITE_OES);
80 }
Jason Samsafcb25c2009-08-25 11:34:49 -070081 glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, mPointSpriteEnable);
82 }
Jason Samscf4c7c92009-12-14 12:57:40 -080083 mTextures[ct]->uploadCheck(rsc);
Jason Sams326e0dd2009-05-22 14:03:28 -070084 glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
85
86 switch(mEnvModes[ct]) {
87 case RS_TEX_ENV_MODE_REPLACE:
Jason Sams334fd9a2009-07-02 15:09:27 -070088 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
Jason Sams326e0dd2009-05-22 14:03:28 -070089 break;
90 case RS_TEX_ENV_MODE_MODULATE:
Jason Sams334fd9a2009-07-02 15:09:27 -070091 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
Jason Sams326e0dd2009-05-22 14:03:28 -070092 break;
93 case RS_TEX_ENV_MODE_DECAL:
Jason Sams334fd9a2009-07-02 15:09:27 -070094 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
Jason Sams326e0dd2009-05-22 14:03:28 -070095 break;
96 }
97
Jason Sams39c8bc72009-05-28 15:37:57 -070098 if (mSamplers[ct].get()) {
99 mSamplers[ct]->setupGL();
100 } else {
Jason Sams6678e9b2009-05-27 14:45:32 -0700101 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
102 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Jason Sams334fd9a2009-07-02 15:09:27 -0700103 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
Jason Sams6678e9b2009-05-27 14:45:32 -0700104 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
Jason Sams39c8bc72009-05-28 15:37:57 -0700105 }
Jason Sams334fd9a2009-07-02 15:09:27 -0700106
107 // Gross hack.
108 if (ct == 2) {
109 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
110
111 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
112 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
113 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
114 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
115 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
116
117 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD);
118 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
119 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
120 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
121 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
122 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700123 }
124 glActiveTexture(GL_TEXTURE0);
Jason Samscfb1d112009-08-05 13:57:03 -0700125 mDirty = false;
Jason Sams326e0dd2009-05-22 14:03:28 -0700126}
127
Jason Samsc460e552009-11-25 13:22:07 -0800128void ProgramFragment::setupGL2(const Context *rsc, ProgramFragmentState *state, ShaderCache *sc)
129{
130 //LOGE("sgl2 frag1 %x", glGetError());
131 if ((state->mLast.get() == this) && !mDirty) {
132 //return;
133 }
134 state->mLast.set(this);
135
136 for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
137 glActiveTexture(GL_TEXTURE0 + ct);
138 if (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) {
139 glDisable(GL_TEXTURE_2D);
140 continue;
141 }
142
Jason Samscf4c7c92009-12-14 12:57:40 -0800143 mTextures[ct]->uploadCheck(rsc);
Jason Samsc460e552009-11-25 13:22:07 -0800144 glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
145 if (mSamplers[ct].get()) {
146 mSamplers[ct]->setupGL();
147 } else {
148 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
149 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
150 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
151 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
152 }
153
154 glEnable(GL_TEXTURE_2D);
155 glUniform1i(sc->fragUniformSlot(ct), ct);
156 }
157
158 glActiveTexture(GL_TEXTURE0);
159 mDirty = false;
160
161 //LOGE("sgl2 frag2 %x", glGetError());
162}
163
Jason Samscd506532009-12-15 19:10:11 -0800164void ProgramFragment::loadShader(Context *rsc) {
165 Program::loadShader(rsc, GL_FRAGMENT_SHADER);
Jason Samsc460e552009-11-25 13:22:07 -0800166}
167
168void ProgramFragment::createShader()
169{
170 mShader.setTo("precision mediump float;\n");
171 mShader.append("varying vec4 varColor;\n");
172 mShader.append("varying vec4 varTex0;\n");
173
Jason Samsf2e4fa22009-12-15 13:27:04 -0800174 if (mUserShader.length() > 1) {
175 for (uint32_t ct=0; ct < mTextureCount; ct++) {
176 char buf[256];
177 sprintf(buf, "uniform sampler2D uni_Tex%i;\n", ct);
Jason Samsc460e552009-11-25 13:22:07 -0800178 mShader.append(buf);
Jason Samsc460e552009-11-25 13:22:07 -0800179 }
Jason Samsc460e552009-11-25 13:22:07 -0800180
Jason Samsf2e4fa22009-12-15 13:27:04 -0800181 mShader.append(mUserShader);
182 } else {
183 uint32_t mask = mTextureEnableMask;
184 uint32_t texNum = 0;
185 while (mask) {
186 if (mask & 1) {
187 char buf[64];
188 mShader.append("uniform sampler2D uni_Tex");
189 sprintf(buf, "%i", texNum);
190 mShader.append(buf);
191 mShader.append(";\n");
Jason Samsc460e552009-11-25 13:22:07 -0800192 }
Jason Samsf2e4fa22009-12-15 13:27:04 -0800193 mask >>= 1;
194 texNum++;
Jason Samsc460e552009-11-25 13:22:07 -0800195 }
Jason Samsf2e4fa22009-12-15 13:27:04 -0800196
197
198 mShader.append("void main() {\n");
199 mShader.append(" vec4 col = varColor;\n");
200
201 if (mTextureEnableMask) {
202 if (mPointSpriteEnable) {
203 mShader.append(" vec2 tex0 = gl_PointCoord;\n");
204 } else {
205 mShader.append(" vec2 tex0 = varTex0.xy;\n");
206 }
207 }
208
209 mask = mTextureEnableMask;
210 texNum = 0;
211 while (mask) {
212 if (mask & 1) {
213 switch(mEnvModes[texNum]) {
214 case RS_TEX_ENV_MODE_REPLACE:
215 mShader.append(" col = texture2D(uni_Tex0, tex0);\n");
216 break;
217 case RS_TEX_ENV_MODE_MODULATE:
218 mShader.append(" col *= texture2D(uni_Tex0, tex0);\n");
219 break;
220 case RS_TEX_ENV_MODE_DECAL:
221 mShader.append(" col = texture2D(uni_Tex0, tex0);\n");
222 break;
223 }
224
225 }
226 mask >>= 1;
227 texNum++;
228 }
229
230 //mShader.append(" col.a = 1.0;\n");
231 //mShader.append(" col.r = 0.5;\n");
232
233 mShader.append(" gl_FragColor = col;\n");
234 mShader.append("}\n");
Jason Samsc460e552009-11-25 13:22:07 -0800235 }
Jason Samsc460e552009-11-25 13:22:07 -0800236}
Jason Sams326e0dd2009-05-22 14:03:28 -0700237
238void ProgramFragment::bindTexture(uint32_t slot, Allocation *a)
239{
240 if (slot >= MAX_TEXTURE) {
241 LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE");
242 return;
243 }
244
Jason Sams334fd9a2009-07-02 15:09:27 -0700245 //LOGE("bindtex %i %p", slot, a);
Jason Sams326e0dd2009-05-22 14:03:28 -0700246 mTextures[slot].set(a);
Jason Samscfb1d112009-08-05 13:57:03 -0700247 mDirty = true;
Jason Sams326e0dd2009-05-22 14:03:28 -0700248}
249
250void ProgramFragment::bindSampler(uint32_t slot, Sampler *s)
251{
252 if (slot >= MAX_TEXTURE) {
253 LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE");
254 return;
255 }
256
257 mSamplers[slot].set(s);
Jason Samscfb1d112009-08-05 13:57:03 -0700258 mDirty = true;
Jason Sams326e0dd2009-05-22 14:03:28 -0700259}
260
261void ProgramFragment::setType(uint32_t slot, const Element *e, uint32_t dim)
262{
263 if (slot >= MAX_TEXTURE) {
264 LOGE("Attempt to setType to a slot > MAX_TEXTURE");
265 return;
266 }
267
268 if (dim >= 4) {
269 LOGE("Attempt to setType to a dimension > 3");
270 return;
271 }
272
273 mTextureFormats[slot].set(e);
274 mTextureDimensions[slot] = dim;
275}
276
277void ProgramFragment::setEnvMode(uint32_t slot, RsTexEnvMode env)
278{
279 if (slot >= MAX_TEXTURE) {
280 LOGE("Attempt to setEnvMode to a slot > MAX_TEXTURE");
281 return;
282 }
283
284 mEnvModes[slot] = env;
285}
286
287void ProgramFragment::setTexEnable(uint32_t slot, bool enable)
288{
289 if (slot >= MAX_TEXTURE) {
290 LOGE("Attempt to setEnvMode to a slot > MAX_TEXTURE");
291 return;
292 }
293
294 uint32_t bit = 1 << slot;
295 mTextureEnableMask &= ~bit;
296 if (enable) {
297 mTextureEnableMask |= bit;
298 }
299}
300
Jason Samsc460e552009-11-25 13:22:07 -0800301void ProgramFragment::init(Context *rsc)
302{
303 mUniformCount = 2;
304 mUniformNames[0].setTo("uni_Tex0");
305 mUniformNames[1].setTo("uni_Tex1");
Jason Sams326e0dd2009-05-22 14:03:28 -0700306
Jason Samsc460e552009-11-25 13:22:07 -0800307 createShader();
308}
Jason Sams326e0dd2009-05-22 14:03:28 -0700309
310ProgramFragmentState::ProgramFragmentState()
311{
312 mPF = NULL;
313}
314
315ProgramFragmentState::~ProgramFragmentState()
316{
317 delete mPF;
318
319}
320
Jason Sams8ce125b2009-06-17 16:52:59 -0700321void ProgramFragmentState::init(Context *rsc, int32_t w, int32_t h)
322{
Jason Samse514b452009-09-25 14:51:22 -0700323 ProgramFragment *pf = new ProgramFragment(rsc, NULL, NULL, false);
Jason Sams8ce125b2009-06-17 16:52:59 -0700324 mDefault.set(pf);
Jason Samsc460e552009-11-25 13:22:07 -0800325 pf->init(rsc);
Jason Sams8ce125b2009-06-17 16:52:59 -0700326}
Jason Sams326e0dd2009-05-22 14:03:28 -0700327
Jason Samsf2649a92009-09-25 16:37:33 -0700328void ProgramFragmentState::deinit(Context *rsc)
329{
330 mDefault.clear();
331 mLast.clear();
332}
333
Jason Sams326e0dd2009-05-22 14:03:28 -0700334
335namespace android {
336namespace renderscript {
337
Jason Samse0158412009-08-20 16:10:36 -0700338void rsi_ProgramFragmentBegin(Context * rsc, RsElement in, RsElement out, bool pointSpriteEnable)
Jason Sams326e0dd2009-05-22 14:03:28 -0700339{
340 delete rsc->mStateFragment.mPF;
Jason Samse514b452009-09-25 14:51:22 -0700341 rsc->mStateFragment.mPF = new ProgramFragment(rsc, (Element *)in, (Element *)out, pointSpriteEnable);
Jason Sams326e0dd2009-05-22 14:03:28 -0700342}
343
344void rsi_ProgramFragmentBindTexture(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsAllocation a)
345{
346 ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
347 pf->bindTexture(slot, static_cast<Allocation *>(a));
Jason Sams326e0dd2009-05-22 14:03:28 -0700348}
349
350void rsi_ProgramFragmentBindSampler(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsSampler s)
351{
352 ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
353 pf->bindSampler(slot, static_cast<Sampler *>(s));
Jason Sams326e0dd2009-05-22 14:03:28 -0700354}
355
Jason Samse0158412009-08-20 16:10:36 -0700356void rsi_ProgramFragmentSetSlot(Context *rsc, uint32_t slot, bool enable, RsTexEnvMode env, RsType vt)
Jason Sams326e0dd2009-05-22 14:03:28 -0700357{
358 const Type *t = static_cast<const Type *>(vt);
Jason Samse0158412009-08-20 16:10:36 -0700359 if (t) {
360 uint32_t dim = 1;
361 if (t->getDimY()) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700362 dim ++;
Jason Samse0158412009-08-20 16:10:36 -0700363 if (t->getDimZ()) {
364 dim ++;
365 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700366 }
Jason Samse0158412009-08-20 16:10:36 -0700367 rsc->mStateFragment.mPF->setType(slot, t->getElement(), dim);
Jason Sams326e0dd2009-05-22 14:03:28 -0700368 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700369 rsc->mStateFragment.mPF->setEnvMode(slot, env);
Jason Sams326e0dd2009-05-22 14:03:28 -0700370 rsc->mStateFragment.mPF->setTexEnable(slot, enable);
371}
372
Jason Samsf2a5d732009-11-30 14:49:55 -0800373void rsi_ProgramFragmentSetShader(Context *rsc, const char *txt, uint32_t len)
374{
375 rsc->mStateFragment.mPF->setShader(txt, len);
376}
377
Jason Sams326e0dd2009-05-22 14:03:28 -0700378RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc)
379{
380 ProgramFragment *pf = rsc->mStateFragment.mPF;
Jason Sams9397e302009-08-27 20:23:34 -0700381 pf->incUserRef();
Jason Samsc460e552009-11-25 13:22:07 -0800382 pf->init(rsc);
Jason Sams326e0dd2009-05-22 14:03:28 -0700383 rsc->mStateFragment.mPF = 0;
384 return pf;
385}
386
Jason Samsf2e4fa22009-12-15 13:27:04 -0800387RsProgramFragment rsi_ProgramFragmentCreate2(Context *rsc, const char * shaderText,
388 uint32_t shaderLength, const uint32_t * params,
389 uint32_t paramLength)
390{
391 ProgramFragment *pf = new ProgramFragment(rsc, shaderText, shaderLength, params, paramLength);
392 pf->incUserRef();
393 return pf;
394}
Jason Sams326e0dd2009-05-22 14:03:28 -0700395
396}
397}
398