LayerBlur.cpp revision 6158b1bf0364da1582468a98ec09d004ba99deec
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
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "BlurFilter.h"
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "LayerBlur.h"
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SurfaceFlinger.h"
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "DisplayHardware/DisplayHardware.h"
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst uint32_t LayerBlur::typeInfo = LayerBaseClient::typeInfo | 8;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst char* const LayerBlur::typeID = "LayerBlur";
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectLayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Client* client, int32_t i)
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     : LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     mRefreshCache(true), mCacheAge(0), mTextureName(-1U)
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectLayerBlur::~LayerBlur()
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mTextureName != -1U) {
5081b0aa696ac954180caec6cb8cc1bb97440e03b5Mathias Agopian        glDeleteTextures(1, &mTextureName);
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid LayerBlur::setVisibleRegion(const Region& visibleRegion)
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LayerBaseClient::setVisibleRegion(visibleRegion);
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (visibleRegionScreen.isEmpty()) {
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mTextureName != -1U) {
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // We're not visible, free the texture up.
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glBindTexture(GL_TEXTURE_2D, 0);
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glDeleteTextures(1, &mTextureName);
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTextureName = -1U;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectuint32_t LayerBlur::doTransaction(uint32_t flags)
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // we're doing a transaction, refresh the cache!
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!mFlinger->isFrozen()) {
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRefreshCache = true;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheDirty = true;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        flags |= eVisibleRegion;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this->contentDirty = true;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return LayerBase::doTransaction(flags);
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid LayerBlur::unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion)
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // this code-path must be as tight as possible, it's called each time
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // the screen is composited.
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (UNLIKELY(!visibleRegionScreen.isEmpty())) {
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // if anything visible below us is invalidated, the cache becomes dirty
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mCacheDirty &&
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                !visibleRegionScreen.intersect(outDirtyRegion).isEmpty()) {
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCacheDirty = true;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCacheDirty) {
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mFlinger->isFrozen()) {
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // update everything below us that is visible
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                outDirtyRegion.orSelf(visibleRegionScreen);
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                nsecs_t now = systemTime();
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((now - mCacheAge) >= ms2ns(500)) {
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCacheAge = now;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mRefreshCache = true;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCacheDirty = false;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!mAutoRefreshPending) {
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mFlinger->signalDelayedEvent(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);
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1396158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian    Region::const_iterator it = clip.begin();
1406158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian    Region::const_iterator const end = clip.end();
1416158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian    if (it != end) {
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        glEnable(GL_TEXTURE_2D);
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        glBindTexture(GL_TEXTURE_2D, mTextureName);
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRefreshCache) {
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRefreshCache = false;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mAutoRefreshPending = false;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // allocate enough memory for 4-bytes (2 pixels) aligned data
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const int32_t s = (w + 1) & ~1;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            uint16_t* const pixels = (uint16_t*)malloc(s*h*2);
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // This reads the frame-buffer, so a h/w GL would have to
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // finish() its rendering first. we don't want to do that
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // too often. Read data is 4-bytes aligned.
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glReadPixels(X, Y, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // blur that texture.
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            GGLSurface bl;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bl.version = sizeof(GGLSurface);
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bl.width = w;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bl.height = h;
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bl.stride = s;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bl.format = GGL_PIXEL_FORMAT_RGB_565;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bl.data = (GGLubyte*)pixels;
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            blurFilter(&bl, 8, 2);
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // NOTE: this works only because we have POT. we'd have to round the
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // texture size up, otherwise.
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            free((void*)pixels);
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const State& s = drawingState();
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (UNLIKELY(s.alpha < 0xFF)) {
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const GGLfixed alpha = (s.alpha << 16)/255;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glColor4x(0, 0, 0, alpha);
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glEnable(GL_BLEND);
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glDisable(GL_BLEND);
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        glDisable(GL_DITHER);
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (UNLIKELY(transformed()
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) {
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // This is a very rare scenario.
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glMatrixMode(GL_TEXTURE);
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glLoadIdentity();
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glScalef(1.0f/w, -1.0f/h, 1);
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glTranslatef(-x, -y, 0);
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glVertexPointer(2, GL_FIXED, 0, mVertices);
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glTexCoordPointer(2, GL_FIXED, 0, mVertices);
2026158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian            while (it != end) {
2036158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian                const Rect& r = *it++;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                const GLint sy = fbHeight - (r.top + r.height());
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                glScissor(r.left, sy, r.width(), r.height());
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2096158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian            // NOTE: this is marginally faster with the software gl, because
2106158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian            // glReadPixels() reads the fb bottom-to-top, however we'll
2116158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian            // skip all the jaccobian computations.
2126158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian            Rect r;
2136158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian            GLint crop[4] = { 0, 0, w, h };
2146158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian            glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
2156158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian            y = fbHeight - (y + h);
2166158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian            while (it != end) {
2176158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian                const Rect& r = *it++;
2186158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian                const GLint sy = fbHeight - (r.top + r.height());
2196158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian                glScissor(r.left, sy, r.width(), r.height());
2206158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian                glDrawTexiOES(x, y, 0, w, h);
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; // namespace android
231