blob: 3ddaa37a5cb8ec2fc67c1c686e6227fffd6beea9 [file] [log] [blame]
Jason Samsd19f10d2009-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 Sams4b962e52009-06-22 17:15:15 -070020#include <GLES/gl.h>
21#include <GLES/glext.h>
Jason Samsbb51c402009-11-25 13:22:07 -080022#include <GLES2/gl2.h>
23#include <GLES2/gl2ext.h>
Jason Sams4b962e52009-06-22 17:15:15 -070024
Jason Samsd19f10d2009-05-22 14:03:28 -070025using namespace android;
26using namespace android::renderscript;
27
28
Jason Samsa9e7a052009-09-25 14:51:22 -070029ProgramFragment::ProgramFragment(Context *rsc, Element *in, Element *out, bool pointSpriteEnable) :
Jason Sams0011bcf2009-12-15 12:58:36 -080030 Program(rsc)
Jason Samsd19f10d2009-05-22 14:03:28 -070031{
Jason Sams61f08d62009-09-25 16:37:33 -070032 mAllocFile = __FILE__;
33 mAllocLine = __LINE__;
Jason Samsd19f10d2009-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 Sams25ffcdc2009-08-20 16:10:36 -070039 mPointSpriteEnable = pointSpriteEnable;
Jason Sams4244afa2009-07-02 15:09:27 -070040 mEnvModes[1] = RS_TEX_ENV_MODE_DECAL;
Jason Samsd19f10d2009-05-22 14:03:28 -070041}
42
43ProgramFragment::~ProgramFragment()
44{
45}
46
Jason Samsb13ada52009-08-25 11:34:49 -070047void ProgramFragment::setupGL(const Context *rsc, ProgramFragmentState *state)
Jason Samsd19f10d2009-05-22 14:03:28 -070048{
Jason Sams9bee51c2009-08-05 13:57:03 -070049 if ((state->mLast.get() == this) && !mDirty) {
50 return;
51 }
52 state->mLast.set(this);
53
Jason Samsd19f10d2009-05-22 14:03:28 -070054 for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
55 glActiveTexture(GL_TEXTURE0 + ct);
Jason Sams4244afa2009-07-02 15:09:27 -070056 if (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) {
Jason Samsd19f10d2009-05-22 14:03:28 -070057 glDisable(GL_TEXTURE_2D);
58 continue;
59 }
60
61 glEnable(GL_TEXTURE_2D);
Jason Samsb13ada52009-08-25 11:34:49 -070062 if (rsc->checkVersion1_1()) {
Romain Guy2d496bf2009-09-04 17:55:41 -070063 if (mPointSpriteEnable) {
64 glEnable(GL_POINT_SPRITE_OES);
65 } else {
66 glDisable(GL_POINT_SPRITE_OES);
67 }
Jason Samsb13ada52009-08-25 11:34:49 -070068 glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, mPointSpriteEnable);
69 }
Jason Sams3b7d39b2009-12-14 12:57:40 -080070 mTextures[ct]->uploadCheck(rsc);
Jason Samsd19f10d2009-05-22 14:03:28 -070071 glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
72
73 switch(mEnvModes[ct]) {
74 case RS_TEX_ENV_MODE_REPLACE:
Jason Sams4244afa2009-07-02 15:09:27 -070075 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
Jason Samsd19f10d2009-05-22 14:03:28 -070076 break;
77 case RS_TEX_ENV_MODE_MODULATE:
Jason Sams4244afa2009-07-02 15:09:27 -070078 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
Jason Samsd19f10d2009-05-22 14:03:28 -070079 break;
80 case RS_TEX_ENV_MODE_DECAL:
Jason Sams4244afa2009-07-02 15:09:27 -070081 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
Jason Samsd19f10d2009-05-22 14:03:28 -070082 break;
83 }
84
Jason Sams02fb2cb2009-05-28 15:37:57 -070085 if (mSamplers[ct].get()) {
86 mSamplers[ct]->setupGL();
87 } else {
Jason Samsfe08d992009-05-27 14:45:32 -070088 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
89 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Jason Sams4244afa2009-07-02 15:09:27 -070090 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
Jason Samsfe08d992009-05-27 14:45:32 -070091 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
Jason Sams02fb2cb2009-05-28 15:37:57 -070092 }
Jason Sams4244afa2009-07-02 15:09:27 -070093
94 // Gross hack.
95 if (ct == 2) {
96 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
97
98 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
99 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
100 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
101 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
102 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
103
104 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD);
105 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
106 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
107 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
108 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
109 }
Jason Samsd19f10d2009-05-22 14:03:28 -0700110 }
111 glActiveTexture(GL_TEXTURE0);
Jason Sams9bee51c2009-08-05 13:57:03 -0700112 mDirty = false;
Jason Samsd19f10d2009-05-22 14:03:28 -0700113}
114
Jason Samsbb51c402009-11-25 13:22:07 -0800115void ProgramFragment::setupGL2(const Context *rsc, ProgramFragmentState *state, ShaderCache *sc)
116{
117 //LOGE("sgl2 frag1 %x", glGetError());
118 if ((state->mLast.get() == this) && !mDirty) {
119 //return;
120 }
121 state->mLast.set(this);
122
123 for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
124 glActiveTexture(GL_TEXTURE0 + ct);
125 if (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) {
126 glDisable(GL_TEXTURE_2D);
127 continue;
128 }
129
Jason Sams3b7d39b2009-12-14 12:57:40 -0800130 mTextures[ct]->uploadCheck(rsc);
Jason Samsbb51c402009-11-25 13:22:07 -0800131 glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
132 if (mSamplers[ct].get()) {
133 mSamplers[ct]->setupGL();
134 } else {
135 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
136 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
137 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
138 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
139 }
140
141 glEnable(GL_TEXTURE_2D);
142 glUniform1i(sc->fragUniformSlot(ct), ct);
143 }
144
145 glActiveTexture(GL_TEXTURE0);
146 mDirty = false;
147
148 //LOGE("sgl2 frag2 %x", glGetError());
149}
150
151void ProgramFragment::loadShader() {
152 Program::loadShader(GL_FRAGMENT_SHADER);
153}
154
155void ProgramFragment::createShader()
156{
157 mShader.setTo("precision mediump float;\n");
158 mShader.append("varying vec4 varColor;\n");
159 mShader.append("varying vec4 varTex0;\n");
160
161 uint32_t mask = mTextureEnableMask;
162 uint32_t texNum = 0;
163 while (mask) {
164 if (mask & 1) {
165 char buf[64];
166 mShader.append("uniform sampler2D uni_Tex");
167 sprintf(buf, "%i", texNum);
168 mShader.append(buf);
169 mShader.append(";\n");
170 }
171 mask >>= 1;
172 texNum++;
173 }
174
175
176 mShader.append("void main() {\n");
Jason Samsbb51c402009-11-25 13:22:07 -0800177 mShader.append(" vec4 col = varColor;\n");
178
Jason Sams54c0ec12009-11-30 14:49:55 -0800179 if (mTextureEnableMask) {
180 if (mPointSpriteEnable) {
181 mShader.append(" vec2 tex0 = gl_PointCoord;\n");
182 } else {
183 mShader.append(" vec2 tex0 = varTex0.xy;\n");
184 }
185 }
186
Jason Samsbb51c402009-11-25 13:22:07 -0800187 mask = mTextureEnableMask;
188 texNum = 0;
189 while (mask) {
190 if (mask & 1) {
191 switch(mEnvModes[texNum]) {
192 case RS_TEX_ENV_MODE_REPLACE:
Jason Sams54c0ec12009-11-30 14:49:55 -0800193 mShader.append(" col = texture2D(uni_Tex0, tex0);\n");
Jason Samsbb51c402009-11-25 13:22:07 -0800194 break;
195 case RS_TEX_ENV_MODE_MODULATE:
Jason Sams54c0ec12009-11-30 14:49:55 -0800196 mShader.append(" col *= texture2D(uni_Tex0, tex0);\n");
Jason Samsbb51c402009-11-25 13:22:07 -0800197 break;
198 case RS_TEX_ENV_MODE_DECAL:
Jason Sams54c0ec12009-11-30 14:49:55 -0800199 mShader.append(" col = texture2D(uni_Tex0, tex0);\n");
Jason Samsbb51c402009-11-25 13:22:07 -0800200 break;
201 }
202
203 }
204 mask >>= 1;
205 texNum++;
206 }
207
208 //mShader.append(" col.a = 1.0;\n");
209 //mShader.append(" col.r = 0.5;\n");
210
211 mShader.append(" gl_FragColor = col;\n");
212 mShader.append("}\n");
213}
Jason Samsd19f10d2009-05-22 14:03:28 -0700214
215void ProgramFragment::bindTexture(uint32_t slot, Allocation *a)
216{
217 if (slot >= MAX_TEXTURE) {
218 LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE");
219 return;
220 }
221
Jason Sams4244afa2009-07-02 15:09:27 -0700222 //LOGE("bindtex %i %p", slot, a);
Jason Samsd19f10d2009-05-22 14:03:28 -0700223 mTextures[slot].set(a);
Jason Sams9bee51c2009-08-05 13:57:03 -0700224 mDirty = true;
Jason Samsd19f10d2009-05-22 14:03:28 -0700225}
226
227void ProgramFragment::bindSampler(uint32_t slot, Sampler *s)
228{
229 if (slot >= MAX_TEXTURE) {
230 LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE");
231 return;
232 }
233
234 mSamplers[slot].set(s);
Jason Sams9bee51c2009-08-05 13:57:03 -0700235 mDirty = true;
Jason Samsd19f10d2009-05-22 14:03:28 -0700236}
237
238void ProgramFragment::setType(uint32_t slot, const Element *e, uint32_t dim)
239{
240 if (slot >= MAX_TEXTURE) {
241 LOGE("Attempt to setType to a slot > MAX_TEXTURE");
242 return;
243 }
244
245 if (dim >= 4) {
246 LOGE("Attempt to setType to a dimension > 3");
247 return;
248 }
249
250 mTextureFormats[slot].set(e);
251 mTextureDimensions[slot] = dim;
252}
253
254void ProgramFragment::setEnvMode(uint32_t slot, RsTexEnvMode env)
255{
256 if (slot >= MAX_TEXTURE) {
257 LOGE("Attempt to setEnvMode to a slot > MAX_TEXTURE");
258 return;
259 }
260
261 mEnvModes[slot] = env;
262}
263
264void ProgramFragment::setTexEnable(uint32_t slot, bool enable)
265{
266 if (slot >= MAX_TEXTURE) {
267 LOGE("Attempt to setEnvMode to a slot > MAX_TEXTURE");
268 return;
269 }
270
271 uint32_t bit = 1 << slot;
272 mTextureEnableMask &= ~bit;
273 if (enable) {
274 mTextureEnableMask |= bit;
275 }
276}
277
Jason Samsbb51c402009-11-25 13:22:07 -0800278void ProgramFragment::init(Context *rsc)
279{
280 mUniformCount = 2;
281 mUniformNames[0].setTo("uni_Tex0");
282 mUniformNames[1].setTo("uni_Tex1");
Jason Samsd19f10d2009-05-22 14:03:28 -0700283
Jason Samsbb51c402009-11-25 13:22:07 -0800284 createShader();
285}
Jason Samsd19f10d2009-05-22 14:03:28 -0700286
287ProgramFragmentState::ProgramFragmentState()
288{
289 mPF = NULL;
290}
291
292ProgramFragmentState::~ProgramFragmentState()
293{
294 delete mPF;
295
296}
297
Jason Sams9c54bdb2009-06-17 16:52:59 -0700298void ProgramFragmentState::init(Context *rsc, int32_t w, int32_t h)
299{
Jason Samsa9e7a052009-09-25 14:51:22 -0700300 ProgramFragment *pf = new ProgramFragment(rsc, NULL, NULL, false);
Jason Sams9c54bdb2009-06-17 16:52:59 -0700301 mDefault.set(pf);
Jason Samsbb51c402009-11-25 13:22:07 -0800302 pf->init(rsc);
Jason Sams9c54bdb2009-06-17 16:52:59 -0700303}
Jason Samsd19f10d2009-05-22 14:03:28 -0700304
Jason Sams61f08d62009-09-25 16:37:33 -0700305void ProgramFragmentState::deinit(Context *rsc)
306{
307 mDefault.clear();
308 mLast.clear();
309}
310
Jason Samsd19f10d2009-05-22 14:03:28 -0700311
312namespace android {
313namespace renderscript {
314
Jason Sams25ffcdc2009-08-20 16:10:36 -0700315void rsi_ProgramFragmentBegin(Context * rsc, RsElement in, RsElement out, bool pointSpriteEnable)
Jason Samsd19f10d2009-05-22 14:03:28 -0700316{
317 delete rsc->mStateFragment.mPF;
Jason Samsa9e7a052009-09-25 14:51:22 -0700318 rsc->mStateFragment.mPF = new ProgramFragment(rsc, (Element *)in, (Element *)out, pointSpriteEnable);
Jason Samsd19f10d2009-05-22 14:03:28 -0700319}
320
321void rsi_ProgramFragmentBindTexture(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsAllocation a)
322{
323 ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
324 pf->bindTexture(slot, static_cast<Allocation *>(a));
Jason Samsd19f10d2009-05-22 14:03:28 -0700325}
326
327void rsi_ProgramFragmentBindSampler(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsSampler s)
328{
329 ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
330 pf->bindSampler(slot, static_cast<Sampler *>(s));
Jason Samsd19f10d2009-05-22 14:03:28 -0700331}
332
Jason Sams25ffcdc2009-08-20 16:10:36 -0700333void rsi_ProgramFragmentSetSlot(Context *rsc, uint32_t slot, bool enable, RsTexEnvMode env, RsType vt)
Jason Samsd19f10d2009-05-22 14:03:28 -0700334{
335 const Type *t = static_cast<const Type *>(vt);
Jason Sams25ffcdc2009-08-20 16:10:36 -0700336 if (t) {
337 uint32_t dim = 1;
338 if (t->getDimY()) {
Jason Samsd19f10d2009-05-22 14:03:28 -0700339 dim ++;
Jason Sams25ffcdc2009-08-20 16:10:36 -0700340 if (t->getDimZ()) {
341 dim ++;
342 }
Jason Samsd19f10d2009-05-22 14:03:28 -0700343 }
Jason Sams25ffcdc2009-08-20 16:10:36 -0700344 rsc->mStateFragment.mPF->setType(slot, t->getElement(), dim);
Jason Samsd19f10d2009-05-22 14:03:28 -0700345 }
Jason Samsd19f10d2009-05-22 14:03:28 -0700346 rsc->mStateFragment.mPF->setEnvMode(slot, env);
Jason Samsd19f10d2009-05-22 14:03:28 -0700347 rsc->mStateFragment.mPF->setTexEnable(slot, enable);
348}
349
Jason Sams54c0ec12009-11-30 14:49:55 -0800350void rsi_ProgramFragmentSetShader(Context *rsc, const char *txt, uint32_t len)
351{
352 rsc->mStateFragment.mPF->setShader(txt, len);
353}
354
Jason Samsd19f10d2009-05-22 14:03:28 -0700355RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc)
356{
357 ProgramFragment *pf = rsc->mStateFragment.mPF;
Jason Sams07ae4062009-08-27 20:23:34 -0700358 pf->incUserRef();
Jason Samsbb51c402009-11-25 13:22:07 -0800359 pf->init(rsc);
Jason Samsd19f10d2009-05-22 14:03:28 -0700360 rsc->mStateFragment.mPF = 0;
361 return pf;
362}
363
Jason Samsd19f10d2009-05-22 14:03:28 -0700364
365}
366}
367