Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1293a8eb authored by Mathias Agopian's avatar Mathias Agopian
Browse files

More clean-up. Get rid off the "blur" effect in SurfaceFlinger

For multiple reason, this effect is not maintainable and was never
used due to its abysmal performance. it'll be resurected when it can be
implemented efficiently.

Change-Id: Id4222c9b86c629275cdec18873ef07be8723b6d2
parent 0a757814
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -6,11 +6,9 @@ LOCAL_SRC_FILES:= \
    DisplayHardware/DisplayHardware.cpp \
    DisplayHardware/DisplayHardwareBase.cpp \
    DisplayHardware/HWComposer.cpp \
    BlurFilter.cpp.arm \
    GLExtensions.cpp \
    Layer.cpp \
    LayerBase.cpp \
    LayerBlur.cpp \
    LayerDim.cpp \
    MessageQueue.cpp \
    SurfaceFlinger.cpp \
+0 −376
Original line number Diff line number Diff line
/* 
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License"); 
** you may not use this file except in compliance with the License. 
** You may obtain a copy of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** Unless required by applicable law or agreed to in writing, software 
** distributed under the License is distributed on an "AS IS" BASIS, 
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
** See the License for the specific language governing permissions and 
** limitations under the License.
*/


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <utils/Errors.h>

#include <pixelflinger/pixelflinger.h>

#include "clz.h"

#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))

namespace android {

#if BYTE_ORDER == LITTLE_ENDIAN
inline uint32_t BLUR_RGBA_TO_HOST(uint32_t v) {
    return v;
}
inline uint32_t BLUR_HOST_TO_RGBA(uint32_t v) {
    return v;
}
#else
inline uint32_t BLUR_RGBA_TO_HOST(uint32_t v) {
    return (v<<24) | (v>>24) | ((v<<8)&0xff0000) | ((v>>8)&0xff00);
}
inline uint32_t BLUR_HOST_TO_RGBA(uint32_t v) {
    return (v<<24) | (v>>24) | ((v<<8)&0xff0000) | ((v>>8)&0xff00);
}
#endif

const int BLUR_DITHER_BITS = 6;  // dither weights stored on 6 bits
const int BLUR_DITHER_ORDER_SHIFT= 3;
const int BLUR_DITHER_ORDER      = (1<<BLUR_DITHER_ORDER_SHIFT);
const int BLUR_DITHER_SIZE       = BLUR_DITHER_ORDER * BLUR_DITHER_ORDER;
const int BLUR_DITHER_MASK       = BLUR_DITHER_ORDER-1;

static const uint8_t gDitherMatrix[BLUR_DITHER_SIZE] = {
     0, 32,  8, 40,  2, 34, 10, 42,
    48, 16, 56, 24, 50, 18, 58, 26,
    12, 44,  4, 36, 14, 46,  6, 38,
    60, 28, 52, 20, 62, 30, 54, 22,
     3, 35, 11, 43,  1, 33,  9, 41,
    51, 19, 59, 27, 49, 17, 57, 25,
    15, 47,  7, 39, 13, 45,  5, 37,
    63, 31, 55, 23, 61, 29, 53, 21
};


template <int FACTOR = 0>
struct BlurColor565
{
    typedef uint16_t type;
    int r, g, b;    
    inline BlurColor565() { }
    inline BlurColor565(uint16_t v) {
        r = v >> 11;
        g = (v >> 5) & 0x3E;
        b = v & 0x1F;
    }
    inline void clear() { r=g=b=0; }
    inline uint16_t to(int shift, int last, int dither) const {
        int R = r;
        int G = g;
        int B = b;
        if  (UNLIKELY(last)) {
            if (FACTOR>0) {
                int L = (R+G+B)>>1;
                R += (((L>>1) - R) * FACTOR) >> 8;
                G += (((L   ) - G) * FACTOR) >> 8;
                B += (((L>>1) - B) * FACTOR) >> 8;
            }
            R += (dither << shift) >> BLUR_DITHER_BITS;
            G += (dither << shift) >> BLUR_DITHER_BITS;
            B += (dither << shift) >> BLUR_DITHER_BITS;
        }
        R >>= shift;
        G >>= shift;
        B >>= shift;
        return (R<<11) | (G<<5) | B;
    }    
    inline BlurColor565& operator += (const BlurColor565& rhs) {
        r += rhs.r;
        g += rhs.g;
        b += rhs.b;
        return *this;
    }
    inline BlurColor565& operator -= (const BlurColor565& rhs) {
        r -= rhs.r;
        g -= rhs.g;
        b -= rhs.b;
        return *this;
    }
};

template <int FACTOR = 0>
struct BlurColor888X
{
    typedef uint32_t type;
    int r, g, b;    
    inline BlurColor888X() { }
    inline BlurColor888X(uint32_t v) {
        v = BLUR_RGBA_TO_HOST(v);
        r = v & 0xFF;
        g = (v >>  8) & 0xFF;
        b = (v >> 16) & 0xFF;
    }
    inline void clear() { r=g=b=0; }
    inline uint32_t to(int shift, int last, int dither) const {
        int R = r;
        int G = g;
        int B = b;
        if  (UNLIKELY(last)) {
            if (FACTOR>0) {
                int L = (R+G+G+B)>>2;
                R += ((L - R) * FACTOR) >> 8;
                G += ((L - G) * FACTOR) >> 8;
                B += ((L - B) * FACTOR) >> 8;
            }
        }
        R >>= shift;
        G >>= shift;
        B >>= shift;
        return BLUR_HOST_TO_RGBA((0xFF<<24) | (B<<16) | (G<<8) | R);
    }    
    inline BlurColor888X& operator += (const BlurColor888X& rhs) {
        r += rhs.r;
        g += rhs.g;
        b += rhs.b;
        return *this;
    }
    inline BlurColor888X& operator -= (const BlurColor888X& rhs) {
        r -= rhs.r;
        g -= rhs.g;
        b -= rhs.b;
        return *this;
    }
};

struct BlurGray565
{
    typedef uint16_t type;
    int l;    
    inline BlurGray565() { }
    inline BlurGray565(uint16_t v) {
        int r = v >> 11;
        int g = (v >> 5) & 0x3F;
        int b = v & 0x1F;
        l = (r + g + b + 1)>>1;
    }
    inline void clear() { l=0; }
    inline uint16_t to(int shift, int last, int dither) const {
        int L = l;
        if  (UNLIKELY(last)) {
            L += (dither << shift) >> BLUR_DITHER_BITS;
        }
        L >>= shift;
        return ((L>>1)<<11) | (L<<5) | (L>>1);
    }
    inline BlurGray565& operator += (const BlurGray565& rhs) {
        l += rhs.l;
        return *this;
    }
    inline BlurGray565& operator -= (const BlurGray565& rhs) {
        l -= rhs.l;
        return *this;
    }
};

struct BlurGray8888
{
    typedef uint32_t type;
    int l, a;    
    inline BlurGray8888() { }
    inline BlurGray8888(uint32_t v) {
        v = BLUR_RGBA_TO_HOST(v);
        int r = v & 0xFF;
        int g = (v >>  8) & 0xFF;
        int b = (v >> 16) & 0xFF;
        a = v >> 24;
        l = r + g + g + b;
    }    
    inline void clear() { l=a=0; }
    inline uint32_t to(int shift, int last, int dither) const {
        int L = l;
        int A = a;
        if  (UNLIKELY(last)) {
            L += (dither << (shift+2)) >> BLUR_DITHER_BITS;
            A += (dither << shift) >> BLUR_DITHER_BITS;
        }
        L >>= (shift+2);
        A >>= shift;
        return BLUR_HOST_TO_RGBA((A<<24) | (L<<16) | (L<<8) | L);
    }
    inline BlurGray8888& operator += (const BlurGray8888& rhs) {
        l += rhs.l;
        a += rhs.a;
        return *this;
    }
    inline BlurGray8888& operator -= (const BlurGray8888& rhs) {
        l -= rhs.l;
        a -= rhs.a;
        return *this;
    }
};


template<typename PIXEL>
static status_t blurFilter(
        GGLSurface const* dst,
        GGLSurface const* src,
        int kernelSizeUser,
        int repeat)
{
    typedef typename PIXEL::type TYPE;

    const int shift             = 31 - clz(kernelSizeUser);
    const int areaShift         = shift*2;
    const int kernelSize        = 1<<shift;
    const int kernelHalfSize    = kernelSize/2;
    const int mask              = kernelSize-1;
    const int w                 = src->width;
    const int h                 = src->height;
    const uint8_t* ditherMatrix = gDitherMatrix;

    // we need a temporary buffer to store one line of blurred columns
    // as well as kernelSize lines of source pixels organized as a ring buffer.
    void* const temporary_buffer = malloc(
            (w + kernelSize) * sizeof(PIXEL) +
            (src->stride * kernelSize) * sizeof(TYPE));
    if (!temporary_buffer)
        return NO_MEMORY;

    PIXEL* const sums = (PIXEL*)temporary_buffer;
    TYPE* const scratch = (TYPE*)(sums + w + kernelSize);

    // Apply the blur 'repeat' times, this is used to approximate
    // gaussian blurs. 3 times gives good results.
    for (int k=0 ; k<repeat ; k++) {

        // Clear the columns sums for this round
        memset(sums, 0, (w + kernelSize) * sizeof(PIXEL));
        TYPE* head;
        TYPE pixel;
        PIXEL current;

        // Since we're going to override the source data we need
        // to copy it in a temporary buffer. Only kernelSize lines are
        // required. But since we start in the center of the kernel,
        // we only copy half of the data, and fill the rest with zeros
        // (assuming black/transparent pixels).
        memcpy( scratch + src->stride*kernelHalfSize,
                src->data,
                src->stride*kernelHalfSize*sizeof(TYPE));

        // sum half of each column, because we assume the first half is
        // zeros (black/transparent).
        for (int y=0 ; y<kernelHalfSize ; y++) {
            head = (TYPE*)src->data + y*src->stride;
            for (int x=0 ; x<w ; x++)
                sums[x] += PIXEL( *head++ );
        }

        for (int y=0 ; y<h ; y++) {
            TYPE* fb = (TYPE*)dst->data + y*dst->stride;

            // compute the dither matrix line
            uint8_t const * ditherY = ditherMatrix
                    + (y & BLUR_DITHER_MASK)*BLUR_DITHER_ORDER;

            // Horizontal blur pass on the columns sums
            int count, dither, x=0;
            PIXEL const * out= sums;
            PIXEL const * in = sums;
            current.clear();

            count = kernelHalfSize;
            do {
                current += *in;
                in++;
            } while (--count);
            
            count = kernelHalfSize;
            do {
                current += *in;
                dither = *(ditherY + ((x++)&BLUR_DITHER_MASK));
                *fb++ = current.to(areaShift, k==repeat-1, dither);
                in++;
            } while (--count);

            count = w-kernelSize;
            do {
                current += *in;
                current -= *out;
                dither = *(ditherY + ((x++)&BLUR_DITHER_MASK));
                *fb++ = current.to(areaShift, k==repeat-1, dither);
                in++, out++;
            } while (--count);

            count = kernelHalfSize;
            do {
                current -= *out;
                dither = *(ditherY + ((x++)&BLUR_DITHER_MASK));
                *fb++ = current.to(areaShift, k==repeat-1, dither);
                out++;
            } while (--count);

            // vertical blur pass, subtract the oldest line from each columns
            // and add a new line. Subtract or add zeros at the top
            // and bottom edges.
            TYPE* const tail = scratch + (y & mask) * src->stride;
            if (y >= kernelHalfSize) {
                for (int x=0 ; x<w ; x++)
                    sums[x] -= PIXEL( tail[x] );
            }
            if (y < h-kernelSize) {
                memcpy( tail,
                        (TYPE*)src->data + (y+kernelHalfSize)*src->stride,
                        src->stride*sizeof(TYPE));
                for (int x=0 ; x<w ; x++)
                    sums[x] += PIXEL( tail[x] );
            }
        }

        // The subsequent passes are always done in-place.
        src = dst;
    }
    
    free(temporary_buffer);

    return NO_ERROR;
}

template status_t blurFilter< BlurColor565<0x80> >(
        GGLSurface const* dst,
        GGLSurface const* src,
        int kernelSizeUser,
        int repeat);

status_t blurFilter(
        GGLSurface const* image,
        int kernelSizeUser,
        int repeat)
{
    status_t err = BAD_VALUE;
    if (image->format == GGL_PIXEL_FORMAT_RGB_565) {
        err = blurFilter< BlurColor565<0x80> >(image, image, kernelSizeUser, repeat);
    } else if (image->format == GGL_PIXEL_FORMAT_RGBX_8888) {
        err = blurFilter< BlurColor888X<0x80> >(image, image, kernelSizeUser, repeat);
    }
    return err;
}

} // namespace android

//err = blur< BlurColor565<0x80> >(dst, src, kernelSizeUser, repeat);
//err = blur<BlurGray565>(dst, src, kernelSizeUser, repeat);
//err = blur<BlurGray8888>(dst, src, kernelSizeUser, repeat);
+0 −35
Original line number Diff line number Diff line
/* 
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License"); 
** you may not use this file except in compliance with the License. 
** You may obtain a copy of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** Unless required by applicable law or agreed to in writing, software 
** distributed under the License is distributed on an "AS IS" BASIS, 
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
** See the License for the specific language governing permissions and 
** limitations under the License.
*/

#ifndef ANDROID_BLUR_FILTER_H
#define ANDROID_BLUR_FILTER_H

#include <stdint.h>
#include <utils/Errors.h>

#include <pixelflinger/pixelflinger.h>

namespace android {

status_t blurFilter(
        GGLSurface const* image,
        int kernelSizeUser,
        int repeat);

} // namespace android

#endif // ANDROID_BLUR_FILTER_H
+0 −251
Original line number Diff line number Diff line
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>

#include <utils/Errors.h>
#include <utils/Log.h>

#include <GLES/gl.h>
#include <GLES/glext.h>

#include "clz.h"
#include "BlurFilter.h"
#include "LayerBlur.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"

namespace android {
// ---------------------------------------------------------------------------

LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
        const sp<Client>& client)
    : LayerBaseClient(flinger, display, client), mCacheDirty(true),
          mRefreshCache(true), mCacheAge(0), mTextureName(-1U),
          mWidthScale(1.0f), mHeightScale(1.0f),
          mBlurFormat(GGL_PIXEL_FORMAT_RGB_565)
{
}

LayerBlur::~LayerBlur()
{
    if (mTextureName != -1U) {
        glDeleteTextures(1, &mTextureName);
    }
}

void LayerBlur::setVisibleRegion(const Region& visibleRegion)
{
    LayerBaseClient::setVisibleRegion(visibleRegion);
    if (visibleRegionScreen.isEmpty()) {
        if (mTextureName != -1U) {
            // We're not visible, free the texture up.
            glBindTexture(GL_TEXTURE_2D, 0);
            glDeleteTextures(1, &mTextureName);
            mTextureName = -1U;
        }
    }
}

uint32_t LayerBlur::doTransaction(uint32_t flags)
{
    // we're doing a transaction, refresh the cache!
    if (!mFlinger->isFrozen()) {
        mRefreshCache = true;
        mCacheDirty = true;
        flags |= eVisibleRegion;
        this->contentDirty = true;
    }
    return LayerBase::doTransaction(flags);    
}

void LayerBlur::unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion)
{
    // this code-path must be as tight as possible, it's called each time
    // the screen is composited.
    if (UNLIKELY(!visibleRegionScreen.isEmpty())) {
        // if anything visible below us is invalidated, the cache becomes dirty
        if (!mCacheDirty && 
                !visibleRegionScreen.intersect(outDirtyRegion).isEmpty()) {
            mCacheDirty = true;
        }
        if (mCacheDirty) {
            if (!mFlinger->isFrozen()) {
                // update everything below us that is visible
                outDirtyRegion.orSelf(visibleRegionScreen);
                nsecs_t now = systemTime();
                if ((now - mCacheAge) >= ms2ns(500)) {
                    mCacheAge = now;
                    mRefreshCache = true;
                    mCacheDirty = false;
                } else {
                    if (!mAutoRefreshPending) {
                        mFlinger->postMessageAsync(
                                new MessageBase(MessageQueue::INVALIDATE),
                                ms2ns(500));
                        mAutoRefreshPending = true;
                    }
                }
            }
        }
    }
    LayerBase::unlockPageFlip(planeTransform, outDirtyRegion);
}

void LayerBlur::onDraw(const Region& clip) const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t fbHeight = hw.getHeight();
    int x = mTransformedBounds.left;
    int y = mTransformedBounds.top;
    int w = mTransformedBounds.width();
    int h = mTransformedBounds.height();
    GLint X = x;
    GLint Y = fbHeight - (y + h);
    if (X < 0) {
        w += X;
        X = 0;
    }
    if (Y < 0) {
        h += Y;
        Y = 0;
    }
    if (w<0 || h<0) {
        // we're outside of the framebuffer
        return;
    }

    if (mTextureName == -1U) {
        // create the texture name the first time
        // can't do that in the ctor, because it runs in another thread.
        glGenTextures(1, &mTextureName);
        glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, &mReadFormat);
        glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, &mReadType);
        if (mReadFormat != GL_RGB || mReadType != GL_UNSIGNED_SHORT_5_6_5) {
            mReadFormat = GL_RGBA;
            mReadType = GL_UNSIGNED_BYTE;
            mBlurFormat = GGL_PIXEL_FORMAT_RGBX_8888;
        }
    }

    Region::const_iterator it = clip.begin();
    Region::const_iterator const end = clip.end();
    if (it != end) {
#if defined(GL_OES_EGL_image_external)
        if (GLExtensions::getInstance().haveTextureExternal()) {
            glDisable(GL_TEXTURE_EXTERNAL_OES);
        }
#endif
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, mTextureName);

        if (mRefreshCache) {
            mRefreshCache = false;
            mAutoRefreshPending = false;

            int32_t pixelSize = 4;
            int32_t s = w;
            if (mReadType == GL_UNSIGNED_SHORT_5_6_5) {
                // allocate enough memory for 4-bytes (2 pixels) aligned data
                s = (w + 1) & ~1;
                pixelSize = 2;
            }

            uint16_t* const pixels = (uint16_t*)malloc(s*h*pixelSize);

            // This reads the frame-buffer, so a h/w GL would have to
            // finish() its rendering first. we don't want to do that
            // too often. Read data is 4-bytes aligned.
            glReadPixels(X, Y, w, h, mReadFormat, mReadType, pixels);

            // blur that texture.
            GGLSurface bl;
            bl.version = sizeof(GGLSurface);
            bl.width = w;
            bl.height = h;
            bl.stride = s;
            bl.format = mBlurFormat;
            bl.data = (GGLubyte*)pixels;            
            blurFilter(&bl, 8, 2);

            if (GLExtensions::getInstance().haveNpot()) {
                glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, w, h, 0,
                        mReadFormat, mReadType, pixels);
                mWidthScale  = 1.0f / w;
                mHeightScale =-1.0f / h;
                mYOffset = 0;
            } else {
                GLuint tw = 1 << (31 - clz(w));
                GLuint th = 1 << (31 - clz(h));
                if (tw < GLuint(w)) tw <<= 1;
                if (th < GLuint(h)) th <<= 1;
                glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, tw, th, 0,
                        mReadFormat, mReadType, NULL);
                glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, 
                        mReadFormat, mReadType, pixels);
                mWidthScale  = 1.0f / tw;
                mHeightScale =-1.0f / th;
                mYOffset = th-h;
            }

            free((void*)pixels);
        }

        const State& s = drawingState();
        if (UNLIKELY(s.alpha < 0xFF)) {
            const GLfloat alpha = s.alpha * (1.0f/255.0f);
            glColor4f(0, 0, 0, alpha);
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        } else {
            glDisable(GL_BLEND);
        }

        if (mFlags & DisplayHardware::SLOW_CONFIG) {
            glDisable(GL_DITHER);
        } else {
            glEnable(GL_DITHER);
        }

        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

        glMatrixMode(GL_TEXTURE);
        glLoadIdentity();
        glScalef(mWidthScale, mHeightScale, 1);
        glTranslatef(-x, mYOffset - y, 0);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glVertexPointer(2, GL_FLOAT, 0, mVertices);
        glTexCoordPointer(2, GL_FLOAT, 0, mVertices);
        while (it != end) {
            const Rect& r = *it++;
            const GLint sy = fbHeight - (r.top + r.height());
            glScissor(r.left, sy, r.width(), r.height());
            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
        }
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glLoadIdentity();
        glMatrixMode(GL_MODELVIEW);
    }
}

// ---------------------------------------------------------------------------

}; // namespace android
+0 −65
Original line number Diff line number Diff line
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_LAYER_BLUR_H
#define ANDROID_LAYER_BLUR_H

#include <stdint.h>
#include <sys/types.h>

#include <ui/Region.h>

#include "LayerBase.h"

namespace android {

// ---------------------------------------------------------------------------

class LayerBlur : public LayerBaseClient
{
public:    
                LayerBlur(SurfaceFlinger* flinger, DisplayID display,
                        const sp<Client>& client);
        virtual ~LayerBlur();

    virtual void onDraw(const Region& clip) const;
    virtual bool needsBlending() const  { return true; }
    virtual bool isSecure() const       { return false; }
    virtual const char* getTypeId() const { return "LayerBlur"; }

    virtual uint32_t doTransaction(uint32_t flags);
    virtual void setVisibleRegion(const Region& visibleRegion);
    virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);

private:
            bool    mCacheDirty;
    mutable bool    mRefreshCache;
    mutable bool    mAutoRefreshPending;
            nsecs_t mCacheAge;
    mutable GLuint  mTextureName;
    mutable GLfloat mWidthScale;
    mutable GLfloat mHeightScale;
    mutable GLfloat mYOffset;
    mutable GLint   mReadFormat;
    mutable GLint   mReadType;
    mutable uint32_t mBlurFormat;
};

// ---------------------------------------------------------------------------

}; // namespace android

#endif // ANDROID_LAYER_BLUR_H
Loading