blob: 78aa8cea1264b54269a378e70c47e7dc101c2653 [file] [log] [blame]
Alex Sakhartchouk7d9c5ff2011-04-01 14:19:01 -07001/*
2 * Copyright (C) 2011 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 "rsFBOCache.h"
18
19#include "rsContext.h"
20#include "rsAllocation.h"
21
22#ifndef ANDROID_RS_SERIALIZE
23#include <GLES/gl.h>
24#include <GLES2/gl2.h>
25#endif //ANDROID_RS_SERIALIZE
26
27using namespace android;
28using namespace android::renderscript;
29
30
31FBOCache::FBOCache() {
32 mFBOId = 0;
33 mDirty = false;
34 mMaxTargets = 1;
35 mColorTargets = new ObjectBaseRef<Allocation>[mMaxTargets];
36}
37
38FBOCache::~FBOCache() {
39 delete[] mColorTargets;
40#ifndef ANDROID_RS_SERIALIZE
41 if(mFBOId != 0) {
42 glDeleteFramebuffers(1, &mFBOId);
43 }
44#endif //ANDROID_RS_SERIALIZE
45}
46
47void FBOCache::bindColorTarget(Context *rsc, Allocation *a, uint32_t slot) {
48 if (slot >= mMaxTargets) {
49 LOGE("Invalid render target index");
50 return;
51 }
52 if (a != NULL) {
53 if (!a->getIsTexture()) {
54 LOGE("Invalid Color Target");
55 return;
56 }
57 if (a->getIsTexture()) {
58 if (a->getTextureID() == 0) {
59 a->deferredUploadToTexture(rsc);
60 }
61 } else if (a->getRenderTargetID() == 0) {
62 a->deferredAllocateRenderTarget(rsc);
63 }
64 }
65 mColorTargets[slot].set(a);
66 mDirty = true;
67}
68
69void FBOCache::bindDepthTarget(Context *rsc, Allocation *a) {
70 if (a != NULL) {
71 if (!a->getIsRenderTarget()) {
72 LOGE("Invalid Depth Target");
73 return;
74 }
75 if (a->getIsTexture()) {
76 if (a->getTextureID() == 0) {
77 a->deferredUploadToTexture(rsc);
78 }
79 } else if (a->getRenderTargetID() == 0) {
80 a->deferredAllocateRenderTarget(rsc);
81 }
82 }
83 mDepthTarget.set(a);
84 mDirty = true;
85}
86
87void FBOCache::resetAll(Context *) {
88 for (uint32_t i = 0; i < mMaxTargets; i ++) {
89 mColorTargets[i].set(NULL);
90 }
91 mDepthTarget.set(NULL);
92 mDirty = true;
93}
94
95bool FBOCache::renderToFramebuffer() {
96 if (mDepthTarget.get() != NULL) {
97 return false;
98 }
99
100 for (uint32_t i = 0; i < mMaxTargets; i ++) {
101 if (mColorTargets[i].get() != NULL) {
102 return false;
103 }
104 }
105 return true;
106}
107
108void FBOCache::checkError(Context *rsc) {
109 GLenum status;
110 status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
111 switch (status) {
112 case GL_FRAMEBUFFER_COMPLETE:
113 break;
114 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
115 rsc->setError(RS_ERROR_BAD_VALUE,
116 "Unable to set up render Target: RFRAMEBUFFER_INCOMPLETE_ATTACHMENT");
117 break;
118 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
119 rsc->setError(RS_ERROR_BAD_VALUE,
120 "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
121 break;
122 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
123 rsc->setError(RS_ERROR_BAD_VALUE,
124 "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
125 break;
126 case GL_FRAMEBUFFER_UNSUPPORTED:
127 rsc->setError(RS_ERROR_BAD_VALUE,
128 "Unable to set up render Target: GL_FRAMEBUFFER_UNSUPPORTED");
129 break;
130 }
131}
132
133void FBOCache::setDepthAttachment(Context *rsc) {
134#ifndef ANDROID_RS_SERIALIZE
135 if (mDepthTarget.get() != NULL) {
136 mDepthTarget->uploadCheck(rsc);
137 if (mDepthTarget->getIsTexture()) {
138 uint32_t texID = mDepthTarget->getTextureID();
139 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
140 GL_TEXTURE_2D, texID, 0);
141 } else {
142 uint32_t texID = mDepthTarget->getRenderTargetID();
143 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
144 GL_RENDERBUFFER, texID);
145 }
146 } else {
147 // Reset last attachment
148 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
149 GL_RENDERBUFFER, 0);
150 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
151 GL_TEXTURE_2D, 0, 0);
152 }
153#endif //ANDROID_RS_SERIALIZE
154}
155
156void FBOCache::setColorAttachment(Context *rsc) {
157#ifndef ANDROID_RS_SERIALIZE
158 // Now attach color targets
159 for (uint32_t i = 0; i < mMaxTargets; i ++) {
160 uint32_t texID = 0;
161 if (mColorTargets[i].get() != NULL) {
162 mColorTargets[i]->uploadCheck(rsc);
163 if (mColorTargets[i]->getIsTexture()) {
164 uint32_t texID = mColorTargets[i]->getTextureID();
165 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
166 GL_TEXTURE_2D, texID, 0);
167 } else {
168 uint32_t texID = mDepthTarget->getRenderTargetID();
169 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
170 GL_RENDERBUFFER, texID);
171 }
172 } else {
173 // Reset last attachment
174 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
175 GL_RENDERBUFFER, 0);
176 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
177 GL_TEXTURE_2D, 0, 0);
178 }
179 }
180#endif //ANDROID_RS_SERIALIZE
181}
182
183void FBOCache::setupGL2(Context *rsc) {
184#ifndef ANDROID_RS_SERIALIZE
185 if (!mDirty) {
186 return;
187 }
188
189 bool framebuffer = renderToFramebuffer();
190
191 if (!framebuffer) {
192 if(mFBOId == 0) {
193 glGenFramebuffers(1, &mFBOId);
194 }
195 glBindFramebuffer(GL_FRAMEBUFFER, mFBOId);
196
197 setDepthAttachment(rsc);
198 setColorAttachment(rsc);
199
200 glViewport(0, 0, mColorTargets[0]->getType()->getDimX(),
201 mColorTargets[0]->getType()->getDimY());
202
203 checkError(rsc);
204 } else {
205 glBindFramebuffer(GL_FRAMEBUFFER, 0);
206 glViewport(0, 0, rsc->getWidth(), rsc->getHeight());
207 }
208#endif //ANDROID_RS_SERIALIZE
209}