Home | History | Annotate | Download | only in driver
      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 
     22 #include <GLES2/gl2.h>
     23 #include <GLES2/gl2ext.h>
     24 
     25 using namespace android;
     26 using namespace android::renderscript;
     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 = NULL;
     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 != NULL) {
     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] != NULL) {
     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 != NULL) {
    113         return false;
    114     }
    115 
    116     for (uint32_t i = 0; i < mColorTargetsCount; i ++) {
    117         if (mColorTargets[i] != NULL) {
    118             return false;
    119         }
    120     }
    121     return true;
    122 }
    123 
    124 void RsdFrameBufferObj::setActive(const Context *rsc) {
    125     bool framebuffer = renderToFramebuffer();
    126     if (!framebuffer) {
    127         if(mFBOId == 0) {
    128             RSD_CALL_GL(glGenFramebuffers, 1, &mFBOId);
    129         }
    130         RSD_CALL_GL(glBindFramebuffer, GL_FRAMEBUFFER, mFBOId);
    131 
    132         if (mDirty) {
    133             setDepthAttachment();
    134             setColorAttachment();
    135             mDirty = false;
    136         }
    137 
    138         RSD_CALL_GL(glViewport, 0, 0, mWidth, mHeight);
    139         checkError(rsc);
    140     } else {
    141         RSD_CALL_GL(glBindFramebuffer, GL_FRAMEBUFFER, 0);
    142         RSD_CALL_GL(glViewport, 0, 0, rsc->getWidth(), rsc->getHeight());
    143     }
    144 }
    145