rsdFrameBuffer.cpp revision da6d34a5a6ece8c30d20673b9b6ff07d8c91768b
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" 20da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 21da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk#include "rsContext.h" 22da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk#include "rsFBOCache.h" 23da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 24da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk#include <GLES2/gl2.h> 25da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk#include <GLES2/gl2ext.h> 26da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 27da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukusing namespace android; 28da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukusing namespace android::renderscript; 29da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 30da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukstruct DrvFrameBuffer { 31da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk GLuint mFBOId; 32da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk}; 33da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 34da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukvoid checkError(const Context *rsc) { 35da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk GLenum status; 36da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 37da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk switch (status) { 38da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk case GL_FRAMEBUFFER_COMPLETE: 39da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk break; 40da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: 41da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk rsc->setError(RS_ERROR_BAD_VALUE, 42da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk "Unable to set up render Target: RFRAMEBUFFER_INCOMPLETE_ATTACHMENT"); 43da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk break; 44da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: 45da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk rsc->setError(RS_ERROR_BAD_VALUE, 46da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"); 47da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk break; 48da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: 49da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk rsc->setError(RS_ERROR_BAD_VALUE, 50da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"); 51da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk break; 52da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk case GL_FRAMEBUFFER_UNSUPPORTED: 53da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk rsc->setError(RS_ERROR_BAD_VALUE, 54da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk "Unable to set up render Target: GL_FRAMEBUFFER_UNSUPPORTED"); 55da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk break; 56da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } 57da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk} 58da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 59da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 60da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukvoid setDepthAttachment(const Context *rsc, const FBOCache *fb) { 61da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk if (fb->mHal.state.depthTarget.get() != NULL) { 62da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk if (fb->mHal.state.depthTarget->getIsTexture()) { 63da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk uint32_t texID = fb->mHal.state.depthTarget->getTextureID(); 64da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 65da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk GL_TEXTURE_2D, texID, 0); 66da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } else { 67da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk uint32_t texID = fb->mHal.state.depthTarget->getRenderTargetID(); 68da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 69da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk GL_RENDERBUFFER, texID); 70da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } 71da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } else { 72da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk // Reset last attachment 73da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 74da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk GL_RENDERBUFFER, 0); 75da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 76da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk GL_TEXTURE_2D, 0, 0); 77da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } 78da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk} 79da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 80da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukvoid setColorAttachment(const Context *rsc, const FBOCache *fb) { 81da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk // Now attach color targets 82da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk for (uint32_t i = 0; i < fb->mHal.state.colorTargetsCount; i ++) { 83da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk uint32_t texID = 0; 84da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk if (fb->mHal.state.colorTargets[i].get() != NULL) { 85da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk if (fb->mHal.state.colorTargets[i]->getIsTexture()) { 86da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk uint32_t texID = fb->mHal.state.colorTargets[i]->getTextureID(); 87da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, 88da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk GL_TEXTURE_2D, texID, 0); 89da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } else { 90da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk uint32_t texID = fb->mHal.state.depthTarget->getRenderTargetID(); 91da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, 92da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk GL_RENDERBUFFER, texID); 93da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } 94da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } else { 95da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk // Reset last attachment 96da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, 97da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk GL_RENDERBUFFER, 0); 98da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, 99da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk GL_TEXTURE_2D, 0, 0); 100da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } 101da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } 102da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk} 103da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 104da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukbool renderToFramebuffer(const FBOCache *fb) { 105da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk if (fb->mHal.state.depthTarget.get() != NULL) { 106da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk return false; 107da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } 108da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 109da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk for (uint32_t i = 0; i < fb->mHal.state.colorTargetsCount; i ++) { 110da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk if (fb->mHal.state.colorTargets[i].get() != NULL) { 111da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk return false; 112da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } 113da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } 114da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk return true; 115da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk} 116da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 117da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 118da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukbool rsdFrameBufferInit(const Context *rsc, const FBOCache *fb) { 119da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk DrvFrameBuffer *drv = (DrvFrameBuffer *)calloc(1, sizeof(DrvFrameBuffer)); 120da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk if (drv == NULL) { 121da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk return false; 122da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } 123da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk fb->mHal.drv = drv; 124da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk drv->mFBOId = 0; 125da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 126da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk return true; 127da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk} 128da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 129da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukvoid rsdFrameBufferSetActive(const Context *rsc, const FBOCache *fb) { 130da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk DrvFrameBuffer *drv = (DrvFrameBuffer *)fb->mHal.drv; 131da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 132da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk bool framebuffer = renderToFramebuffer(fb); 133da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk if (!framebuffer) { 134da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk if(drv->mFBOId == 0) { 135da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk glGenFramebuffers(1, &drv->mFBOId); 136da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } 137da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk glBindFramebuffer(GL_FRAMEBUFFER, drv->mFBOId); 138da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 139da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk setDepthAttachment(rsc, fb); 140da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk setColorAttachment(rsc, fb); 141da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 142da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk glViewport(0, 0, fb->mHal.state.colorTargets[0]->getType()->getDimX(), 143da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk fb->mHal.state.colorTargets[0]->getType()->getDimY()); 144da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 145da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk checkError(rsc); 146da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } else { 147da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk glBindFramebuffer(GL_FRAMEBUFFER, 0); 148da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk glViewport(0, 0, rsc->getWidth(), rsc->getHeight()); 149da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } 150da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk} 151da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 152da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukvoid rsdFrameBufferDestroy(const Context *rsc, const FBOCache *fb) { 153da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk DrvFrameBuffer *drv = (DrvFrameBuffer *)fb->mHal.drv; 154da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk if(drv->mFBOId != 0) { 155da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk glDeleteFramebuffers(1, &drv->mFBOId); 156da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk } 157da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 158da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk free(fb->mHal.drv); 159da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk fb->mHal.drv = NULL; 160da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk} 161da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 162da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk 163