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