blob: daefc2c6f0e22a5d213145fb915dda81457f7660 [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) :
30 Program(rsc, in, out)
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
43ProgramFragment::~ProgramFragment()
44{
45}
46
Jason Samsafcb25c2009-08-25 11:34:49 -070047void ProgramFragment::setupGL(const Context *rsc, ProgramFragmentState *state)
Jason Sams326e0dd2009-05-22 14:03:28 -070048{
Jason Samscfb1d112009-08-05 13:57:03 -070049 if ((state->mLast.get() == this) && !mDirty) {
50 return;
51 }
52 state->mLast.set(this);
53
Jason Sams326e0dd2009-05-22 14:03:28 -070054 for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
55 glActiveTexture(GL_TEXTURE0 + ct);
Jason Sams334fd9a2009-07-02 15:09:27 -070056 if (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) {
Jason Sams326e0dd2009-05-22 14:03:28 -070057 glDisable(GL_TEXTURE_2D);
58 continue;
59 }
60
61 glEnable(GL_TEXTURE_2D);
Jason Samsafcb25c2009-08-25 11:34:49 -070062 if (rsc->checkVersion1_1()) {
Romain Guye62cc902009-09-04 17:55:41 -070063 if (mPointSpriteEnable) {
64 glEnable(GL_POINT_SPRITE_OES);
65 } else {
66 glDisable(GL_POINT_SPRITE_OES);
67 }
Jason Samsafcb25c2009-08-25 11:34:49 -070068 glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, mPointSpriteEnable);
69 }
Jason Sams326e0dd2009-05-22 14:03:28 -070070 glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
71
72 switch(mEnvModes[ct]) {
73 case RS_TEX_ENV_MODE_REPLACE:
Jason Sams334fd9a2009-07-02 15:09:27 -070074 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
Jason Sams326e0dd2009-05-22 14:03:28 -070075 break;
76 case RS_TEX_ENV_MODE_MODULATE:
Jason Sams334fd9a2009-07-02 15:09:27 -070077 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
Jason Sams326e0dd2009-05-22 14:03:28 -070078 break;
79 case RS_TEX_ENV_MODE_DECAL:
Jason Sams334fd9a2009-07-02 15:09:27 -070080 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
Jason Sams326e0dd2009-05-22 14:03:28 -070081 break;
82 }
83
Jason Sams39c8bc72009-05-28 15:37:57 -070084 if (mSamplers[ct].get()) {
85 mSamplers[ct]->setupGL();
86 } else {
Jason Sams6678e9b2009-05-27 14:45:32 -070087 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
88 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Jason Sams334fd9a2009-07-02 15:09:27 -070089 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
Jason Sams6678e9b2009-05-27 14:45:32 -070090 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
Jason Sams39c8bc72009-05-28 15:37:57 -070091 }
Jason Sams334fd9a2009-07-02 15:09:27 -070092
93 // Gross hack.
94 if (ct == 2) {
95 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
96
97 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
98 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
99 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
100 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
101 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
102
103 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD);
104 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
105 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
106 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
107 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
108 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700109 }
110 glActiveTexture(GL_TEXTURE0);
Jason Samscfb1d112009-08-05 13:57:03 -0700111 mDirty = false;
Jason Sams326e0dd2009-05-22 14:03:28 -0700112}
113
Jason Samsc460e552009-11-25 13:22:07 -0800114void ProgramFragment::setupGL2(const Context *rsc, ProgramFragmentState *state, ShaderCache *sc)
115{
116 //LOGE("sgl2 frag1 %x", glGetError());
117 if ((state->mLast.get() == this) && !mDirty) {
118 //return;
119 }
120 state->mLast.set(this);
121
122 for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
123 glActiveTexture(GL_TEXTURE0 + ct);
124 if (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) {
125 glDisable(GL_TEXTURE_2D);
126 continue;
127 }
128
129 glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
130 if (mSamplers[ct].get()) {
131 mSamplers[ct]->setupGL();
132 } else {
133 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
134 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
135 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
136 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
137 }
138
139 glEnable(GL_TEXTURE_2D);
140 glUniform1i(sc->fragUniformSlot(ct), ct);
141 }
142
143 glActiveTexture(GL_TEXTURE0);
144 mDirty = false;
145
146 //LOGE("sgl2 frag2 %x", glGetError());
147}
148
149void ProgramFragment::loadShader() {
150 Program::loadShader(GL_FRAGMENT_SHADER);
151}
152
153void ProgramFragment::createShader()
154{
155 mShader.setTo("precision mediump float;\n");
156 mShader.append("varying vec4 varColor;\n");
157 mShader.append("varying vec4 varTex0;\n");
158
159 uint32_t mask = mTextureEnableMask;
160 uint32_t texNum = 0;
161 while (mask) {
162 if (mask & 1) {
163 char buf[64];
164 mShader.append("uniform sampler2D uni_Tex");
165 sprintf(buf, "%i", texNum);
166 mShader.append(buf);
167 mShader.append(";\n");
168 }
169 mask >>= 1;
170 texNum++;
171 }
172
173
174 mShader.append("void main() {\n");
175 //mShader.append(" gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n");
176 mShader.append(" vec4 col = varColor;\n");
177
178 mask = mTextureEnableMask;
179 texNum = 0;
180 while (mask) {
181 if (mask & 1) {
182 switch(mEnvModes[texNum]) {
183 case RS_TEX_ENV_MODE_REPLACE:
184 mShader.append(" col = texture2D(uni_Tex0, varTex0.xy);\n");
185 break;
186 case RS_TEX_ENV_MODE_MODULATE:
187 mShader.append(" col *= texture2D(uni_Tex0, varTex0.xy);\n");
188 break;
189 case RS_TEX_ENV_MODE_DECAL:
190 mShader.append(" col = texture2D(uni_Tex0, varTex0.xy);\n");
191 break;
192 }
193
194 }
195 mask >>= 1;
196 texNum++;
197 }
198
199 //mShader.append(" col.a = 1.0;\n");
200 //mShader.append(" col.r = 0.5;\n");
201
202 mShader.append(" gl_FragColor = col;\n");
203 mShader.append("}\n");
204}
Jason Sams326e0dd2009-05-22 14:03:28 -0700205
206void ProgramFragment::bindTexture(uint32_t slot, Allocation *a)
207{
208 if (slot >= MAX_TEXTURE) {
209 LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE");
210 return;
211 }
212
Jason Sams334fd9a2009-07-02 15:09:27 -0700213 //LOGE("bindtex %i %p", slot, a);
Jason Sams326e0dd2009-05-22 14:03:28 -0700214 mTextures[slot].set(a);
Jason Samscfb1d112009-08-05 13:57:03 -0700215 mDirty = true;
Jason Sams326e0dd2009-05-22 14:03:28 -0700216}
217
218void ProgramFragment::bindSampler(uint32_t slot, Sampler *s)
219{
220 if (slot >= MAX_TEXTURE) {
221 LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE");
222 return;
223 }
224
225 mSamplers[slot].set(s);
Jason Samscfb1d112009-08-05 13:57:03 -0700226 mDirty = true;
Jason Sams326e0dd2009-05-22 14:03:28 -0700227}
228
229void ProgramFragment::setType(uint32_t slot, const Element *e, uint32_t dim)
230{
231 if (slot >= MAX_TEXTURE) {
232 LOGE("Attempt to setType to a slot > MAX_TEXTURE");
233 return;
234 }
235
236 if (dim >= 4) {
237 LOGE("Attempt to setType to a dimension > 3");
238 return;
239 }
240
241 mTextureFormats[slot].set(e);
242 mTextureDimensions[slot] = dim;
243}
244
245void ProgramFragment::setEnvMode(uint32_t slot, RsTexEnvMode env)
246{
247 if (slot >= MAX_TEXTURE) {
248 LOGE("Attempt to setEnvMode to a slot > MAX_TEXTURE");
249 return;
250 }
251
252 mEnvModes[slot] = env;
253}
254
255void ProgramFragment::setTexEnable(uint32_t slot, bool enable)
256{
257 if (slot >= MAX_TEXTURE) {
258 LOGE("Attempt to setEnvMode to a slot > MAX_TEXTURE");
259 return;
260 }
261
262 uint32_t bit = 1 << slot;
263 mTextureEnableMask &= ~bit;
264 if (enable) {
265 mTextureEnableMask |= bit;
266 }
267}
268
Jason Samsc460e552009-11-25 13:22:07 -0800269void ProgramFragment::init(Context *rsc)
270{
271 mUniformCount = 2;
272 mUniformNames[0].setTo("uni_Tex0");
273 mUniformNames[1].setTo("uni_Tex1");
Jason Sams326e0dd2009-05-22 14:03:28 -0700274
Jason Samsc460e552009-11-25 13:22:07 -0800275 createShader();
276}
Jason Sams326e0dd2009-05-22 14:03:28 -0700277
278ProgramFragmentState::ProgramFragmentState()
279{
280 mPF = NULL;
281}
282
283ProgramFragmentState::~ProgramFragmentState()
284{
285 delete mPF;
286
287}
288
Jason Sams8ce125b2009-06-17 16:52:59 -0700289void ProgramFragmentState::init(Context *rsc, int32_t w, int32_t h)
290{
Jason Samse514b452009-09-25 14:51:22 -0700291 ProgramFragment *pf = new ProgramFragment(rsc, NULL, NULL, false);
Jason Sams8ce125b2009-06-17 16:52:59 -0700292 mDefault.set(pf);
Jason Samsc460e552009-11-25 13:22:07 -0800293 pf->init(rsc);
Jason Sams8ce125b2009-06-17 16:52:59 -0700294}
Jason Sams326e0dd2009-05-22 14:03:28 -0700295
Jason Samsf2649a92009-09-25 16:37:33 -0700296void ProgramFragmentState::deinit(Context *rsc)
297{
298 mDefault.clear();
299 mLast.clear();
300}
301
Jason Sams326e0dd2009-05-22 14:03:28 -0700302
303namespace android {
304namespace renderscript {
305
Jason Samse0158412009-08-20 16:10:36 -0700306void rsi_ProgramFragmentBegin(Context * rsc, RsElement in, RsElement out, bool pointSpriteEnable)
Jason Sams326e0dd2009-05-22 14:03:28 -0700307{
308 delete rsc->mStateFragment.mPF;
Jason Samse514b452009-09-25 14:51:22 -0700309 rsc->mStateFragment.mPF = new ProgramFragment(rsc, (Element *)in, (Element *)out, pointSpriteEnable);
Jason Sams326e0dd2009-05-22 14:03:28 -0700310}
311
312void rsi_ProgramFragmentBindTexture(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsAllocation a)
313{
314 ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
315 pf->bindTexture(slot, static_cast<Allocation *>(a));
Jason Sams326e0dd2009-05-22 14:03:28 -0700316}
317
318void rsi_ProgramFragmentBindSampler(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsSampler s)
319{
320 ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
321 pf->bindSampler(slot, static_cast<Sampler *>(s));
Jason Sams326e0dd2009-05-22 14:03:28 -0700322}
323
Jason Samse0158412009-08-20 16:10:36 -0700324void rsi_ProgramFragmentSetSlot(Context *rsc, uint32_t slot, bool enable, RsTexEnvMode env, RsType vt)
Jason Sams326e0dd2009-05-22 14:03:28 -0700325{
326 const Type *t = static_cast<const Type *>(vt);
Jason Samse0158412009-08-20 16:10:36 -0700327 if (t) {
328 uint32_t dim = 1;
329 if (t->getDimY()) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700330 dim ++;
Jason Samse0158412009-08-20 16:10:36 -0700331 if (t->getDimZ()) {
332 dim ++;
333 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700334 }
Jason Samse0158412009-08-20 16:10:36 -0700335 rsc->mStateFragment.mPF->setType(slot, t->getElement(), dim);
Jason Sams326e0dd2009-05-22 14:03:28 -0700336 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700337 rsc->mStateFragment.mPF->setEnvMode(slot, env);
Jason Sams326e0dd2009-05-22 14:03:28 -0700338 rsc->mStateFragment.mPF->setTexEnable(slot, enable);
339}
340
341RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc)
342{
343 ProgramFragment *pf = rsc->mStateFragment.mPF;
Jason Sams9397e302009-08-27 20:23:34 -0700344 pf->incUserRef();
Jason Samsc460e552009-11-25 13:22:07 -0800345 pf->init(rsc);
Jason Sams326e0dd2009-05-22 14:03:28 -0700346 rsc->mStateFragment.mPF = 0;
347 return pf;
348}
349
Jason Sams326e0dd2009-05-22 14:03:28 -0700350
351}
352}
353