Home | History | Annotate | Download | only in surfaceflinger
      1 /*
      2  * Copyright (C) 2007 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 #include <stdlib.h>
     18 #include <stdint.h>
     19 #include <sys/types.h>
     20 
     21 #include <utils/Errors.h>
     22 #include <utils/Log.h>
     23 
     24 #include <ui/GraphicBuffer.h>
     25 
     26 #include "LayerDim.h"
     27 #include "SurfaceFlinger.h"
     28 #include "DisplayHardware/DisplayHardware.h"
     29 
     30 namespace android {
     31 // ---------------------------------------------------------------------------
     32 
     33 const uint32_t LayerDim::typeInfo = LayerBaseClient::typeInfo | 0x10;
     34 const char* const LayerDim::typeID = "LayerDim";
     35 
     36 bool LayerDim::sUseTexture;
     37 GLuint LayerDim::sTexId;
     38 EGLImageKHR LayerDim::sImage;
     39 int32_t LayerDim::sWidth;
     40 int32_t LayerDim::sHeight;
     41 
     42 // ---------------------------------------------------------------------------
     43 
     44 LayerDim::LayerDim(SurfaceFlinger* flinger, DisplayID display,
     45         const sp<Client>& client, int32_t i)
     46     : LayerBaseClient(flinger, display, client, i)
     47 {
     48 }
     49 
     50 void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h)
     51 {
     52     sTexId = -1;
     53     sImage = EGL_NO_IMAGE_KHR;
     54     sWidth = w;
     55     sHeight = h;
     56     sUseTexture = false;
     57 
     58 #if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
     59 
     60 #warning "using a texture to implement LayerDim"
     61 
     62     /* On some h/w like msm7K, it is faster to use a texture because the
     63      * software renderer will defer to copybit, for this to work we need to
     64      * use an EGLImage texture so copybit can actually make use of it.
     65      * This burns a full-screen worth of graphic memory.
     66      */
     67 
     68     const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
     69     uint32_t flags = hw.getFlags();
     70 
     71     if (LIKELY(flags & DisplayHardware::DIRECT_TEXTURE)) {
     72         sp<GraphicBuffer> buffer = new GraphicBuffer(w, h, PIXEL_FORMAT_RGB_565,
     73                  GraphicBuffer::USAGE_SW_WRITE_OFTEN |
     74                  GraphicBuffer::USAGE_HW_TEXTURE);
     75 
     76         android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
     77 
     78         glGenTextures(1, &sTexId);
     79         glBindTexture(GL_TEXTURE_2D, sTexId);
     80 
     81         EGLDisplay dpy = eglGetCurrentDisplay();
     82         sImage = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
     83                 EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)clientBuf, 0);
     84         if (sImage == EGL_NO_IMAGE_KHR) {
     85             LOGE("eglCreateImageKHR() failed. err=0x%4x", eglGetError());
     86             return;
     87         }
     88 
     89         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)sImage);
     90         GLint error = glGetError();
     91         if (error != GL_NO_ERROR) {
     92             eglDestroyImageKHR(dpy, sImage);
     93             LOGE("glEGLImageTargetTexture2DOES() failed. err=0x%4x", error);
     94             return;
     95         }
     96 
     97         // initialize the texture with zeros
     98         GGLSurface t;
     99         buffer->lock(&t, GRALLOC_USAGE_SW_WRITE_OFTEN);
    100         memset(t.data, 0, t.stride * t.height * 2);
    101         buffer->unlock();
    102         sUseTexture = true;
    103     }
    104 #endif
    105 }
    106 
    107 LayerDim::~LayerDim()
    108 {
    109 }
    110 
    111 void LayerDim::onDraw(const Region& clip) const
    112 {
    113     const State& s(drawingState());
    114     Region::const_iterator it = clip.begin();
    115     Region::const_iterator const end = clip.end();
    116     if (s.alpha>0 && (it != end)) {
    117         const DisplayHardware& hw(graphicPlane(0).displayHardware());
    118         const GGLfixed alpha = (s.alpha << 16)/255;
    119         const uint32_t fbHeight = hw.getHeight();
    120         glDisable(GL_DITHER);
    121         glEnable(GL_BLEND);
    122         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    123         glColor4x(0, 0, 0, alpha);
    124 
    125 #if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
    126         if (sUseTexture) {
    127             glBindTexture(GL_TEXTURE_2D, sTexId);
    128             glEnable(GL_TEXTURE_2D);
    129             glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    130             const GLshort texCoords[4][2] = {
    131                     { 0,  0 },
    132                     { 0,  1 },
    133                     { 1,  1 },
    134                     { 1,  0 }
    135             };
    136             glMatrixMode(GL_TEXTURE);
    137             glLoadIdentity();
    138             glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    139             glTexCoordPointer(2, GL_SHORT, 0, texCoords);
    140         } else
    141 #endif
    142         {
    143             glDisable(GL_TEXTURE_2D);
    144         }
    145 
    146         GLshort w = sWidth;
    147         GLshort h = sHeight;
    148         const GLshort vertices[4][2] = {
    149                 { 0, 0 },
    150                 { 0, h },
    151                 { w, h },
    152                 { w, 0 }
    153         };
    154         glVertexPointer(2, GL_SHORT, 0, vertices);
    155 
    156         while (it != end) {
    157             const Rect& r = *it++;
    158             const GLint sy = fbHeight - (r.top + r.height());
    159             glScissor(r.left, sy, r.width(), r.height());
    160             glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    161         }
    162     }
    163     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    164 }
    165 
    166 // ---------------------------------------------------------------------------
    167 
    168 }; // namespace android
    169