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