rsdFrameBufferObj.cpp revision a94952436aeb251f587c1bccdf94c7f75285dfe2
1/*
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
18#include "rsdFrameBufferObj.h"
19#include "rsdAllocation.h"
20
21#include <GLES2/gl2.h>
22#include <GLES2/gl2ext.h>
23
24using namespace android;
25using namespace android::renderscript;
26
27RsdFrameBufferObj::RsdFrameBufferObj() {
28    mFBOId = 0;
29    mWidth = 0;
30    mHeight = 0;
31    mColorTargetsCount = 1;
32    mColorTargets = new DrvAllocation*[mColorTargetsCount];
33    for (uint32_t i = 0; i < mColorTargetsCount; i ++) {
34        mColorTargets[i] = 0;
35    }
36    mDepthTarget = NULL;
37    mDirty = true;
38}
39
40RsdFrameBufferObj::~RsdFrameBufferObj() {
41    if(mFBOId != 0) {
42        glDeleteFramebuffers(1, &mFBOId);
43    }
44    delete [] mColorTargets;
45}
46
47void RsdFrameBufferObj::checkError(const Context *rsc) {
48    GLenum status;
49    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
50    switch (status) {
51    case GL_FRAMEBUFFER_COMPLETE:
52        break;
53    case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
54        rsc->setError(RS_ERROR_BAD_VALUE,
55                      "Unable to set up render Target: RFRAMEBUFFER_INCOMPLETE_ATTACHMENT");
56        break;
57    case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
58        rsc->setError(RS_ERROR_BAD_VALUE,
59                      "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
60        break;
61    case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
62        rsc->setError(RS_ERROR_BAD_VALUE,
63                      "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
64        break;
65    case GL_FRAMEBUFFER_UNSUPPORTED:
66        rsc->setError(RS_ERROR_BAD_VALUE,
67                      "Unable to set up render Target: GL_FRAMEBUFFER_UNSUPPORTED");
68        break;
69    }
70}
71
72
73void RsdFrameBufferObj::setDepthAttachment() {
74    if (mDepthTarget != NULL) {
75        if (mDepthTarget->textureID) {
76            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
77                                   GL_TEXTURE_2D, mDepthTarget->textureID, 0);
78        } else {
79            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
80                                      GL_RENDERBUFFER, mDepthTarget->renderTargetID);
81        }
82    } else {
83        // Reset last attachment
84        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
85        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
86    }
87}
88
89void RsdFrameBufferObj::setColorAttachment() {
90    // Now attach color targets
91    for (uint32_t i = 0; i < mColorTargetsCount; i ++) {
92        if (mColorTargets[i] != NULL) {
93            if (mColorTargets[i]->textureID) {
94                glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
95                                       GL_TEXTURE_2D, mColorTargets[i]->textureID, 0);
96            } else {
97                glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
98                                          GL_RENDERBUFFER, mColorTargets[i]->renderTargetID);
99            }
100        } else {
101            // Reset last attachment
102            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
103                                      GL_RENDERBUFFER, 0);
104            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
105                                   GL_TEXTURE_2D, 0, 0);
106        }
107    }
108}
109
110bool RsdFrameBufferObj::renderToFramebuffer() {
111    if (mDepthTarget != NULL) {
112        return false;
113    }
114
115    for (uint32_t i = 0; i < mColorTargetsCount; i ++) {
116        if (mColorTargets[i] != NULL) {
117            return false;
118        }
119    }
120    return true;
121}
122
123void RsdFrameBufferObj::setActive(const Context *rsc) {
124    bool framebuffer = renderToFramebuffer();
125    if (!framebuffer) {
126        if(mFBOId == 0) {
127            glGenFramebuffers(1, &mFBOId);
128        }
129        glBindFramebuffer(GL_FRAMEBUFFER, mFBOId);
130
131        if (mDirty) {
132            setDepthAttachment();
133            setColorAttachment();
134            mDirty = false;
135        }
136
137        glViewport(0, 0, mWidth, mHeight);
138        checkError(rsc);
139    } else {
140        glBindFramebuffer(GL_FRAMEBUFFER, 0);
141        glViewport(0, 0, rsc->getWidth(), rsc->getHeight());
142    }
143}
144