rsdFrameBuffer.cpp revision da6d34a5a6ece8c30d20673b9b6ff07d8c91768b
1da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk/*
2da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk * Copyright (C) 2011 The Android Open Source Project
3da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk *
4da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk * Licensed under the Apache License, Version 2.0 (the "License");
5da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk * you may not use this file except in compliance with the License.
6da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk * You may obtain a copy of the License at
7da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk *
8da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk *      http://www.apache.org/licenses/LICENSE-2.0
9da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk *
10da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk * Unless required by applicable law or agreed to in writing, software
11da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk * distributed under the License is distributed on an "AS IS" BASIS,
12da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk * See the License for the specific language governing permissions and
14da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk * limitations under the License.
15da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk */
16da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
17da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
18da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk#include "rsdCore.h"
19da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk#include "rsdFrameBuffer.h"
20da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
21da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk#include "rsContext.h"
22da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk#include "rsFBOCache.h"
23da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
24da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk#include <GLES2/gl2.h>
25da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk#include <GLES2/gl2ext.h>
26da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
27da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukusing namespace android;
28da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukusing namespace android::renderscript;
29da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
30da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukstruct DrvFrameBuffer {
31da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    GLuint mFBOId;
32da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk};
33da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
34da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukvoid checkError(const Context *rsc) {
35da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    GLenum status;
36da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
37da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    switch (status) {
38da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    case GL_FRAMEBUFFER_COMPLETE:
39da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        break;
40da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
41da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        rsc->setError(RS_ERROR_BAD_VALUE,
42da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                      "Unable to set up render Target: RFRAMEBUFFER_INCOMPLETE_ATTACHMENT");
43da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        break;
44da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
45da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        rsc->setError(RS_ERROR_BAD_VALUE,
46da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                      "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
47da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        break;
48da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
49da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        rsc->setError(RS_ERROR_BAD_VALUE,
50da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                      "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
51da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        break;
52da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    case GL_FRAMEBUFFER_UNSUPPORTED:
53da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        rsc->setError(RS_ERROR_BAD_VALUE,
54da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                      "Unable to set up render Target: GL_FRAMEBUFFER_UNSUPPORTED");
55da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        break;
56da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    }
57da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk}
58da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
59da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
60da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukvoid setDepthAttachment(const Context *rsc, const FBOCache *fb) {
61da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    if (fb->mHal.state.depthTarget.get() != NULL) {
62da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        if (fb->mHal.state.depthTarget->getIsTexture()) {
63da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk            uint32_t texID = fb->mHal.state.depthTarget->getTextureID();
64da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
65da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                                   GL_TEXTURE_2D, texID, 0);
66da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        } else {
67da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk            uint32_t texID = fb->mHal.state.depthTarget->getRenderTargetID();
68da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
69da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                                      GL_RENDERBUFFER, texID);
70da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        }
71da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    } else {
72da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        // Reset last attachment
73da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
74da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                                  GL_RENDERBUFFER, 0);
75da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
76da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                               GL_TEXTURE_2D, 0, 0);
77da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    }
78da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk}
79da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
80da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukvoid setColorAttachment(const Context *rsc, const FBOCache *fb) {
81da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    // Now attach color targets
82da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    for (uint32_t i = 0; i < fb->mHal.state.colorTargetsCount; i ++) {
83da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        uint32_t texID = 0;
84da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        if (fb->mHal.state.colorTargets[i].get() != NULL) {
85da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk            if (fb->mHal.state.colorTargets[i]->getIsTexture()) {
86da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                uint32_t texID = fb->mHal.state.colorTargets[i]->getTextureID();
87da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
88da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                                       GL_TEXTURE_2D, texID, 0);
89da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk            } else {
90da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                uint32_t texID = fb->mHal.state.depthTarget->getRenderTargetID();
91da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
92da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                                          GL_RENDERBUFFER, texID);
93da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk            }
94da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        } else {
95da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk            // Reset last attachment
96da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
97da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                                      GL_RENDERBUFFER, 0);
98da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
99da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                                   GL_TEXTURE_2D, 0, 0);
100da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        }
101da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    }
102da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk}
103da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
104da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukbool renderToFramebuffer(const FBOCache *fb) {
105da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    if (fb->mHal.state.depthTarget.get() != NULL) {
106da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        return false;
107da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    }
108da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
109da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    for (uint32_t i = 0; i < fb->mHal.state.colorTargetsCount; i ++) {
110da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        if (fb->mHal.state.colorTargets[i].get() != NULL) {
111da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk            return false;
112da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        }
113da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    }
114da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    return true;
115da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk}
116da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
117da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
118da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukbool rsdFrameBufferInit(const Context *rsc, const FBOCache *fb) {
119da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    DrvFrameBuffer *drv = (DrvFrameBuffer *)calloc(1, sizeof(DrvFrameBuffer));
120da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    if (drv == NULL) {
121da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        return false;
122da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    }
123da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    fb->mHal.drv = drv;
124da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    drv->mFBOId = 0;
125da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
126da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    return true;
127da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk}
128da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
129da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukvoid rsdFrameBufferSetActive(const Context *rsc, const FBOCache *fb) {
130da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    DrvFrameBuffer *drv = (DrvFrameBuffer *)fb->mHal.drv;
131da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
132da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    bool framebuffer = renderToFramebuffer(fb);
133da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    if (!framebuffer) {
134da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        if(drv->mFBOId == 0) {
135da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk            glGenFramebuffers(1, &drv->mFBOId);
136da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        }
137da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        glBindFramebuffer(GL_FRAMEBUFFER, drv->mFBOId);
138da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
139da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        setDepthAttachment(rsc, fb);
140da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        setColorAttachment(rsc, fb);
141da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
142da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        glViewport(0, 0, fb->mHal.state.colorTargets[0]->getType()->getDimX(),
143da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk                         fb->mHal.state.colorTargets[0]->getType()->getDimY());
144da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
145da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        checkError(rsc);
146da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    } else {
147da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        glBindFramebuffer(GL_FRAMEBUFFER, 0);
148da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        glViewport(0, 0, rsc->getWidth(), rsc->getHeight());
149da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    }
150da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk}
151da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
152da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukvoid rsdFrameBufferDestroy(const Context *rsc, const FBOCache *fb) {
153da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    DrvFrameBuffer *drv = (DrvFrameBuffer *)fb->mHal.drv;
154da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    if(drv->mFBOId != 0) {
155da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk        glDeleteFramebuffers(1, &drv->mFBOId);
156da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    }
157da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
158da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    free(fb->mHal.drv);
159da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    fb->mHal.drv = NULL;
160da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk}
161da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
162da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
163