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