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 namespace android;
     27 using namespace android::renderscript;
     28 
     29 RsdFrameBufferObj::RsdFrameBufferObj() {
     30     mFBOId = 0;
     31     mWidth = 0;
     32     mHeight = 0;
     33     mColorTargetsCount = 1;
     34     mColorTargets = new DrvAllocation*[mColorTargetsCount];
     35     for (uint32_t i = 0; i < mColorTargetsCount; i ++) {
     36         mColorTargets[i] = 0;
     37     }
     38     mDepthTarget = NULL;
     39     mDirty = true;
     40 }
     41 
     42 RsdFrameBufferObj::~RsdFrameBufferObj() {
     43     if(mFBOId != 0) {
     44         glDeleteFramebuffers(1, &mFBOId);
     45     }
     46     delete [] mColorTargets;
     47 }
     48 
     49 void RsdFrameBufferObj::checkError(const Context *rsc) {
     50     GLenum status;
     51     status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
     52     switch (status) {
     53     case GL_FRAMEBUFFER_COMPLETE:
     54         break;
     55     case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
     56         rsc->setError(RS_ERROR_BAD_VALUE,
     57                       "Unable to set up render Target: RFRAMEBUFFER_INCOMPLETE_ATTACHMENT");
     58         break;
     59     case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
     60         rsc->setError(RS_ERROR_BAD_VALUE,
     61                       "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
     62         break;
     63     case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
     64         rsc->setError(RS_ERROR_BAD_VALUE,
     65                       "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
     66         break;
     67     case GL_FRAMEBUFFER_UNSUPPORTED:
     68         rsc->setError(RS_ERROR_BAD_VALUE,
     69                       "Unable to set up render Target: GL_FRAMEBUFFER_UNSUPPORTED");
     70         break;
     71     }
     72 }
     73 
     74 
     75 void RsdFrameBufferObj::setDepthAttachment() {
     76     if (mDepthTarget != NULL) {
     77         if (mDepthTarget->textureID) {
     78             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
     79                                    GL_TEXTURE_2D, mDepthTarget->textureID, 0);
     80         } else {
     81             glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
     82                                       GL_RENDERBUFFER, mDepthTarget->renderTargetID);
     83         }
     84     } else {
     85         // Reset last attachment
     86         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
     87         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
     88     }
     89 }
     90 
     91 void RsdFrameBufferObj::setColorAttachment() {
     92     // Now attach color targets
     93     for (uint32_t i = 0; i < mColorTargetsCount; i ++) {
     94         if (mColorTargets[i] != NULL) {
     95             if (mColorTargets[i]->textureID) {
     96                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
     97                                        GL_TEXTURE_2D, mColorTargets[i]->textureID, 0);
     98             } else {
     99                 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
    100                                           GL_RENDERBUFFER, mColorTargets[i]->renderTargetID);
    101             }
    102         } else {
    103             // Reset last attachment
    104             glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
    105                                       GL_RENDERBUFFER, 0);
    106             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
    107                                    GL_TEXTURE_2D, 0, 0);
    108         }
    109     }
    110 }
    111 
    112 bool RsdFrameBufferObj::renderToFramebuffer() {
    113     if (mDepthTarget != NULL) {
    114         return false;
    115     }
    116 
    117     for (uint32_t i = 0; i < mColorTargetsCount; i ++) {
    118         if (mColorTargets[i] != NULL) {
    119             return false;
    120         }
    121     }
    122     return true;
    123 }
    124 
    125 void RsdFrameBufferObj::setActive(const Context *rsc) {
    126     RsdHal *dc = (RsdHal *)rsc->mHal.drv;
    127     bool framebuffer = renderToFramebuffer();
    128 
    129     if(mColorTargets[0] && mColorTargets[0]->wnd) {
    130         rsdGLSetInternalSurface(rsc, mColorTargets[0]->wnd);
    131         EGLint width, height;
    132         eglQuerySurface(dc->gl.egl.display, dc->gl.egl.surface, EGL_WIDTH, &width);
    133         eglQuerySurface(dc->gl.egl.display, dc->gl.egl.surface, EGL_HEIGHT, &height);
    134         RSD_CALL_GL(glViewport, 0, 0, width, height);
    135     } else {
    136         if (!framebuffer) {
    137             if(mFBOId == 0) {
    138                 RSD_CALL_GL(glGenFramebuffers, 1, &mFBOId);
    139             }
    140             RSD_CALL_GL(glBindFramebuffer, GL_FRAMEBUFFER, mFBOId);
    141 
    142             if (mDirty) {
    143                 setDepthAttachment();
    144                 setColorAttachment();
    145                 mDirty = false;
    146             }
    147 
    148             RSD_CALL_GL(glViewport, 0, 0, mWidth, mHeight);
    149             checkError(rsc);
    150         } else {
    151             if(dc->gl.wndSurface != dc->gl.currentWndSurface) {
    152                 rsdGLSetInternalSurface(rsc, dc->gl.wndSurface);
    153             } else {
    154                 RSD_CALL_GL(glBindFramebuffer, GL_FRAMEBUFFER, 0);
    155             }
    156             RSD_CALL_GL(glViewport, 0, 0, rsc->getWidth(), rsc->getHeight());
    157         }
    158     }
    159 }
    160