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