1a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk/*
2a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * Copyright (C) 2011 The Android Open Source Project
3a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk *
4a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * Licensed under the Apache License, Version 2.0 (the "License");
5a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * you may not use this file except in compliance with the License.
6a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * You may obtain a copy of the License at
7a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk *
8a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk *      http://www.apache.org/licenses/LICENSE-2.0
9a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk *
10a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * Unless required by applicable law or agreed to in writing, software
11a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * distributed under the License is distributed on an "AS IS" BASIS,
12a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * See the License for the specific language governing permissions and
14a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * limitations under the License.
15a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk */
16a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk
17a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk
18a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk#include "rsdFrameBufferObj.h"
19a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk#include "rsdAllocation.h"
202382aba4a55c6ae74789c478eead8fbd96593321Jason Sams#include "rsdGL.h"
21b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams#include "rsdCore.h"
22a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk
23a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk#include <GLES2/gl2.h>
24a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk#include <GLES2/gl2ext.h>
25a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk
26a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchoukusing namespace android;
27a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchoukusing namespace android::renderscript;
28a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk
29a94952436aeb251f587c1bccdf94c7f75285dfe2Alex SakhartchoukRsdFrameBufferObj::RsdFrameBufferObj() {
30a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    mFBOId = 0;
31a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    mWidth = 0;
32a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    mHeight = 0;
33a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    mColorTargetsCount = 1;
34a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    mColorTargets = new DrvAllocation*[mColorTargetsCount];
35a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    for (uint32_t i = 0; i < mColorTargetsCount; i ++) {
36a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        mColorTargets[i] = 0;
37a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    }
38a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    mDepthTarget = NULL;
39a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    mDirty = true;
40a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk}
41a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk
42a94952436aeb251f587c1bccdf94c7f75285dfe2Alex SakhartchoukRsdFrameBufferObj::~RsdFrameBufferObj() {
43a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    if(mFBOId != 0) {
44a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        glDeleteFramebuffers(1, &mFBOId);
45a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    }
46a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    delete [] mColorTargets;
47a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk}
48a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk
49a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchoukvoid RsdFrameBufferObj::checkError(const Context *rsc) {
50a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    GLenum status;
51a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
52a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    switch (status) {
53a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    case GL_FRAMEBUFFER_COMPLETE:
54a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        break;
55a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
56a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        rsc->setError(RS_ERROR_BAD_VALUE,
57a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk                      "Unable to set up render Target: RFRAMEBUFFER_INCOMPLETE_ATTACHMENT");
58a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        break;
59a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
60a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        rsc->setError(RS_ERROR_BAD_VALUE,
61a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk                      "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
62a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        break;
63a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
64a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        rsc->setError(RS_ERROR_BAD_VALUE,
65a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk                      "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
66a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        break;
67a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    case GL_FRAMEBUFFER_UNSUPPORTED:
68a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        rsc->setError(RS_ERROR_BAD_VALUE,
69a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk                      "Unable to set up render Target: GL_FRAMEBUFFER_UNSUPPORTED");
70a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        break;
71a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    }
72a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk}
73a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk
74a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk
75a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchoukvoid RsdFrameBufferObj::setDepthAttachment() {
76a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    if (mDepthTarget != NULL) {
77a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        if (mDepthTarget->textureID) {
78a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
79a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk                                   GL_TEXTURE_2D, mDepthTarget->textureID, 0);
80a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        } else {
81a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
82a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk                                      GL_RENDERBUFFER, mDepthTarget->renderTargetID);
83a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        }
84a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    } else {
85a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        // Reset last attachment
86a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
87a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
88a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    }
89a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk}
90a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk
91a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchoukvoid RsdFrameBufferObj::setColorAttachment() {
92a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    // Now attach color targets
93a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    for (uint32_t i = 0; i < mColorTargetsCount; i ++) {
94a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        if (mColorTargets[i] != NULL) {
95a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk            if (mColorTargets[i]->textureID) {
96a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk                glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
97a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk                                       GL_TEXTURE_2D, mColorTargets[i]->textureID, 0);
98a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk            } else {
99a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk                glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
100a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk                                          GL_RENDERBUFFER, mColorTargets[i]->renderTargetID);
101a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk            }
102a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        } else {
103a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk            // Reset last attachment
104a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
105a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk                                      GL_RENDERBUFFER, 0);
106a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
107a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk                                   GL_TEXTURE_2D, 0, 0);
108a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        }
109a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    }
110a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk}
111a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk
112a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchoukbool RsdFrameBufferObj::renderToFramebuffer() {
113a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    if (mDepthTarget != NULL) {
114a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        return false;
115a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    }
116a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk
117a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    for (uint32_t i = 0; i < mColorTargetsCount; i ++) {
118a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        if (mColorTargets[i] != NULL) {
119a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk            return false;
120a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk        }
121a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    }
122a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    return true;
123a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk}
124a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk
125a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchoukvoid RsdFrameBufferObj::setActive(const Context *rsc) {
126b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
127a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    bool framebuffer = renderToFramebuffer();
128a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk
129b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams    if(mColorTargets[0] && mColorTargets[0]->wnd) {
130b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams        rsdGLSetInternalSurface(rsc, mColorTargets[0]->wnd);
131773d0083085ed15e3af4d336df7098d8d9646f45Alex Sakhartchouk        EGLint width, height;
132773d0083085ed15e3af4d336df7098d8d9646f45Alex Sakhartchouk        eglQuerySurface(dc->gl.egl.display, dc->gl.egl.surface, EGL_WIDTH, &width);
133773d0083085ed15e3af4d336df7098d8d9646f45Alex Sakhartchouk        eglQuerySurface(dc->gl.egl.display, dc->gl.egl.surface, EGL_HEIGHT, &height);
134773d0083085ed15e3af4d336df7098d8d9646f45Alex Sakhartchouk        RSD_CALL_GL(glViewport, 0, 0, width, height);
135a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    } else {
136b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams        if (!framebuffer) {
137b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams            if(mFBOId == 0) {
138b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams                RSD_CALL_GL(glGenFramebuffers, 1, &mFBOId);
139b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams            }
140b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams            RSD_CALL_GL(glBindFramebuffer, GL_FRAMEBUFFER, mFBOId);
141b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams
142b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams            if (mDirty) {
143b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams                setDepthAttachment();
144b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams                setColorAttachment();
145b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams                mDirty = false;
146b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams            }
147b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams
148b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams            RSD_CALL_GL(glViewport, 0, 0, mWidth, mHeight);
149b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams            checkError(rsc);
150b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams        } else {
151b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams            if(dc->gl.wndSurface != dc->gl.currentWndSurface) {
152b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams                rsdGLSetInternalSurface(rsc, dc->gl.wndSurface);
153b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams            } else {
154b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams                RSD_CALL_GL(glBindFramebuffer, GL_FRAMEBUFFER, 0);
155b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams            }
156b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams            RSD_CALL_GL(glViewport, 0, 0, rsc->getWidth(), rsc->getHeight());
157b322033c13487a174bb9c26466e9684d1ff4de8dJason Sams        }
158a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk    }
159a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk}
160