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