19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h>
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdint.h>
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h>
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Errors.h>
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h>
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <GLES/gl.h>
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <GLES/glext.h>
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian#include "clz.h"
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "BlurFilter.h"
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "LayerBlur.h"
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SurfaceFlinger.h"
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "DisplayHardware/DisplayHardware.h"
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectLayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
37593c05ce7bcf7b6d94bd8c50da2b818cf05116b1Mathias Agopian        const sp<Client>& client)
38593c05ce7bcf7b6d94bd8c50da2b818cf05116b1Mathias Agopian    : LayerBaseClient(flinger, display, client), mCacheDirty(true),
39d8b28e4fcddcacdbd2b69584a4e3aa12f52e8229Mathias Agopian          mRefreshCache(true), mCacheAge(0), mTextureName(-1U),
40d8b28e4fcddcacdbd2b69584a4e3aa12f52e8229Mathias Agopian          mWidthScale(1.0f), mHeightScale(1.0f),
41d8b28e4fcddcacdbd2b69584a4e3aa12f52e8229Mathias Agopian          mBlurFormat(GGL_PIXEL_FORMAT_RGB_565)
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectLayerBlur::~LayerBlur()
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mTextureName != -1U) {
4881b0aa696ac954180caec6cb8cc1bb97440e03b5Mathias Agopian        glDeleteTextures(1, &mTextureName);
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid LayerBlur::setVisibleRegion(const Region& visibleRegion)
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LayerBaseClient::setVisibleRegion(visibleRegion);
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (visibleRegionScreen.isEmpty()) {
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mTextureName != -1U) {
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // We're not visible, free the texture up.
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glBindTexture(GL_TEXTURE_2D, 0);
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glDeleteTextures(1, &mTextureName);
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTextureName = -1U;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectuint32_t LayerBlur::doTransaction(uint32_t flags)
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // we're doing a transaction, refresh the cache!
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!mFlinger->isFrozen()) {
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRefreshCache = true;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheDirty = true;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        flags |= eVisibleRegion;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this->contentDirty = true;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return LayerBase::doTransaction(flags);
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid LayerBlur::unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion)
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // this code-path must be as tight as possible, it's called each time
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // the screen is composited.
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (UNLIKELY(!visibleRegionScreen.isEmpty())) {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // if anything visible below us is invalidated, the cache becomes dirty
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mCacheDirty &&
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                !visibleRegionScreen.intersect(outDirtyRegion).isEmpty()) {
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCacheDirty = true;
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCacheDirty) {
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mFlinger->isFrozen()) {
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // update everything below us that is visible
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                outDirtyRegion.orSelf(visibleRegionScreen);
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                nsecs_t now = systemTime();
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((now - mCacheAge) >= ms2ns(500)) {
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCacheAge = now;
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mRefreshCache = true;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCacheDirty = false;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!mAutoRefreshPending) {
98898c4c91be8e11b6d5388c623ae80f12ac25fd27Mathias Agopian                        mFlinger->postMessageAsync(
99898c4c91be8e11b6d5388c623ae80f12ac25fd27Mathias Agopian                                new MessageBase(MessageQueue::INVALIDATE),
100898c4c91be8e11b6d5388c623ae80f12ac25fd27Mathias Agopian                                ms2ns(500));
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mAutoRefreshPending = true;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LayerBase::unlockPageFlip(planeTransform, outDirtyRegion);
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid LayerBlur::onDraw(const Region& clip) const
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const DisplayHardware& hw(graphicPlane(0).displayHardware());
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const uint32_t fbHeight = hw.getHeight();
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int x = mTransformedBounds.left;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int y = mTransformedBounds.top;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int w = mTransformedBounds.width();
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int h = mTransformedBounds.height();
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    GLint X = x;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    GLint Y = fbHeight - (y + h);
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (X < 0) {
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        w += X;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        X = 0;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (Y < 0) {
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        h += Y;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Y = 0;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (w<0 || h<0) {
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // we're outside of the framebuffer
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mTextureName == -1U) {
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // create the texture name the first time
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // can't do that in the ctor, because it runs in another thread.
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        glGenTextures(1, &mTextureName);
1372c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian        glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, &mReadFormat);
1382c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian        glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, &mReadType);
1392c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian        if (mReadFormat != GL_RGB || mReadType != GL_UNSIGNED_SHORT_5_6_5) {
1402c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian            mReadFormat = GL_RGBA;
1412c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian            mReadType = GL_UNSIGNED_BYTE;
1422c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian            mBlurFormat = GGL_PIXEL_FORMAT_RGBX_8888;
1432c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian        }
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1466158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian    Region::const_iterator it = clip.begin();
1476158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian    Region::const_iterator const end = clip.end();
1486158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian    if (it != end) {
149e20a56d929fc8fedc2b468ea6d1900bd2aa6e81aMichael I. Gold#if defined(GL_OES_EGL_image_external)
150781953d62dc17d761e39540f0480e5ca7451cdbeMathias Agopian        if (GLExtensions::getInstance().haveTextureExternal()) {
151781953d62dc17d761e39540f0480e5ca7451cdbeMathias Agopian            glDisable(GL_TEXTURE_EXTERNAL_OES);
152781953d62dc17d761e39540f0480e5ca7451cdbeMathias Agopian        }
153f8b4b4408cb864bf604608221eafa9d37323d348Mathias Agopian#endif
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        glEnable(GL_TEXTURE_2D);
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        glBindTexture(GL_TEXTURE_2D, mTextureName);
1562c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRefreshCache) {
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRefreshCache = false;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mAutoRefreshPending = false;
1602c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian
1612c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian            int32_t pixelSize = 4;
1622c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian            int32_t s = w;
1632c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian            if (mReadType == GL_UNSIGNED_SHORT_5_6_5) {
1642c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian                // allocate enough memory for 4-bytes (2 pixels) aligned data
1652c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian                s = (w + 1) & ~1;
1662c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian                pixelSize = 2;
1672c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian            }
1682c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian
1692c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian            uint16_t* const pixels = (uint16_t*)malloc(s*h*pixelSize);
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // This reads the frame-buffer, so a h/w GL would have to
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // finish() its rendering first. we don't want to do that
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // too often. Read data is 4-bytes aligned.
1742c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian            glReadPixels(X, Y, w, h, mReadFormat, mReadType, pixels);
1752c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // blur that texture.
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            GGLSurface bl;
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bl.version = sizeof(GGLSurface);
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bl.width = w;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bl.height = h;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bl.stride = s;
1822c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian            bl.format = mBlurFormat;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bl.data = (GGLubyte*)pixels;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            blurFilter(&bl, 8, 2);
185e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian
186781953d62dc17d761e39540f0480e5ca7451cdbeMathias Agopian            if (GLExtensions::getInstance().haveNpot()) {
1872c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian                glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, w, h, 0,
1882c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian                        mReadFormat, mReadType, pixels);
189e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian                mWidthScale  = 1.0f / w;
190e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian                mHeightScale =-1.0f / h;
191e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian                mYOffset = 0;
192e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian            } else {
193e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian                GLuint tw = 1 << (31 - clz(w));
194e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian                GLuint th = 1 << (31 - clz(h));
1954961c959aebac31991fd7653853d47dfd79d3472Mathias Agopian                if (tw < GLuint(w)) tw <<= 1;
1964961c959aebac31991fd7653853d47dfd79d3472Mathias Agopian                if (th < GLuint(h)) th <<= 1;
1972c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian                glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, tw, th, 0,
1982c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian                        mReadFormat, mReadType, NULL);
199e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian                glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h,
2002c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian                        mReadFormat, mReadType, pixels);
201e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian                mWidthScale  = 1.0f / tw;
202e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian                mHeightScale =-1.0f / th;
203e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian                mYOffset = th-h;
204e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian            }
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            free((void*)pixels);
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2082c68dd0483dd4f7b211bea32652d42c3c7cd602cMathias Agopian
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const State& s = drawingState();
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (UNLIKELY(s.alpha < 0xFF)) {
211e5c0a7b7810092a593ff386843927238c175bdbdMathias Agopian            const GLfloat alpha = s.alpha * (1.0f/255.0f);
212e5c0a7b7810092a593ff386843927238c175bdbdMathias Agopian            glColor4f(0, 0, 0, alpha);
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glEnable(GL_BLEND);
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glDisable(GL_BLEND);
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
220e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian        if (mFlags & DisplayHardware::SLOW_CONFIG) {
221e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian            glDisable(GL_DITHER);
222e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian        } else {
223e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian            glEnable(GL_DITHER);
224e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian        }
225e7c11d770ab44656d32330ba585489bd284b4a47Mathias Agopian
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
230e5c0a7b7810092a593ff386843927238c175bdbdMathias Agopian        glMatrixMode(GL_TEXTURE);
231e5c0a7b7810092a593ff386843927238c175bdbdMathias Agopian        glLoadIdentity();
232e5c0a7b7810092a593ff386843927238c175bdbdMathias Agopian        glScalef(mWidthScale, mHeightScale, 1);
233e5c0a7b7810092a593ff386843927238c175bdbdMathias Agopian        glTranslatef(-x, mYOffset - y, 0);
234e5c0a7b7810092a593ff386843927238c175bdbdMathias Agopian        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
235e5c0a7b7810092a593ff386843927238c175bdbdMathias Agopian        glVertexPointer(2, GL_FLOAT, 0, mVertices);
236e5c0a7b7810092a593ff386843927238c175bdbdMathias Agopian        glTexCoordPointer(2, GL_FLOAT, 0, mVertices);
237e5c0a7b7810092a593ff386843927238c175bdbdMathias Agopian        while (it != end) {
238e5c0a7b7810092a593ff386843927238c175bdbdMathias Agopian            const Rect& r = *it++;
239e5c0a7b7810092a593ff386843927238c175bdbdMathias Agopian            const GLint sy = fbHeight - (r.top + r.height());
240e5c0a7b7810092a593ff386843927238c175bdbdMathias Agopian            glScissor(r.left, sy, r.width(), r.height());
241e5c0a7b7810092a593ff386843927238c175bdbdMathias Agopian            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
243e5c0a7b7810092a593ff386843927238c175bdbdMathias Agopian        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
244e96aa3e859cb747e241dfa2999fcd142a688ed57Mathias Agopian        glLoadIdentity();
245e96aa3e859cb747e241dfa2999fcd142a688ed57Mathias Agopian        glMatrixMode(GL_MODELVIEW);
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; // namespace android
252