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