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