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