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 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 41 RsdFrameBufferObj::~RsdFrameBufferObj() { 42 if(mFBOId != 0) { 43 glDeleteFramebuffers(1, &mFBOId); 44 } 45 delete [] mColorTargets; 46 } 47 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 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 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 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 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