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 #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