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