예제 #1
0
void LayerDim::onDraw(const Region& clip) const
{
    const State& s(drawingState());
    if (s.alpha>0) {
        const DisplayHardware& hw(graphicPlane(0).displayHardware());
        const GLfloat alpha = s.alpha/255.0f;
        const uint32_t fbHeight = hw.getHeight();
        glDisable(GL_TEXTURE_EXTERNAL_OES);
        glDisable(GL_TEXTURE_2D);

        if (s.alpha == 0xFF) {
            glDisable(GL_BLEND);
        } else {
            glEnable(GL_BLEND);
            glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
        }

        glColor4f(0, 0, 0, alpha);

        glVertexPointer(2, GL_FLOAT, 0, mVertices);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

        glDisable(GL_BLEND);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    }
}
예제 #2
0
void LayerBase::drawForSreenShot()
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    setFiltering(true);
    onDraw( Region(hw.bounds()) );
    setFiltering(false);
}
예제 #3
0
void Layer::setGeometry(hwc_layer_t* hwcl)
{
    LayerBaseClient::setGeometry(hwcl);

    hwcl->flags &= ~HWC_SKIP_LAYER;

    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    // we can't do alpha-fade with the hwc HAL. C2D composition
    // can handle fade cases
    const State& s(drawingState());
    if ((s.alpha < 0xFF) &&
        !(DisplayHardware::C2D_COMPOSITION & hw.getFlags())) {
        hwcl->flags = HWC_SKIP_LAYER;
    }

    hwcl->alpha = s.alpha;

    /*
     * Transformations are applied in this order:
     * 1) buffer orientation/flip/mirror
     * 2) state transformation (window manager)
     * 3) layer orientation (screen orientation)
     * mTransform is already the composition of (2) and (3)
     * (NOTE: the matrices are multiplied in reverse order)
     */

    const Transform bufferOrientation(mCurrentTransform);
    const Transform tr(mTransform * bufferOrientation);

    // this gives us only the "orientation" component of the transform
    const uint32_t finalTransform = tr.getOrientation();

    // we can only handle simple transformation
    if (finalTransform & Transform::ROT_INVALID) {
        hwcl->flags = HWC_SKIP_LAYER;
    } else {
        hwcl->transform = finalTransform;
    }

    if (isCropped()) {
        hwcl->sourceCrop.left   = mCurrentCrop.left;
        hwcl->sourceCrop.top    = mCurrentCrop.top;
        hwcl->sourceCrop.right  = mCurrentCrop.right;
        hwcl->sourceCrop.bottom = mCurrentCrop.bottom;
    } else {
        const sp<GraphicBuffer>& buffer(mActiveBuffer);
        hwcl->sourceCrop.left   = 0;
        hwcl->sourceCrop.top    = 0;
        if (buffer != NULL) {
            hwcl->sourceCrop.right  = buffer->width;
            hwcl->sourceCrop.bottom = buffer->height;
        } else {
            hwcl->sourceCrop.right  = mTransformedBounds.width();
            hwcl->sourceCrop.bottom = mTransformedBounds.height();
        }
    }
}
예제 #4
0
void Layer::onLayerDisplayed() {
    if (mFrameLatencyNeeded) {
        const DisplayHardware& hw(graphicPlane(0).displayHardware());
        mFrameStats[mFrameLatencyOffset].timestamp = mSurfaceTexture->getTimestamp();
        mFrameStats[mFrameLatencyOffset].set = systemTime();
        mFrameStats[mFrameLatencyOffset].vsync = hw.getRefreshTimestamp();
        mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
        mFrameLatencyNeeded = false;
    }
}
예제 #5
0
status_t Layer::setBuffers( uint32_t w, uint32_t h,
                            PixelFormat format, uint32_t flags)
{
    // this surfaces pixel format
    PixelFormatInfo info;
    status_t err = getPixelFormatInfo(format, &info);
    if (err) {
        ALOGE("unsupported pixelformat %d", format);
        return err;
    }

    // the display's pixel format
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    uint32_t const maxSurfaceDims = min(
            hw.getMaxTextureSize(), hw.getMaxViewportDims());

    // never allow a surface larger than what our underlying GL implementation
    // can handle.
    if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
        ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
        return BAD_VALUE;
    }

    PixelFormatInfo displayInfo;
    getPixelFormatInfo(hw.getFormat(), &displayInfo);
    const uint32_t hwFlags = hw.getFlags();
    
    mFormat = format;

    mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
    mProtectedByApp = (flags & ISurfaceComposer::eProtectedByApp) ? true : false;
    mOpaqueLayer = (flags & ISurfaceComposer::eOpaque);
    mCurrentOpacity = getOpacityForFormat(format);

    mSurfaceTexture->setDefaultBufferSize(w, h);
    mSurfaceTexture->setDefaultBufferFormat(format);
    mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));

    int useDither = mFlinger->getUseDithering();
    if (useDither) {
        if (useDither == 2) {
            mNeedsDithering = true;
        }
        else {
            // we use the red index
            int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
            int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
            mNeedsDithering = (layerRedsize > displayRedSize);
        }
    } else {
        mNeedsDithering = false;
    }

    return NO_ERROR;
}
예제 #6
0
void LayerBase::drawForSreenShot()
{
    //Dont draw External-only layers
    if (isLayerExternalOnly(getLayer())) {
        return;
    }
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    setFiltering(true);
    onDraw( Region(hw.bounds()) );
    setFiltering(false);
}
예제 #7
0
void LayerScreenshot::onDraw(const Region& clip) const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    copybit_image_t dst;
    hw.getDisplaySurface(&dst);
    if (dst.base != 0) {
        uint8_t const* src = (uint8_t const*)(intptr_t(dst.base) + dst.offset); 
        const int fbWidth = dst.w;
        const int fbHeight = dst.h;
        const int fbFormat = dst.format;

        int x = mTransformedBounds.left;
        int y = mTransformedBounds.top;
        int w = mTransformedBounds.width();
        int h = mTransformedBounds.height();
        Parcel* const reply = mReply;
        if (reply) {
            const size_t Bpp = bytesPerPixel(fbFormat);
            const size_t size = w * h * Bpp;
            int32_t cfg = SkBitmap::kNo_Config;
            switch (fbFormat) {
                case PIXEL_FORMAT_RGBA_4444: cfg = SkBitmap::kARGB_4444_Config;
                case PIXEL_FORMAT_RGBA_8888: cfg = SkBitmap::kARGB_8888_Config;
                case PIXEL_FORMAT_RGB_565:   cfg = SkBitmap::kRGB_565_Config;
                case PIXEL_FORMAT_A_8:       cfg = SkBitmap::kA8_Config;
            }
            reply->writeInt32(0);
            reply->writeInt32(cfg);
            reply->writeInt32(w);
            reply->writeInt32(h);
            reply->writeInt32(w * Bpp);
            void* data = reply->writeInplace(size);
            if (data) {
                uint8_t* d = (uint8_t*)data;
                uint8_t const* s = src + (x + y*fbWidth) * Bpp;
                if (w == fbWidth) {
                    memcpy(d, s, w*h*Bpp);   
                } else {
                    for (int y=0 ; y<h ; y++) {
                        memcpy(d, s, w*Bpp);
                        d += w*Bpp;
                        s += fbWidth*Bpp;
                    }
                }
            }
        }
    }
    mCV.broadcast();
}
예제 #8
0
void LayerBase::clearWithOpenGL(const Region& clip, GLclampf red,
                                GLclampf green, GLclampf blue,
                                GLclampf alpha) const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t fbHeight = hw.getHeight();
    glColor4f(red,green,blue,alpha);

    glDisable(GL_TEXTURE_EXTERNAL_OES);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);

    glVertexPointer(2, GL_FLOAT, 0, mVertices);
    glDrawArrays(GL_TRIANGLE_FAN, 0, mNumVertices);
}
예제 #9
0
void LayerBase::drawRegion(const Region& reg) const
{
    Region::iterator iterator(reg);
    if (iterator) {
        Rect r;
        const DisplayHardware& hw(graphicPlane(0).displayHardware());
        const int32_t fbWidth  = hw.getWidth();
        const int32_t fbHeight = hw.getHeight();
        const GLshort vertices[][2] = { { 0, 0 }, { fbWidth, 0 }, 
                { fbWidth, fbHeight }, { 0, fbHeight }  };
        glVertexPointer(2, GL_SHORT, 0, vertices);
        while (iterator.iterate(&r)) {
            const GLint sy = fbHeight - (r.top + r.height());
            glScissor(r.left, sy, r.width(), r.height());
            glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
        }
    }
}
예제 #10
0
void LayerBase::validateVisibility(const Transform& planeTransform)
{
    const Layer::State& s(drawingState());
    const Transform tr(planeTransform * s.transform);
    const bool transformed = tr.transformed();
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t hw_h = hw.getHeight();
    const Rect& crop(s.active.crop);

    Rect win(s.active.w, s.active.h);
    if (!crop.isEmpty()) {
        win.intersect(crop, &win);
    }

    mNumVertices = 4;
    tr.transform(mVertices[0], win.left,  win.top);
    tr.transform(mVertices[1], win.left,  win.bottom);
    tr.transform(mVertices[2], win.right, win.bottom);
    tr.transform(mVertices[3], win.right, win.top);
    for (size_t i=0 ; i<4 ; i++)
        mVertices[i][1] = hw_h - mVertices[i][1];

    if (CC_UNLIKELY(transformed)) {
        // NOTE: here we could also punt if we have too many rectangles
        // in the transparent region
        if (tr.preserveRects()) {
            // transform the transparent region
            transparentRegionScreen = tr.transform(s.transparentRegion);
        } else {
            // transformation too complex, can't do the transparent region
            // optimization.
            transparentRegionScreen.clear();
        }
    } else {
        transparentRegionScreen = s.transparentRegion;
    }

    // cache a few things...
    mOrientation = tr.getOrientation();
    mPlaneOrientation = planeTransform.getOrientation();
    mTransform = tr;
    mTransformedBounds = tr.transform(win);
}
예제 #11
0
void LayerBase::clearWithOpenGL(const Region& clip) const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t fbHeight = hw.getHeight();
    glColor4x(0,0,0,0);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);
    glDisable(GL_DITHER);
    Rect r;
    Region::iterator iterator(clip);
    if (iterator) {
        glVertexPointer(2, GL_FIXED, 0, mVertices);
        while (iterator.iterate(&r)) {
            const GLint sy = fbHeight - (r.top + r.height());
            glScissor(r.left, sy, r.width(), r.height());
            glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
        }
    }
}
예제 #12
0
void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
{
    LayerBaseClient::dumpStats(result, buffer, SIZE);
    const size_t o = mFrameLatencyOffset;
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const nsecs_t period = hw.getRefreshPeriod();
    result.appendFormat("%lld\n", period);
    for (size_t i=0 ; i<128 ; i++) {
        const size_t index = (o+i) % 128;
        const nsecs_t time_app   = mFrameStats[index].timestamp;
        const nsecs_t time_set   = mFrameStats[index].set;
        const nsecs_t time_vsync = mFrameStats[index].vsync;
        result.appendFormat("%lld\t%lld\t%lld\n",
                time_app,
                time_vsync,
                time_set);
    }
    result.append("\n");
}
예제 #13
0
status_t Layer::setBuffers( uint32_t w, uint32_t h,
                            PixelFormat format, uint32_t flags)
{
    // this surfaces pixel format
    PixelFormatInfo info;
    status_t err = getPixelFormatInfo(format, &info);
    if (err) return err;

    // the display's pixel format
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    uint32_t const maxSurfaceDims = min(
            hw.getMaxTextureSize(), hw.getMaxViewportDims());

    // never allow a surface larger than what our underlying GL implementation
    // can handle.
    if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
        return BAD_VALUE;
    }

    PixelFormatInfo displayInfo;
    getPixelFormatInfo(hw.getFormat(), &displayInfo);
    const uint32_t hwFlags = hw.getFlags();
    
    mFormat = format;
    mWidth  = w;
    mHeight = h;

    mReqFormat = format;
    mReqWidth = w;
    mReqHeight = h;

    mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
    mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;

    // we use the red index
    int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
    int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
    mNeedsDithering = layerRedsize > displayRedSize;

    mSurface = new SurfaceLayer(mFlinger, this);
    return NO_ERROR;
}
예제 #14
0
void LayerBase::validateVisibility(const Transform& planeTransform)
{
    const Layer::State& s(drawingState());
    const Transform tr(planeTransform * s.transform);
    const bool transformed = tr.transformed();
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t hw_h = hw.getHeight();

    uint32_t w = s.w;
    uint32_t h = s.h;    
    tr.transform(mVertices[0], 0, 0);
    tr.transform(mVertices[1], 0, h);
    tr.transform(mVertices[2], w, h);
    tr.transform(mVertices[3], w, 0);
    for (size_t i=0 ; i<4 ; i++)
        mVertices[i][1] = hw_h - mVertices[i][1];

    if (UNLIKELY(transformed)) {
        // NOTE: here we could also punt if we have too many rectangles
        // in the transparent region
        if (tr.preserveRects()) {
            // transform the transparent region
            transparentRegionScreen = tr.transform(s.transparentRegion);
        } else {
            // transformation too complex, can't do the transparent region
            // optimization.
            transparentRegionScreen.clear();
        }
    } else {
        transparentRegionScreen = s.transparentRegion;
    }

    // cache a few things...
    mOrientation = tr.getOrientation();
    mPlaneOrientation = planeTransform.getOrientation();
    mTransform = tr;
    mTransformedBounds = tr.makeBounds(w, h);
}
예제 #15
0
void LayerBase::clearWithOpenGL(const Region& clip, GLclampf red,
                                GLclampf green, GLclampf blue,
                                GLclampf alpha) const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t fbHeight = hw.getHeight();
    glColor4f(red,green,blue,alpha);

    glDisable(GL_TEXTURE_EXTERNAL_OES);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);

    Region::const_iterator it = clip.begin();
    Region::const_iterator const end = clip.end();
    glEnable(GL_SCISSOR_TEST);
    glVertexPointer(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); 
    }
}
예제 #16
0
void LayerBuffer::drawForSreenShot() const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    clearWithOpenGL( Region(hw.bounds()) );
}
예제 #17
0
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);
    }

    Region::iterator iterator(clip);
    if (iterator) {
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, mTextureName);
    
        if (mRefreshCache) {
            mRefreshCache = false;
            mAutoRefreshPending = false;
            
            // allocate enough memory for 4-bytes (2 pixels) aligned data
            const int32_t s = (w + 1) & ~1;
            uint16_t* const pixels = (uint16_t*)malloc(s*h*2);

            // 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, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
            
            // blur that texture.
            GGLSurface bl;
            bl.version = sizeof(GGLSurface);
            bl.width = w;
            bl.height = h;
            bl.stride = s;
            bl.format = GGL_PIXEL_FORMAT_RGB_565;
            bl.data = (GGLubyte*)pixels;            
            blurFilter(&bl, 8, 2);
            
            // NOTE: this works only because we have POT. we'd have to round the
            // texture size up, otherwise.
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);

            free((void*)pixels);
        }
        
        const State& s = drawingState();
        if (UNLIKELY(s.alpha < 0xFF)) {
            const GGLfixed alpha = (s.alpha << 16)/255;
            glColor4x(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);
        }

        glDisable(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);

        if (UNLIKELY(transformed()
                || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) {
            // This is a very rare scenario.
            glMatrixMode(GL_TEXTURE);
            glLoadIdentity();
            glScalef(1.0f/w, -1.0f/h, 1);
            glTranslatef(-x, -y, 0);
            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
            glVertexPointer(2, GL_FIXED, 0, mVertices);
            glTexCoordPointer(2, GL_FIXED, 0, mVertices);
            Rect r;
            while (iterator.iterate(&r)) {
                const GLint sy = fbHeight - (r.top + r.height());
                glScissor(r.left, sy, r.width(), r.height());
                glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
            }       
        } else {
            Region::iterator iterator(clip);
            if (iterator) {
                // NOTE: this is marginally faster with the software gl, because
                // glReadPixels() reads the fb bottom-to-top, however we'll
                // skip all the jaccobian computations.
                Rect r;
                GLint crop[4] = { 0, 0, w, h };
                glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
                y = fbHeight - (y + h);
                while (iterator.iterate(&r)) {
                    const GLint sy = fbHeight - (r.top + r.height());
                    glScissor(r.left, sy, r.width(), r.height());
                    glDrawTexiOES(x, y, 0, w, h);
                }
            }
        }
    }

    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
예제 #18
0
void LayerBase::drawWithOpenGL(const Region& clip) const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t fbHeight = hw.getHeight();
    const State& s(drawingState());

    GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
    if (UNLIKELY(s.alpha < 0xFF)) {
        const GLfloat alpha = s.alpha * (1.0f/255.0f);
        if (mPremultipliedAlpha) {
            glColor4f(alpha, alpha, alpha, alpha);
        } else {
            glColor4f(1, 1, 1, alpha);
        }
        glEnable(GL_BLEND);
        glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    } else {
        glColor4f(1, 1, 1, 1);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        if (!isOpaque()) {
            glEnable(GL_BLEND);
            glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
        } else {
            glDisable(GL_BLEND);
        }
    }

    struct TexCoords {
        GLfloat u;
        GLfloat v;
    };

    TexCoords texCoords[4];
    texCoords[0].u = 0;
    texCoords[0].v = 1;
    texCoords[1].u = 0;
    texCoords[1].v = 0;
    texCoords[2].u = 1;
    texCoords[2].v = 0;
    texCoords[3].u = 1;
    texCoords[3].v = 1;

    if (drawRotatedTexture) {
        int tWidth = mTransformedBounds.right - mTransformedBounds.left;
        int val = drawRotatedTexture(mOrientation, tWidth, fbHeight,
                                             clip, (GLfloat *) mVertices,
                                                  (GLfloat *) texCoords);
        if (val == NO_ERROR) {
            return;
        }
    }

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, mVertices);
    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);

    Region::const_iterator it = clip.begin();
    Region::const_iterator const end = clip.end();
    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);
    glDisable(GL_BLEND);
}
void LayerBase::drawForSreenShot() const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    onDraw( Region(hw.bounds()) );
}
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);

#ifdef AVOID_DRAW_TEXTURE
        if(UNLIKELY(transformed()))
#endif
        {
            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);
        }
#ifdef AVOID_DRAW_TEXTURE
        else{
            Rect r;
            GLint crop[4] = { 0, 0, w, h };
            glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
            y = fbHeight - (y + h);
            while (it != end) {
                const Rect& r = *it++;
                const GLint sy = fbHeight - (r.top + r.height());
                glScissor(r.left, sy, r.width(), r.height());
                glDrawTexiOES(x, y, 0, w, h);
            }
        }
#endif
        glLoadIdentity();
        glMatrixMode(GL_MODELVIEW);
    }
}
void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t fbHeight = hw.getHeight();
    const State& s(drawingState());
    
    // bind our texture
    TextureManager::activateTexture(texture, needsFiltering());
    uint32_t width  = texture.width; 
    uint32_t height = texture.height;

    GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;

    int renderEffect = mFlinger->getRenderEffect();
    int renderColorR = mFlinger->getRenderColorR();
    int renderColorG = mFlinger->getRenderColorG();
    int renderColorB = mFlinger->getRenderColorB();

    bool noEffect = renderEffect == 0;

    if (UNLIKELY(s.alpha < 0xFF) && noEffect) {
        const GLfloat alpha = s.alpha * (1.0f/255.0f);
        if (mPremultipliedAlpha) {
            glColor4f(alpha, alpha, alpha, alpha);
        } else {
            glColor4f(1, 1, 1, alpha);
        }
        glEnable(GL_BLEND);
        glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    } else if (noEffect) {
        glColor4f(1, 1, 1, 1);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        if (needsBlending()) {
            glEnable(GL_BLEND);
            glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
        } else {
            glDisable(GL_BLEND);
        }
    } else {
        // Apply a render effect, which is simple color masks for now.
        GLenum env, src;
        env = GL_MODULATE;
        src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
        const GGLfixed alpha = (s.alpha << 16)/255;
        switch (renderEffect) {
            case RENDER_EFFECT_NIGHT:
                glColor4x(alpha, alpha*0.6204, alpha*0.3018, alpha);
                break;
            case RENDER_EFFECT_TERMINAL:
                glColor4x(0, alpha, 0, alpha);
                break;
            case RENDER_EFFECT_BLUE:
                glColor4x(0, 0, alpha, alpha);
                break;
            case RENDER_EFFECT_AMBER:
                glColor4x(alpha, alpha*0.75, 0, alpha);
                break;
            case RENDER_EFFECT_SALMON:
                glColor4x(alpha, alpha*0.5, alpha*0.5, alpha);
                break;
            case RENDER_EFFECT_FUSCIA:
                glColor4x(alpha, 0, alpha*0.5, alpha);
                break;
            case RENDER_EFFECT_N1_CALIBRATED_N:
                glColor4x(alpha*renderColorR/1000, alpha*renderColorG/1000, alpha*renderColorB/1000, alpha);
                break;
            case RENDER_EFFECT_N1_CALIBRATED_R:
                glColor4x(alpha*(renderColorR-50)/1000, alpha*renderColorG/1000, alpha*(renderColorB-30)/1000, alpha);
                break;
            case RENDER_EFFECT_N1_CALIBRATED_C:
                glColor4x(alpha*renderColorR/1000, alpha*renderColorG/1000, alpha*(renderColorB+30)/1000, alpha);
                break;
            case RENDER_EFFECT_RED:
                glColor4x(alpha, 0, 0, alpha);
                break;
        }
        glEnable(GL_BLEND);
        glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env);
    }

    /*
     *  compute texture coordinates
     *  here, we handle NPOT, cropping and buffer transformations
     */

    GLfloat cl, ct, cr, cb;
    if (!mBufferCrop.isEmpty()) {
        // source is cropped
        const GLfloat us = (texture.NPOTAdjust ? texture.wScale : 1.0f) / width;
        const GLfloat vs = (texture.NPOTAdjust ? texture.hScale : 1.0f) / height;
        cl = mBufferCrop.left   * us;
        ct = mBufferCrop.top    * vs;
        cr = mBufferCrop.right  * us;
        cb = mBufferCrop.bottom * vs;
    } else {
        cl = 0;
        ct = 0;
        cr = (texture.NPOTAdjust ? texture.wScale : 1.0f);
        cb = (texture.NPOTAdjust ? texture.hScale : 1.0f);
    }

    /*
     * For the buffer transformation, we apply the rotation last.
     * Since we're transforming the texture-coordinates, we need
     * to apply the inverse of the buffer transformation:
     *   inverse( FLIP_V -> FLIP_H -> ROT_90 )
     *   <=> inverse( ROT_90 * FLIP_H * FLIP_V )
     *    =  inverse(FLIP_V) * inverse(FLIP_H) * inverse(ROT_90)
     *    =  FLIP_V * FLIP_H * ROT_270
     *   <=> ROT_270 -> FLIP_H -> FLIP_V
     *
     * The rotation is performed first, in the texture coordinate space.
     *
     */

    struct TexCoords {
        GLfloat u;
        GLfloat v;
    };

    enum {
        // name of the corners in the texture map
        LB = 0, // left-bottom
        LT = 1, // left-top
        RT = 2, // right-top
        RB = 3  // right-bottom
    };

    // vertices in screen space
    int vLT = LB;
    int vLB = LT;
    int vRB = RT;
    int vRT = RB;

    // the texture's source is rotated
    uint32_t transform = mBufferTransform;
    if (transform & HAL_TRANSFORM_ROT_90) {
        vLT = RB;
        vLB = LB;
        vRB = LT;
        vRT = RT;
    }
    if (transform & HAL_TRANSFORM_FLIP_V) {
        swap(vLT, vLB);
        swap(vRT, vRB);
    }
    if (transform & HAL_TRANSFORM_FLIP_H) {
        swap(vLT, vRT);
        swap(vLB, vRB);
    }

    TexCoords texCoords[4];
    texCoords[vLT].u = cl;
    texCoords[vLT].v = ct;
    texCoords[vLB].u = cl;
    texCoords[vLB].v = cb;
    texCoords[vRB].u = cr;
    texCoords[vRB].v = cb;
    texCoords[vRT].u = cr;
    texCoords[vRT].v = ct;

    if (needsDithering()) {
        glEnable(GL_DITHER);
    } else {
        glDisable(GL_DITHER);
    }

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, mVertices);
    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);

    Region::const_iterator it = clip.begin();
    Region::const_iterator const end = clip.end();
    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);
}
예제 #22
0
void LayerBase::drawWithOpenGL(const Region& clip,
        GLint textureName, const GGLSurface& t) const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t fbHeight = hw.getHeight();
    const State& s(drawingState());

    // bind our texture
    validateTexture(textureName);
    glEnable(GL_TEXTURE_2D);

    // Dithering...
    if (s.flags & ISurfaceComposer::eLayerDither) {
        glEnable(GL_DITHER);
    } else {
        glDisable(GL_DITHER);
    }

    if (UNLIKELY(s.alpha < 0xFF)) {
        // We have an alpha-modulation. We need to modulate all
        // texture components by alpha because we're always using 
        // premultiplied alpha.
        
        // If the texture doesn't have an alpha channel we can
        // use REPLACE and switch to non premultiplied alpha
        // blending (SRCA/ONE_MINUS_SRCA).
        
        GLenum env, src;
        if (needsBlending()) {
            env = GL_MODULATE;
            src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
        } else {
            env = GL_REPLACE;
            src = GL_SRC_ALPHA;
        }
        const GGLfixed alpha = (s.alpha << 16)/255;
        glColor4x(alpha, alpha, alpha, alpha);
        glEnable(GL_BLEND);
        glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env);
    } else {
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        glColor4x(0x10000, 0x10000, 0x10000, 0x10000);
        if (needsBlending()) {
            GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
            glEnable(GL_BLEND);
            glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
        } else {
            glDisable(GL_BLEND);
        }
    }

    if (UNLIKELY(transformed()
            || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) 
    {
        //StopWatch watch("GL transformed");
        Region::iterator iterator(clip);
        if (iterator) {
            // always use high-quality filtering with fast configurations
            bool fast = !(mFlags & DisplayHardware::SLOW_CONFIG);
            if (!fast && s.flags & ISurfaceComposer::eLayerFilter) {
                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            }            
            const GLfixed texCoords[4][2] = {
                    { 0,        0 },
                    { 0,        0x10000 },
                    { 0x10000,  0x10000 },
                    { 0x10000,  0 }
            };

            glMatrixMode(GL_TEXTURE);
            glLoadIdentity();
            if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
                // find the smallest power-of-two that will accommodate our surface
                GLuint tw = 1 << (31 - clz(t.width));
                GLuint th = 1 << (31 - clz(t.height));
                if (tw < t.width)  tw <<= 1;
                if (th < t.height) th <<= 1;
                // this divide should be relatively fast because it's
                // a power-of-two (optimized path in libgcc)
                GLfloat ws = GLfloat(t.width) /tw;
                GLfloat hs = GLfloat(t.height)/th;
                glScalef(ws, hs, 1.0f);
            }

            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
            glVertexPointer(2, GL_FIXED, 0, mVertices);
            glTexCoordPointer(2, GL_FIXED, 0, texCoords);

            Rect r;
            while (iterator.iterate(&r)) {
                const GLint sy = fbHeight - (r.top + r.height());
                glScissor(r.left, sy, r.width(), r.height());
                glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
            }

            if (!fast && s.flags & ISurfaceComposer::eLayerFilter) {
                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
            }
            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        }
    } else {
        Region::iterator iterator(clip);
        if (iterator) {
            Rect r;
            GLint crop[4] = { 0, t.height, t.width, -t.height };
            glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
            int x = tx();
            int y = ty();
            y = fbHeight - (y + t.height);
            while (iterator.iterate(&r)) {
                const GLint sy = fbHeight - (r.top + r.height());
                glScissor(r.left, sy, r.width(), r.height());
                glDrawTexiOES(x, y, 0, t.width, t.height);
            }
        }
    }
}
예제 #23
0
void LayerBase::drawWithOpenGL(const Region& clip) const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t fbHeight = hw.getHeight();
    const State& s(drawingState());

    GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
    if (CC_UNLIKELY(s.alpha < 0xFF)) {
        const GLfloat alpha = s.alpha * (1.0f/255.0f);
        if (mPremultipliedAlpha) {
            glColor4f(alpha, alpha, alpha, alpha);
        } else {
            glColor4f(1, 1, 1, alpha);
        }
        glEnable(GL_BLEND);
        glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    } else {
        glColor4f(1, 1, 1, 1);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        if (!isOpaque()) {
            glEnable(GL_BLEND);
            glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
        } else {
            glDisable(GL_BLEND);
        }
    }

    struct TexCoords {
        GLfloat u;
        GLfloat v;
    };

    Rect crop(s.active.w, s.active.h);
    if (!s.active.crop.isEmpty()) {
        crop = s.active.crop;
    }
    GLfloat left = GLfloat(crop.left) / GLfloat(s.active.w);
    GLfloat top = GLfloat(crop.top) / GLfloat(s.active.h);
    GLfloat right = GLfloat(crop.right) / GLfloat(s.active.w);
    GLfloat bottom = GLfloat(crop.bottom) / GLfloat(s.active.h);

    TexCoords texCoords[4];
    texCoords[0].u = left;
    texCoords[0].v = top;
    texCoords[1].u = left;
    texCoords[1].v = bottom;
    texCoords[2].u = right;
    texCoords[2].v = bottom;
    texCoords[3].u = right;
    texCoords[3].v = top;
    for (int i = 0; i < 4; i++) {
        texCoords[i].v = 1.0f - texCoords[i].v;
    }

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, mVertices);
    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
    glDrawArrays(GL_TRIANGLE_FAN, 0, mNumVertices);

    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisable(GL_BLEND);
}
예제 #24
0
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
    if (mQueuedFrames > 0) {
        // Capture the old state of the layer for comparisons later
        const bool oldOpacity = isOpaque();
        sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;

        // signal another event if we have more frames pending
        if (android_atomic_dec(&mQueuedFrames) > 1) {
            mFlinger->signalEvent();
        }

        const DisplayHardware& hw(graphicPlane(0).displayHardware());
        
        bool avoidTex = (hw.getFlags() & DisplayHardware::MDP_COMPOSITION) ?
                          true : false;

        if (mSurfaceTexture->updateTexImage(avoidTex) < NO_ERROR) {
            // something happened!
            recomputeVisibleRegions = true;
            return;
        }

        updateLayerQcomFlags(LAYER_UPDATE_STATUS, true, mLayerQcomFlags);

        // update the active buffer
        mActiveBuffer = mSurfaceTexture->getCurrentBuffer();

        const Rect crop(mSurfaceTexture->getCurrentCrop());
        const uint32_t transform(mSurfaceTexture->getCurrentTransform());
        const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
        if ((crop != mCurrentCrop) ||
            (transform != mCurrentTransform) ||
            (scalingMode != mCurrentScalingMode))
        {
            mCurrentCrop = crop;
            mCurrentTransform = transform;
            mCurrentScalingMode = scalingMode;
            mFlinger->invalidateHwcGeometry();
        }

        GLfloat textureMatrix[16];
        mSurfaceTexture->getTransformMatrix(textureMatrix);
        if (memcmp(textureMatrix, mTextureMatrix, sizeof(textureMatrix))) {
            memcpy(mTextureMatrix, textureMatrix, sizeof(textureMatrix));
            mFlinger->invalidateHwcGeometry();
        }

        uint32_t bufWidth  = mActiveBuffer->getWidth();
        uint32_t bufHeight = mActiveBuffer->getHeight();
        if (oldActiveBuffer != NULL) {
            if (bufWidth != uint32_t(oldActiveBuffer->width) ||
                bufHeight != uint32_t(oldActiveBuffer->height)) {
                mFlinger->invalidateHwcGeometry();
            }
        }

        mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
        if (oldOpacity != isOpaque()) {
            recomputeVisibleRegions = true;
        }

        glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        // update the layer size if needed
        const Layer::State& front(drawingState());

        // FIXME: mPostedDirtyRegion = dirty & bounds
        mPostedDirtyRegion.set(front.w, front.h);

        if ((front.w != front.requested_w) ||
            (front.h != front.requested_h))
        {
            // check that we received a buffer of the right size
            // (Take the buffer's orientation into account)
            if (mCurrentTransform & Transform::ROT_90) {
                swap(bufWidth, bufHeight);
            }

            if (isFixedSize() ||
                    (bufWidth == front.requested_w &&
                    bufHeight == front.requested_h))
            {
                // Here we pretend the transaction happened by updating the
                // current and drawing states. Drawing state is only accessed
                // in this thread, no need to have it locked
                Layer::State& editDraw(mDrawingState);
                editDraw.w = editDraw.requested_w;
                editDraw.h = editDraw.requested_h;

                // We also need to update the current state so that we don't
                // end-up doing too much work during the next transaction.
                // NOTE: We actually don't need hold the transaction lock here
                // because State::w and State::h are only accessed from
                // this thread
                Layer::State& editTemp(currentState());
                editTemp.w = editDraw.w;
                editTemp.h = editDraw.h;

                // recompute visible region
                recomputeVisibleRegions = true;
            }

            LOGD_IF(DEBUG_RESIZE,
                    "lockPageFlip : "
                    "       (layer=%p), buffer (%ux%u, tr=%02x), "
                    "requested (%dx%d)",
                    this,
                    bufWidth, bufHeight, mCurrentTransform,
                    front.requested_w, front.requested_h);
        }
    } else {
        updateLayerQcomFlags(LAYER_UPDATE_STATUS, false, mLayerQcomFlags);
    }
}
예제 #25
0
status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy,
        sp<IMemoryHeap>* heap,
        uint32_t* w, uint32_t* h, PixelFormat* f,
        uint32_t sw, uint32_t sh)
{
   LOGI("captureScreenImplLocked");
    status_t result = PERMISSION_DENIED;

    // only one display supported for now
    if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
        return BAD_VALUE;

    if (!GLExtensions::getInstance().haveFramebufferObject())
        return INVALID_OPERATION;

    // get screen geometry
    const DisplayHardware& hw(graphicPlane(dpy).displayHardware());
    const uint32_t hw_w = hw.getWidth();
    const uint32_t hw_h = hw.getHeight();

    if ((sw > hw_w) || (sh > hw_h))
        return BAD_VALUE;

    sw = (!sw) ? hw_w : sw;
    sh = (!sh) ? hw_h : sh;
    const size_t size = sw * sh * 4;

    // make sure to clear all GL error flags
    while ( glGetError() != GL_NO_ERROR ) ;

    // create a FBO
    GLuint name, tname;
    glGenRenderbuffersOES(1, &tname);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname);
    glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, sw, sh);
    glGenFramebuffersOES(1, &name);
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
            GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname);

    GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
    if (status == GL_FRAMEBUFFER_COMPLETE_OES) {

        // invert everything, b/c glReadPixel() below will invert the FB
        glViewport(0, 0, sw, sh);
        glScissor(0, 0, sw, sh);
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        glOrthof(0, hw_w, 0, hw_h, 0, 1);
        glMatrixMode(GL_MODELVIEW);

        // redraw the screen entirely...
        glClearColor(0,0,0,1);
        glClear(GL_COLOR_BUFFER_BIT);

        const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
        const size_t count = layers.size();
        for (size_t i=0 ; i<count ; ++i) {
            const sp<LayerBase>& layer(layers[i]);
            layer->drawForSreenShot();
        }

        // XXX: this is needed on tegra
        glScissor(0, 0, sw, sh);

        // check for errors and return screen capture
        if (glGetError() != GL_NO_ERROR) {
            // error while rendering
            result = INVALID_OPERATION;
        } else {
            // allocate shared memory large enough to hold the
            // screen capture
            sp<MemoryHeapBase> base(
                    new MemoryHeapBase(size, 0, "screen-capture") );
            void* const ptr = base->getBase();
            if (ptr) {
                // capture the screen with glReadPixels()
                glReadPixels(0, 0, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, ptr);
                if (glGetError() == GL_NO_ERROR) {
                    *heap = base;
                    *w = sw;
                    *h = sh;
                    *f = PIXEL_FORMAT_RGBA_8888;
                    result = NO_ERROR;
                }
            } else {
                result = NO_MEMORY;
            }
        }
        glEnable(GL_SCISSOR_TEST);
        glViewport(0, 0, hw_w, hw_h);
        glMatrixMode(GL_PROJECTION);
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);


    } else {
        result = BAD_VALUE;
    }

    // release FBO resources
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
    glDeleteRenderbuffersOES(1, &tname);
    glDeleteFramebuffersOES(1, &name);

    hw.compositionComplete();

    return result;
}
예제 #26
0
//end
void LayerBase::drawWithOpenGL(const Region& clip) const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t fbHeight = hw.getHeight();
	const uint32_t fbWidth = hw.getWidth();
    const State& s(drawingState());
	const SurfaceFlinger::State& sSF = mFlinger->getDrawingState();

    GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
    if (UNLIKELY(s.alpha < 0xFF)) {
        const GLfloat alpha = s.alpha * (1.0f/255.0f);
        if (mPremultipliedAlpha) {
            glColor4f(alpha, alpha, alpha, alpha);
        } else {
            glColor4f(1, 1, 1, alpha);
        }
        glEnable(GL_BLEND);
        glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    } else {
        glColor4f(1, 1, 1, 1);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        if (!isOpaque()) {
            glEnable(GL_BLEND);
            glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
        } else {
            glDisable(GL_BLEND);
        }
    }  
	//first judge wheather is 3D module 40641
	const uint32_t hw_w_half = hw.getWidth()/2;
	struct TexCoords {
        				GLfloat u;
      					GLfloat v;
   						};			 
	TexCoords texCoords[4];
	//judge if 3D modle
	
					
	switch(sSF.composing3D){
		case eSTEREO_OSD_3D_NONE:			
		{
			drawNormal(clip,fbHeight,mDrawingState.flags);			

			break;
		}
		
		case eSTEREO_OSD_3D_SBSHALFE_PR:
		{
			
			drawSideBySide(clip,hw_w_half,fbHeight,mDrawingState.flags);

			break;
		}
			
		case eSTEREO_OSD_3D_TPANDBT_PR:
		{
			
			drawTopAndBottom(clip,fbHeight,mDrawingState.flags);					

			break;
		}
			
		default:
		break;		
}
	
			
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisable(GL_BLEND);
}
예제 #27
0
void Layer::setGeometry(hwc_layer_t* hwcl)
{
    LayerBaseClient::setGeometry(hwcl);

    hwcl->flags &= ~HWC_SKIP_LAYER;

    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    // we can't do alpha-fade with the hwc HAL,
    // unless we are using C2D
    const State& s(drawingState());
    if (s.alpha < 0xFF) {
        if ((QCCompositionType::getInstance().getCompositionType() & COMPOSITION_TYPE_C2D)
            && (!isOpaque())) {
            hwcl->blending = mPremultipliedAlpha ?
                HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE;
        } else {
            hwcl->flags = HWC_SKIP_LAYER;
        }
    }

    //hwcl->alpha = s.alpha;

    /*
     * Transformations are applied in this order:
     * 1) buffer orientation/flip/mirror
     * 2) state transformation (window manager)
     * 3) layer orientation (screen orientation)
     * mTransform is already the composition of (2) and (3)
     * (NOTE: the matrices are multiplied in reverse order)
     */

    const Transform bufferOrientation(mCurrentTransform);
    const Transform tr(mTransform * bufferOrientation);

    // this gives us only the "orientation" component of the transform
    const uint32_t finalTransform = tr.getOrientation();

    // we can only handle simple transformation
    if (finalTransform & Transform::ROT_INVALID) {
        hwcl->flags = HWC_SKIP_LAYER;
    } else {
        hwcl->transform = finalTransform;
        //mBufferTransform will have the srcTransform
        //include src and final transform in the hwcl->transform
        hwcl->transform = (( bufferOrientation.getOrientation() <<
                                       SHIFT_SRC_TRANSFORM) | hwcl->transform);
    }

    if (isCropped()) {
        hwcl->sourceCrop.left   = mCurrentCrop.left;
        hwcl->sourceCrop.top    = mCurrentCrop.top;
        hwcl->sourceCrop.right  = mCurrentCrop.right;
        hwcl->sourceCrop.bottom = mCurrentCrop.bottom;
    } else {
        const sp<GraphicBuffer>& buffer(mActiveBuffer);
        hwcl->sourceCrop.left   = 0;
        hwcl->sourceCrop.top    = 0;
        if (buffer != NULL) {
            hwcl->sourceCrop.right  = buffer->width;
            hwcl->sourceCrop.bottom = buffer->height;
        } else {
            hwcl->sourceCrop.right  = mTransformedBounds.width();
            hwcl->sourceCrop.bottom = mTransformedBounds.height();
        }
    }
}