rsdFrameBuffer.cpp revision eb4fe18dd88634330f9566cbb9e785d8c7ec5813
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 "rsdCore.h"
19#include "rsdFrameBuffer.h"
20#include "rsdAllocation.h"
21
22#include "rsContext.h"
23#include "rsFBOCache.h"
24
25#include <GLES2/gl2.h>
26#include <GLES2/gl2ext.h>
27
28using namespace android;
29using namespace android::renderscript;
30
31struct DrvFrameBuffer {
32    GLuint mFBOId;
33};
34
35void checkError(const Context *rsc) {
36    GLenum status;
37    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
38    switch (status) {
39    case GL_FRAMEBUFFER_COMPLETE:
40        break;
41    case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
42        rsc->setError(RS_ERROR_BAD_VALUE,
43                      "Unable to set up render Target: RFRAMEBUFFER_INCOMPLETE_ATTACHMENT");
44        break;
45    case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
46        rsc->setError(RS_ERROR_BAD_VALUE,
47                      "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
48        break;
49    case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
50        rsc->setError(RS_ERROR_BAD_VALUE,
51                      "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
52        break;
53    case GL_FRAMEBUFFER_UNSUPPORTED:
54        rsc->setError(RS_ERROR_BAD_VALUE,
55                      "Unable to set up render Target: GL_FRAMEBUFFER_UNSUPPORTED");
56        break;
57    }
58}
59
60
61void setDepthAttachment(const Context *rsc, const FBOCache *fb) {
62    if (fb->mHal.state.depthTarget.get() != NULL) {
63        DrvAllocation *drv = (DrvAllocation *)fb->mHal.state.depthTarget->mHal.drv;
64
65        if (drv->textureID) {
66            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
67                                   GL_TEXTURE_2D, drv->textureID, 0);
68        } else {
69            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
70                                      GL_RENDERBUFFER, drv->renderTargetID);
71        }
72    } else {
73        // Reset last attachment
74        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
75        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
76    }
77}
78
79void setColorAttachment(const Context *rsc, const FBOCache *fb) {
80    // Now attach color targets
81    for (uint32_t i = 0; i < fb->mHal.state.colorTargetsCount; i ++) {
82        uint32_t texID = 0;
83        if (fb->mHal.state.colorTargets[i].get() != NULL) {
84            DrvAllocation *drv = (DrvAllocation *)fb->mHal.state.colorTargets[i]->mHal.drv;
85
86            if (drv->textureID) {
87                glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
88                                       GL_TEXTURE_2D, drv->textureID, 0);
89            } else {
90                glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
91                                          GL_RENDERBUFFER, drv->renderTargetID);
92            }
93        } else {
94            // Reset last attachment
95            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
96                                      GL_RENDERBUFFER, 0);
97            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
98                                   GL_TEXTURE_2D, 0, 0);
99        }
100    }
101}
102
103bool renderToFramebuffer(const FBOCache *fb) {
104    if (fb->mHal.state.depthTarget.get() != NULL) {
105        return false;
106    }
107
108    for (uint32_t i = 0; i < fb->mHal.state.colorTargetsCount; i ++) {
109        if (fb->mHal.state.colorTargets[i].get() != NULL) {
110            return false;
111        }
112    }
113    return true;
114}
115
116
117bool rsdFrameBufferInit(const Context *rsc, const FBOCache *fb) {
118    DrvFrameBuffer *drv = (DrvFrameBuffer *)calloc(1, sizeof(DrvFrameBuffer));
119    if (drv == NULL) {
120        return false;
121    }
122    fb->mHal.drv = drv;
123    drv->mFBOId = 0;
124
125    return true;
126}
127
128void rsdFrameBufferSetActive(const Context *rsc, const FBOCache *fb) {
129    DrvFrameBuffer *drv = (DrvFrameBuffer *)fb->mHal.drv;
130
131    bool framebuffer = renderToFramebuffer(fb);
132    if (!framebuffer) {
133        if(drv->mFBOId == 0) {
134            glGenFramebuffers(1, &drv->mFBOId);
135        }
136        glBindFramebuffer(GL_FRAMEBUFFER, drv->mFBOId);
137
138        setDepthAttachment(rsc, fb);
139        setColorAttachment(rsc, fb);
140
141        glViewport(0, 0, fb->mHal.state.colorTargets[0]->getType()->getDimX(),
142                         fb->mHal.state.colorTargets[0]->getType()->getDimY());
143
144        checkError(rsc);
145    } else {
146        glBindFramebuffer(GL_FRAMEBUFFER, 0);
147        glViewport(0, 0, rsc->getWidth(), rsc->getHeight());
148    }
149}
150
151void rsdFrameBufferDestroy(const Context *rsc, const FBOCache *fb) {
152    DrvFrameBuffer *drv = (DrvFrameBuffer *)fb->mHal.drv;
153    if(drv->mFBOId != 0) {
154        glDeleteFramebuffers(1, &drv->mFBOId);
155    }
156
157    free(fb->mHal.drv);
158    fb->mHal.drv = NULL;
159}
160
161
162