rsProgramFragment.cpp revision 334fd9aeacd4221fc8cd1333b2a34fb3b26b3a0d
1/*
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
20#include <GLES/gl.h>
21#include <GLES/glext.h>
22
23using namespace android;
24using namespace android::renderscript;
25
26
27ProgramFragment::ProgramFragment(Element *in, Element *out) :
28    Program(in, out)
29{
30    for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
31        mEnvModes[ct] = RS_TEX_ENV_MODE_REPLACE;
32        mTextureDimensions[ct] = 2;
33    }
34    mTextureEnableMask = 0;
35    mEnvModes[1] = RS_TEX_ENV_MODE_DECAL;
36}
37
38ProgramFragment::~ProgramFragment()
39{
40}
41
42void ProgramFragment::setupGL()
43{
44    for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
45        glActiveTexture(GL_TEXTURE0 + ct);
46        if (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) {
47            glDisable(GL_TEXTURE_2D);
48            continue;
49        }
50
51        glEnable(GL_TEXTURE_2D);
52        glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
53
54        switch(mEnvModes[ct]) {
55        case RS_TEX_ENV_MODE_REPLACE:
56            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
57            break;
58        case RS_TEX_ENV_MODE_MODULATE:
59            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
60            break;
61        case RS_TEX_ENV_MODE_DECAL:
62            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
63            break;
64        }
65
66        if (mSamplers[ct].get()) {
67            mSamplers[ct]->setupGL();
68        } else {
69            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
70            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
71            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
72            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
73        }
74
75        // Gross hack.
76        if (ct == 2) {
77            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
78
79            glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
80            glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
81            glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
82            glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
83            glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
84
85            glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD);
86            glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
87            glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
88            glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
89            glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
90        }
91    }
92
93
94    glActiveTexture(GL_TEXTURE0);
95}
96
97
98void ProgramFragment::bindTexture(uint32_t slot, Allocation *a)
99{
100    if (slot >= MAX_TEXTURE) {
101        LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE");
102        return;
103    }
104
105    //LOGE("bindtex %i %p", slot, a);
106    mTextures[slot].set(a);
107}
108
109void ProgramFragment::bindSampler(uint32_t slot, Sampler *s)
110{
111    if (slot >= MAX_TEXTURE) {
112        LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE");
113        return;
114    }
115
116    mSamplers[slot].set(s);
117}
118
119void ProgramFragment::setType(uint32_t slot, const Element *e, uint32_t dim)
120{
121    if (slot >= MAX_TEXTURE) {
122        LOGE("Attempt to setType to a slot > MAX_TEXTURE");
123        return;
124    }
125
126    if (dim >= 4) {
127        LOGE("Attempt to setType to a dimension > 3");
128        return;
129    }
130
131    mTextureFormats[slot].set(e);
132    mTextureDimensions[slot] = dim;
133}
134
135void ProgramFragment::setEnvMode(uint32_t slot, RsTexEnvMode env)
136{
137    if (slot >= MAX_TEXTURE) {
138        LOGE("Attempt to setEnvMode to a slot > MAX_TEXTURE");
139        return;
140    }
141
142    mEnvModes[slot] = env;
143}
144
145void ProgramFragment::setTexEnable(uint32_t slot, bool enable)
146{
147    if (slot >= MAX_TEXTURE) {
148        LOGE("Attempt to setEnvMode to a slot > MAX_TEXTURE");
149        return;
150    }
151
152    uint32_t bit = 1 << slot;
153    mTextureEnableMask &= ~bit;
154    if (enable) {
155        mTextureEnableMask |= bit;
156    }
157}
158
159
160
161ProgramFragmentState::ProgramFragmentState()
162{
163    mPF = NULL;
164}
165
166ProgramFragmentState::~ProgramFragmentState()
167{
168    delete mPF;
169
170}
171
172void ProgramFragmentState::init(Context *rsc, int32_t w, int32_t h)
173{
174    ProgramFragment *pf = new ProgramFragment(NULL, NULL);
175    mDefault.set(pf);
176}
177
178
179namespace android {
180namespace renderscript {
181
182void rsi_ProgramFragmentBegin(Context * rsc, RsElement in, RsElement out)
183{
184    delete rsc->mStateFragment.mPF;
185    rsc->mStateFragment.mPF = new ProgramFragment((Element *)in, (Element *)out);
186}
187
188void rsi_ProgramFragmentBindTexture(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsAllocation a)
189{
190    ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
191    pf->bindTexture(slot, static_cast<Allocation *>(a));
192    if (pf == rsc->getFragment()) {
193        pf->setupGL();
194    }
195}
196
197void rsi_ProgramFragmentBindSampler(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsSampler s)
198{
199    ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
200    pf->bindSampler(slot, static_cast<Sampler *>(s));
201
202    if (pf == rsc->getFragment()) {
203        pf->setupGL();
204    }
205}
206
207void rsi_ProgramFragmentSetType(Context *rsc, uint32_t slot, RsType vt)
208{
209    const Type *t = static_cast<const Type *>(vt);
210    uint32_t dim = 1;
211    if (t->getDimY()) {
212        dim ++;
213        if (t->getDimZ()) {
214            dim ++;
215        }
216    }
217
218    rsc->mStateFragment.mPF->setType(slot, t->getElement(), dim);
219}
220
221void rsi_ProgramFragmentSetEnvMode(Context *rsc, uint32_t slot, RsTexEnvMode env)
222{
223    rsc->mStateFragment.mPF->setEnvMode(slot, env);
224}
225
226void rsi_ProgramFragmentSetTexEnable(Context *rsc, uint32_t slot, bool enable)
227{
228    rsc->mStateFragment.mPF->setTexEnable(slot, enable);
229}
230
231RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc)
232{
233    ProgramFragment *pf = rsc->mStateFragment.mPF;
234    pf->incRef();
235    rsc->mStateFragment.mPF = 0;
236    return pf;
237}
238
239void rsi_ProgramFragmentDestroy(Context *rsc, RsProgramFragment vpf)
240{
241    ProgramFragment *pf = (ProgramFragment *)vpf;
242    if (pf->getName()) {
243        rsc->removeName(pf);
244    }
245    pf->decRef();
246}
247
248
249}
250}
251
252