SpriteController.cpp revision 5541de9ea3513a12d1ac2ad07e7e04a3aa7741a0
170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve/*
270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve * Copyright (C) 2011 The Android Open Source Project
370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve *
470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve * Licensed under the Apache License, Version 2.0 (the "License");
570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve * you may not use this file except in compliance with the License.
670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve * You may obtain a copy of the License at
770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve *
870bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve *      http://www.apache.org/licenses/LICENSE-2.0
970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve *
1070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve * Unless required by applicable law or agreed to in writing, software
1170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve * distributed under the License is distributed on an "AS IS" BASIS,
1270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve * See the License for the specific language governing permissions and
1470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve * limitations under the License.
155b79591450c47920139705712a402251af7eed79Vikram S. Adve */
16822b4fb896846b87dd11a330ae13f2239329aeefChris Lattner
176e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve#define LOG_TAG "Sprites"
185b79591450c47920139705712a402251af7eed79Vikram S. Adve
1970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve//#define LOG_NDEBUG 0
2070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
215b79591450c47920139705712a402251af7eed79Vikram S. Adve#include "SpriteController.h"
2270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
2370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve#include <cutils/log.h>
2470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve#include <utils/String8.h>
251885da4f49cf32efde2d4c840365c4333a0c8579Vikram S. Adve
2670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve#include <SkBitmap.h>
2770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve#include <SkCanvas.h>
2870bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve#include <SkColor.h>
2970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve#include <SkPaint.h>
306a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve#include <SkXfermode.h>
3170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
321885da4f49cf32efde2d4c840365c4333a0c8579Vikram S. Advenamespace android {
331885da4f49cf32efde2d4c840365c4333a0c8579Vikram S. Adve
341885da4f49cf32efde2d4c840365c4333a0c8579Vikram S. Adve// --- SpriteController ---
351885da4f49cf32efde2d4c840365c4333a0c8579Vikram S. Adve
361885da4f49cf32efde2d4c840365c4333a0c8579Vikram S. AdveSpriteController::SpriteController(const sp<Looper>& looper, int32_t overlayLayer) :
371885da4f49cf32efde2d4c840365c4333a0c8579Vikram S. Adve        mLooper(looper), mOverlayLayer(overlayLayer) {
381885da4f49cf32efde2d4c840365c4333a0c8579Vikram S. Adve    mHandler = new WeakMessageHandler(this);
391885da4f49cf32efde2d4c840365c4333a0c8579Vikram S. Adve}
401885da4f49cf32efde2d4c840365c4333a0c8579Vikram S. Adve
411885da4f49cf32efde2d4c840365c4333a0c8579Vikram S. AdveSpriteController::~SpriteController() {
421885da4f49cf32efde2d4c840365c4333a0c8579Vikram S. Adve    mLooper->removeMessages(mHandler);
4370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
4470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    if (mSurfaceComposerClient != NULL) {
4570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        mSurfaceComposerClient->dispose();
4670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        mSurfaceComposerClient.clear();
4770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    }
4845c171ee25619f6650e90fa5e3102d9969fd82b3Ruchira Sasanka}
4970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
506a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Advesp<Sprite> SpriteController::createSprite() {
5170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    return new SpriteImpl(this);
52149977b48a02735861697d5b4df1fe5a8592245fVikram S. Adve}
536e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve
5470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Advevoid SpriteController::invalidateSpriteLocked(const sp<SpriteImpl>& sprite) {
5570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    bool wasEmpty = mInvalidatedSprites.isEmpty();
5670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    mInvalidatedSprites.push(sprite);
5770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    if (wasEmpty) {
5870bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES));
5945c171ee25619f6650e90fa5e3102d9969fd82b3Ruchira Sasanka    }
6070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve}
616a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve
6270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Advevoid SpriteController::disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl) {
63149977b48a02735861697d5b4df1fe5a8592245fVikram S. Adve    bool wasEmpty = mDisposedSurfaces.isEmpty();
646e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve    mDisposedSurfaces.push(surfaceControl);
6570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    if (wasEmpty) {
6670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        mLooper->sendMessage(mHandler, Message(MSG_DISPOSE_SURFACES));
6770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    }
6870bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve}
6945c171ee25619f6650e90fa5e3102d9969fd82b3Ruchira Sasanka
7070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Advevoid SpriteController::handleMessage(const Message& message) {
716a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve    switch (message.what) {
7270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    case MSG_UPDATE_SPRITES:
73149977b48a02735861697d5b4df1fe5a8592245fVikram S. Adve        doUpdateSprites();
746e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve        break;
7570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    case MSG_DISPOSE_SURFACES:
7670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        doDisposeSurfaces();
7770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        break;
780b03c6a492a0e09049b6c0bd127bd0ede7732aa5Ruchira Sasanka    }
7970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve}
8070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
8170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Advevoid SpriteController::doUpdateSprites() {
8270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    // Collect information about sprite updates.
8370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    // Each sprite update record includes a reference to its associated sprite so we can
8470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    // be certain the sprites will not be deleted while this function runs.  Sprites
8570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    // may invalidate themselves again during this time but we will handle those changes
8670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    // in the next iteration.
8770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    Vector<SpriteUpdate> updates;
8870bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    size_t numSprites;
896a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve    { // acquire lock
9070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        AutoMutex _l(mLock);
9170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
9270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        numSprites = mInvalidatedSprites.size();
9370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        for (size_t i = 0; i < numSprites; i++) {
946a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve            const sp<SpriteImpl>& sprite = mInvalidatedSprites.itemAt(i);
956a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve
966a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve            updates.push(SpriteUpdate(sprite, sprite->getStateLocked()));
976a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve            sprite->resetDirtyLocked();
986a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve        }
996a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve        mInvalidatedSprites.clear();
1006a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve    } // release lock
1016a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve
1026a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve    // Create missing surfaces.
1036a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve    bool surfaceChanged = false;
1046a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve    for (size_t i = 0; i < numSprites; i++) {
10570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        SpriteUpdate& update = updates.editItemAt(i);
10670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
10770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        if (update.state.surfaceControl == NULL && update.state.wantSurfaceVisible()) {
1086e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve            update.state.surfaceWidth = update.state.bitmap.width();
1096e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve            update.state.surfaceHeight = update.state.bitmap.height();
1106e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve            update.state.surfaceDrawn = false;
1116e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve            update.state.surfaceVisible = false;
1126e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve            update.state.surfaceControl = obtainSurface(
1136e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                    update.state.surfaceWidth, update.state.surfaceHeight);
1146e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve            if (update.state.surfaceControl != NULL) {
1156e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                update.surfaceChanged = surfaceChanged = true;
1166e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve            }
1176e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve        }
1186e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve    }
1196e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve
1206e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve    // Resize sprites if needed, inside a global transaction.
1216e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve    bool haveGlobalTransaction = false;
122e6fdb11e1ae823d69e646e76828ccb5d427a9d3aChris Lattner    for (size_t i = 0; i < numSprites; i++) {
12370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        SpriteUpdate& update = updates.editItemAt(i);
124e6fdb11e1ae823d69e646e76828ccb5d427a9d3aChris Lattner
1256e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve        if (update.state.surfaceControl != NULL && update.state.wantSurfaceVisible()) {
1266e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve            int32_t desiredWidth = update.state.bitmap.width();
1276e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve            int32_t desiredHeight = update.state.bitmap.height();
1286e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve            if (update.state.surfaceWidth < desiredWidth
1296e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                    || update.state.surfaceHeight < desiredHeight) {
1306e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                if (!haveGlobalTransaction) {
1316e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                    SurfaceComposerClient::openGlobalTransaction();
1326e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                    haveGlobalTransaction = true;
1336e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                }
1346e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve
1356e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                status_t status = update.state.surfaceControl->setSize(desiredWidth, desiredHeight);
1366e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                if (status) {
1376e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                    LOGE("Error %d resizing sprite surface from %dx%d to %dx%d",
1386e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                            status, update.state.surfaceWidth, update.state.surfaceHeight,
1396e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                            desiredWidth, desiredHeight);
1406e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                } else {
1416e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                    update.state.surfaceWidth = desiredWidth;
142e949da5bb18f89de40b6781237dfe616cba7bfc9Vikram S. Adve                    update.state.surfaceHeight = desiredHeight;
143e949da5bb18f89de40b6781237dfe616cba7bfc9Vikram S. Adve                    update.state.surfaceDrawn = false;
144e949da5bb18f89de40b6781237dfe616cba7bfc9Vikram S. Adve                    update.surfaceChanged = surfaceChanged = true;
145e949da5bb18f89de40b6781237dfe616cba7bfc9Vikram S. Adve
146e949da5bb18f89de40b6781237dfe616cba7bfc9Vikram S. Adve                    if (update.state.surfaceVisible) {
147e949da5bb18f89de40b6781237dfe616cba7bfc9Vikram S. Adve                        status = update.state.surfaceControl->hide();
148e949da5bb18f89de40b6781237dfe616cba7bfc9Vikram S. Adve                        if (status) {
1496e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                            LOGE("Error %d hiding sprite surface after resize.", status);
1506e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                        } else {
1516e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                            update.state.surfaceVisible = false;
1526e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                        }
153e6fdb11e1ae823d69e646e76828ccb5d427a9d3aChris Lattner                    }
15470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                }
15570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            }
15670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        }
15770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    }
15870bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    if (haveGlobalTransaction) {
15970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        SurfaceComposerClient::closeGlobalTransaction();
16070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    }
16170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
16270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    // Redraw sprites if needed.
16370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    for (size_t i = 0; i < numSprites; i++) {
16470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        SpriteUpdate& update = updates.editItemAt(i);
16570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
16670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        if ((update.state.dirty & DIRTY_BITMAP) && update.state.surfaceDrawn) {
16770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            update.state.surfaceDrawn = false;
16870bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            update.surfaceChanged = surfaceChanged = true;
169c2a2396e17f8fd6c78afd81368d2b80e8cfe6c42Chris Lattner        }
170c2a2396e17f8fd6c78afd81368d2b80e8cfe6c42Chris Lattner
17170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        if (update.state.surfaceControl != NULL && !update.state.surfaceDrawn
17270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                && update.state.wantSurfaceVisible()) {
17370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            sp<Surface> surface = update.state.surfaceControl->getSurface();
17470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            Surface::SurfaceInfo surfaceInfo;
17570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            status_t status = surface->lock(&surfaceInfo);
17670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            if (status) {
17770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                LOGE("Error %d locking sprite surface before drawing.", status);
17870bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            } else {
17970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                SkBitmap surfaceBitmap;
18070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                ssize_t bpr = surfaceInfo.s * bytesPerPixel(surfaceInfo.format);
18170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                surfaceBitmap.setConfig(SkBitmap::kARGB_8888_Config,
18270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                        surfaceInfo.w, surfaceInfo.h, bpr);
18370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                surfaceBitmap.setPixels(surfaceInfo.bits);
18470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
18570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                SkCanvas surfaceCanvas;
18670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                surfaceCanvas.setBitmapDevice(surfaceBitmap);
18770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
18870bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                SkPaint paint;
18970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                paint.setXfermodeMode(SkXfermode::kSrc_Mode);
1906a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                surfaceCanvas.drawBitmap(update.state.bitmap, 0, 0, &paint);
19170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
19270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                if (surfaceInfo.w > uint32_t(update.state.bitmap.width())) {
19370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    paint.setColor(0); // transparent fill color
19470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    surfaceCanvas.drawRectCoords(update.state.bitmap.width(), 0,
1956a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                            surfaceInfo.w, update.state.bitmap.height(), paint);
19670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                }
19770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                if (surfaceInfo.h > uint32_t(update.state.bitmap.height())) {
19870bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    paint.setColor(0); // transparent fill color
19970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    surfaceCanvas.drawRectCoords(0, update.state.bitmap.height(),
2006a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                            surfaceInfo.w, surfaceInfo.h, paint);
2016a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                }
20270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
20370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                status = surface->unlockAndPost();
2046e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                if (status) {
2056e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                    LOGE("Error %d unlocking and posting sprite surface after drawing.", status);
2066e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                } else {
2076e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                    update.state.surfaceDrawn = true;
2086e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                    update.surfaceChanged = surfaceChanged = true;
2096e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                }
21070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            }
21170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        }
21270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    }
21370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
21470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    // Set sprite surface properties and make them visible.
21570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    bool haveTransaction = false;
2165b79591450c47920139705712a402251af7eed79Vikram S. Adve    for (size_t i = 0; i < numSprites; i++) {
21770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        SpriteUpdate& update = updates.editItemAt(i);
21870bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
21970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        bool wantSurfaceVisibleAndDrawn = update.state.wantSurfaceVisible()
2206a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                && update.state.surfaceDrawn;
2216a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve        bool becomingVisible = wantSurfaceVisibleAndDrawn && !update.state.surfaceVisible;
22270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        bool becomingHidden = !wantSurfaceVisibleAndDrawn && update.state.surfaceVisible;
22370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        if (update.state.surfaceControl != NULL && (becomingVisible || becomingHidden
2246e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                || (wantSurfaceVisibleAndDrawn && (update.state.dirty & (DIRTY_ALPHA
2256e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                        | DIRTY_POSITION | DIRTY_TRANSFORMATION_MATRIX | DIRTY_LAYER
2266e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                        | DIRTY_VISIBILITY | DIRTY_HOTSPOT))))) {
2276e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve            status_t status;
2286e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve            if (!haveTransaction) {
229b221a763862ccaed46dee3fbf56c384981d84fbdChris Lattner                status = mSurfaceComposerClient->openTransaction();
230b221a763862ccaed46dee3fbf56c384981d84fbdChris Lattner                if (status) {
23170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    LOGE("Error %d opening transation to update sprite surface.", status);
23270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    break;
2335b79591450c47920139705712a402251af7eed79Vikram S. Adve                }
2345b79591450c47920139705712a402251af7eed79Vikram S. Adve                haveTransaction = true;
23570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            }
23670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
23770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            if (wantSurfaceVisibleAndDrawn
23870bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    && (becomingVisible || (update.state.dirty & DIRTY_ALPHA))) {
23970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                status = update.state.surfaceControl->setAlpha(update.state.alpha);
24070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                if (status) {
24170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    LOGE("Error %d setting sprite surface alpha.", status);
2426a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                }
24370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            }
2446a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve
24570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            if (wantSurfaceVisibleAndDrawn
2466a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                    && (becomingVisible || (update.state.dirty & (DIRTY_POSITION
2476a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                            | DIRTY_HOTSPOT)))) {
2486a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                status = update.state.surfaceControl->setPosition(
24970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                        update.state.positionX - update.state.hotSpotX,
2506e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                        update.state.positionY - update.state.hotSpotY);
2516e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                if (status) {
2526e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                    LOGE("Error %d setting sprite surface position.", status);
2536e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve                }
2546e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve            }
2556a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve
25670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            if (wantSurfaceVisibleAndDrawn
25770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    && (becomingVisible
2586a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                            || (update.state.dirty & DIRTY_TRANSFORMATION_MATRIX))) {
2596a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                status = update.state.surfaceControl->setMatrix(
2606a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                        update.state.transformationMatrix.dsdx,
2616a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                        update.state.transformationMatrix.dtdx,
26270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                        update.state.transformationMatrix.dsdy,
26370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                        update.state.transformationMatrix.dtdy);
26470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                if (status) {
2656a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                    LOGE("Error %d setting sprite surface transformation matrix.", status);
266149977b48a02735861697d5b4df1fe5a8592245fVikram S. Adve                }
26770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            }
268149977b48a02735861697d5b4df1fe5a8592245fVikram S. Adve
26970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            int32_t surfaceLayer = mOverlayLayer + update.state.layer;
27070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            if (wantSurfaceVisibleAndDrawn
27170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    && (becomingVisible || (update.state.dirty & DIRTY_LAYER))) {
2726a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                status = update.state.surfaceControl->setLayer(surfaceLayer);
27370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                if (status) {
27470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    LOGE("Error %d setting sprite surface layer.", status);
27570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                }
27670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            }
27770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
2786a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve            if (becomingVisible) {
27970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                status = update.state.surfaceControl->show(surfaceLayer);
28070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                if (status) {
28170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    LOGE("Error %d showing sprite surface.", status);
28270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                } else {
28370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    update.state.surfaceVisible = true;
28470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    update.surfaceChanged = surfaceChanged = true;
28570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                }
28670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            } else if (becomingHidden) {
28770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                status = update.state.surfaceControl->hide();
2886a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                if (status) {
28970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    LOGE("Error %d hiding sprite surface.", status);
29070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                } else {
29170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    update.state.surfaceVisible = false;
29270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                    update.surfaceChanged = surfaceChanged = true;
2936a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                }
29470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            }
29570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        }
29670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    }
2976e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve
2986e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve    if (haveTransaction) {
2996e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve        status_t status = mSurfaceComposerClient->closeTransaction();
30070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        if (status) {
3016e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve            LOGE("Error %d closing transaction to update sprite surface.", status);
3026e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve        }
30370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    }
30470bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
30570bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    // If any surfaces were changed, write back the new surface properties to the sprites.
30670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    if (surfaceChanged) { // acquire lock
30770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        AutoMutex _l(mLock);
30870bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
3096a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve        for (size_t i = 0; i < numSprites; i++) {
31070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            const SpriteUpdate& update = updates.itemAt(i);
31170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
31270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            if (update.surfaceChanged) {
31370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve                update.sprite->setSurfaceLocked(update.state.surfaceControl,
3146a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                        update.state.surfaceWidth, update.state.surfaceHeight,
3156a175e01eb164baac5cc16311c474ff644ce17c1Vikram S. Adve                        update.state.surfaceDrawn, update.state.surfaceVisible);
31670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve            }
31770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        }
31870bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    } // release lock
31970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
32070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    // Clear the sprite update vector outside the lock.  It is very important that
321990f2a5a1a0b16d0dc07cee486033c0a3864334eChris Lattner    // we do not clear sprite references inside the lock since we could be releasing
322990f2a5a1a0b16d0dc07cee486033c0a3864334eChris Lattner    // the last remaining reference to the sprite here which would result in the
323990f2a5a1a0b16d0dc07cee486033c0a3864334eChris Lattner    // sprite being deleted and the lock being reacquired by the sprite destructor
3246e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve    // while already held.
3256e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve    updates.clear();
3266e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve}
3276e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve
3286e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Advevoid SpriteController::doDisposeSurfaces() {
3296e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve    // Collect disposed surfaces.
3306e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve    Vector<sp<SurfaceControl> > disposedSurfaces;
3316e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve    { // acquire lock
332990f2a5a1a0b16d0dc07cee486033c0a3864334eChris Lattner        disposedSurfaces = mDisposedSurfaces;
3336e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve        mDisposedSurfaces.clear();
3346e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve    } // release lock
3356e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve
33670bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    // Release the last reference to each surface outside of the lock.
337990f2a5a1a0b16d0dc07cee486033c0a3864334eChris Lattner    // We don't want the surfaces to be deleted while we are holding our lock.
338990f2a5a1a0b16d0dc07cee486033c0a3864334eChris Lattner    disposedSurfaces.clear();
33970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve}
34070bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
34170bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Advevoid SpriteController::ensureSurfaceComposerClient() {
34270bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    if (mSurfaceComposerClient == NULL) {
34370bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve        mSurfaceComposerClient = new SurfaceComposerClient();
344990f2a5a1a0b16d0dc07cee486033c0a3864334eChris Lattner    }
3456e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve}
3466e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve
3476e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Advesp<SurfaceControl> SpriteController::obtainSurface(int32_t width, int32_t height) {
3486e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve    ensureSurfaceComposerClient();
3496e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve
3506e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve    sp<SurfaceControl> surfaceControl = mSurfaceComposerClient->createSurface(
3516e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve            getpid(), String8("Sprite"), 0, width, height, PIXEL_FORMAT_RGBA_8888);
3526e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve    if (surfaceControl == NULL) {
3536e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve        LOGE("Error creating sprite surface.");
3546e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve        return NULL;
355990f2a5a1a0b16d0dc07cee486033c0a3864334eChris Lattner    }
3566e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve    return surfaceControl;
3576e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve}
3586e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve
3596e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve
3606e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve// --- SpriteController::SpriteImpl ---
3616e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve
3626e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. AdveSpriteController::SpriteImpl::SpriteImpl(const sp<SpriteController> controller) :
3636e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve        mController(controller), mTransactionNestingCount(0) {
3646e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve}
3656e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. Adve
3666e447181928b95902c38ea89e57bc835ecd83cb5Vikram S. AdveSpriteController::SpriteImpl::~SpriteImpl() {
36770bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    AutoMutex _m(mController->mLock);
36870bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve
36970bc4b5d1a3795a8f41be96723cfcbccac8e1671Vikram S. Adve    // Let the controller take care of deleting the last reference to sprite
3705b79591450c47920139705712a402251af7eed79Vikram S. Adve    // surfaces so that we do not block the caller on an IPC here.
3715b79591450c47920139705712a402251af7eed79Vikram S. Adve    if (mState.surfaceControl != NULL) {
3725b79591450c47920139705712a402251af7eed79Vikram S. Adve        mController->disposeSurfaceLocked(mState.surfaceControl);
373ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka        mState.surfaceControl.clear();
374ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka    }
375ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka}
376ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka
377ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasankavoid SpriteController::SpriteImpl::setBitmap(const SkBitmap* bitmap,
378ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka        float hotSpotX, float hotSpotY) {
379ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka    AutoMutex _l(mController->mLock);
380ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka
381ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka    if (bitmap) {
382ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka        bitmap->copyTo(&mState.bitmap, SkBitmap::kARGB_8888_Config);
383ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka    } else {
384ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka        mState.bitmap.reset();
385ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka    }
386ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka
387ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka    uint32_t dirty = DIRTY_BITMAP;
388ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka    if (mState.hotSpotX != hotSpotX || mState.hotSpotY != hotSpotY) {
389ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka        mState.hotSpotX = hotSpotX;
390ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka        mState.hotSpotY = hotSpotY;
391ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka        dirty |= DIRTY_HOTSPOT;
392ed8f674b9a18312886355288ac49f9a2dd5e4e94Ruchira Sasanka    }
393
394    invalidateLocked(dirty);
395}
396
397void SpriteController::SpriteImpl::setVisible(bool visible) {
398    AutoMutex _l(mController->mLock);
399
400    if (mState.visible != visible) {
401        mState.visible = visible;
402        invalidateLocked(DIRTY_VISIBILITY);
403    }
404}
405
406void SpriteController::SpriteImpl::setPosition(float x, float y) {
407    AutoMutex _l(mController->mLock);
408
409    if (mState.positionX != x || mState.positionY != y) {
410        mState.positionX = x;
411        mState.positionY = y;
412        invalidateLocked(DIRTY_POSITION);
413    }
414}
415
416void SpriteController::SpriteImpl::setLayer(int32_t layer) {
417    AutoMutex _l(mController->mLock);
418
419    if (mState.layer != layer) {
420        mState.layer = layer;
421        invalidateLocked(DIRTY_LAYER);
422    }
423}
424
425void SpriteController::SpriteImpl::setAlpha(float alpha) {
426    AutoMutex _l(mController->mLock);
427
428    if (mState.alpha != alpha) {
429        mState.alpha = alpha;
430        invalidateLocked(DIRTY_ALPHA);
431    }
432}
433
434void SpriteController::SpriteImpl::setTransformationMatrix(
435        const SpriteTransformationMatrix& matrix) {
436    AutoMutex _l(mController->mLock);
437
438    if (mState.transformationMatrix != matrix) {
439        mState.transformationMatrix = matrix;
440        invalidateLocked(DIRTY_TRANSFORMATION_MATRIX);
441    }
442}
443
444void SpriteController::SpriteImpl::openTransaction() {
445    AutoMutex _l(mController->mLock);
446
447    mTransactionNestingCount += 1;
448}
449
450void SpriteController::SpriteImpl::closeTransaction() {
451    AutoMutex _l(mController->mLock);
452
453    LOG_ALWAYS_FATAL_IF(mTransactionNestingCount == 0,
454            "Sprite closeTransaction() called but there is no open sprite transaction");
455
456    mTransactionNestingCount -= 1;
457    if (mTransactionNestingCount == 0 && mState.dirty) {
458        mController->invalidateSpriteLocked(this);
459    }
460}
461
462void SpriteController::SpriteImpl::invalidateLocked(uint32_t dirty) {
463    if (mTransactionNestingCount > 0) {
464        bool wasDirty = mState.dirty;
465        mState.dirty |= dirty;
466        if (!wasDirty) {
467            mController->invalidateSpriteLocked(this);
468        }
469    }
470}
471
472} // namespace android
473