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