15541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown/*
25541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * Copyright (C) 2011 The Android Open Source Project
35541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown *
45541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
55541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * you may not use this file except in compliance with the License.
65541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * You may obtain a copy of the License at
75541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown *
85541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
95541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown *
105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * Unless required by applicable law or agreed to in writing, software
115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * See the License for the specific language governing permissions and
145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * limitations under the License.
155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown */
165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#define LOG_TAG "Sprites"
185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//#define LOG_NDEBUG 0
205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include "SpriteController.h"
225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <cutils/log.h>
245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <utils/String8.h>
255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkBitmap.h>
275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkCanvas.h>
285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkColor.h>
295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkPaint.h>
305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkXfermode.h>
315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownnamespace android {
335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown// --- SpriteController ---
355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::SpriteController(const sp<Looper>& looper, int32_t overlayLayer) :
375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mLooper(looper), mOverlayLayer(overlayLayer) {
385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    mHandler = new WeakMessageHandler(this);
392352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
402352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.transactionNestingCount = 0;
412352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.deferredSpriteUpdate = false;
425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::~SpriteController() {
455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    mLooper->removeMessages(mHandler);
465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mSurfaceComposerClient != NULL) {
485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mSurfaceComposerClient->dispose();
495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mSurfaceComposerClient.clear();
505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownsp<Sprite> SpriteController::createSprite() {
545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    return new SpriteImpl(this);
555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
572352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownvoid SpriteController::openTransaction() {
582352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    AutoMutex _l(mLock);
592352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
602352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.transactionNestingCount += 1;
612352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown}
622352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
632352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownvoid SpriteController::closeTransaction() {
642352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    AutoMutex _l(mLock);
652352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
662352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    LOG_ALWAYS_FATAL_IF(mLocked.transactionNestingCount == 0,
672352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            "Sprite closeTransaction() called but there is no open sprite transaction");
682352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
692352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.transactionNestingCount -= 1;
702352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.transactionNestingCount == 0 && mLocked.deferredSpriteUpdate) {
712352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.deferredSpriteUpdate = false;
722352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES));
732352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    }
742352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown}
752352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
765541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::invalidateSpriteLocked(const sp<SpriteImpl>& sprite) {
772352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    bool wasEmpty = mLocked.invalidatedSprites.isEmpty();
782352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.invalidatedSprites.push(sprite);
795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (wasEmpty) {
802352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        if (mLocked.transactionNestingCount != 0) {
812352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            mLocked.deferredSpriteUpdate = true;
822352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        } else {
832352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES));
842352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        }
855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl) {
892352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    bool wasEmpty = mLocked.disposedSurfaces.isEmpty();
902352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.disposedSurfaces.push(surfaceControl);
915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (wasEmpty) {
925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mLooper->sendMessage(mHandler, Message(MSG_DISPOSE_SURFACES));
935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
955541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::handleMessage(const Message& message) {
975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    switch (message.what) {
985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    case MSG_UPDATE_SPRITES:
995541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        doUpdateSprites();
1005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        break;
1015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    case MSG_DISPOSE_SURFACES:
1025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        doDisposeSurfaces();
1035541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        break;
1045541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1055541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
1065541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1075541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::doUpdateSprites() {
1085541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Collect information about sprite updates.
1095541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Each sprite update record includes a reference to its associated sprite so we can
1105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // be certain the sprites will not be deleted while this function runs.  Sprites
1115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // may invalidate themselves again during this time but we will handle those changes
1125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // in the next iteration.
1135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    Vector<SpriteUpdate> updates;
1145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    size_t numSprites;
1155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    { // acquire lock
1165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        AutoMutex _l(mLock);
1175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1182352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        numSprites = mLocked.invalidatedSprites.size();
1195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        for (size_t i = 0; i < numSprites; i++) {
1202352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            const sp<SpriteImpl>& sprite = mLocked.invalidatedSprites.itemAt(i);
1215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            updates.push(SpriteUpdate(sprite, sprite->getStateLocked()));
1235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            sprite->resetDirtyLocked();
1245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1252352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.invalidatedSprites.clear();
1265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } // release lock
1275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Create missing surfaces.
1295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    bool surfaceChanged = false;
1305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
1315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
1325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl == NULL && update.state.wantSurfaceVisible()) {
1342352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            update.state.surfaceWidth = update.state.icon.bitmap.width();
1352352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            update.state.surfaceHeight = update.state.icon.bitmap.height();
1365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceDrawn = false;
1375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceVisible = false;
1385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceControl = obtainSurface(
1395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceWidth, update.state.surfaceHeight);
1405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (update.state.surfaceControl != NULL) {
1415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                update.surfaceChanged = surfaceChanged = true;
1425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
1435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Resize sprites if needed, inside a global transaction.
1475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    bool haveGlobalTransaction = false;
1485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
1495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
1505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl != NULL && update.state.wantSurfaceVisible()) {
1522352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            int32_t desiredWidth = update.state.icon.bitmap.width();
1532352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            int32_t desiredHeight = update.state.icon.bitmap.height();
1545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (update.state.surfaceWidth < desiredWidth
1555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    || update.state.surfaceHeight < desiredHeight) {
1565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (!haveGlobalTransaction) {
1575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    SurfaceComposerClient::openGlobalTransaction();
1585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    haveGlobalTransaction = true;
1595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
1605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status_t status = update.state.surfaceControl->setSize(desiredWidth, desiredHeight);
1625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
1633762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d resizing sprite surface from %dx%d to %dx%d",
1645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            status, update.state.surfaceWidth, update.state.surfaceHeight,
1655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            desiredWidth, desiredHeight);
1665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
1675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceWidth = desiredWidth;
1685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceHeight = desiredHeight;
1695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceDrawn = false;
1705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
1715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1725541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    if (update.state.surfaceVisible) {
1735541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        status = update.state.surfaceControl->hide();
1745541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        if (status) {
1753762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                            ALOGE("Error %d hiding sprite surface after resize.", status);
1765541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        } else {
1775541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            update.state.surfaceVisible = false;
1785541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        }
1795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    }
1805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
1815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
1825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (haveGlobalTransaction) {
1855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SurfaceComposerClient::closeGlobalTransaction();
1865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Redraw sprites if needed.
1895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
1905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
1915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if ((update.state.dirty & DIRTY_BITMAP) && update.state.surfaceDrawn) {
1935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceDrawn = false;
1945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.surfaceChanged = surfaceChanged = true;
1955541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl != NULL && !update.state.surfaceDrawn
1985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                && update.state.wantSurfaceVisible()) {
1995541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            sp<Surface> surface = update.state.surfaceControl->getSurface();
2005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            Surface::SurfaceInfo surfaceInfo;
2015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            status_t status = surface->lock(&surfaceInfo);
2025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (status) {
2033762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                ALOGE("Error %d locking sprite surface before drawing.", status);
2045541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            } else {
2055541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                SkBitmap surfaceBitmap;
2065541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                ssize_t bpr = surfaceInfo.s * bytesPerPixel(surfaceInfo.format);
2075541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                surfaceBitmap.setConfig(SkBitmap::kARGB_8888_Config,
2085541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        surfaceInfo.w, surfaceInfo.h, bpr);
2095541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                surfaceBitmap.setPixels(surfaceInfo.bits);
2105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                SkCanvas surfaceCanvas;
2125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                surfaceCanvas.setBitmapDevice(surfaceBitmap);
2135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                SkPaint paint;
2155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                paint.setXfermodeMode(SkXfermode::kSrc_Mode);
2162352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                surfaceCanvas.drawBitmap(update.state.icon.bitmap, 0, 0, &paint);
2175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2182352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                if (surfaceInfo.w > uint32_t(update.state.icon.bitmap.width())) {
2195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    paint.setColor(0); // transparent fill color
2202352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                    surfaceCanvas.drawRectCoords(update.state.icon.bitmap.width(), 0,
2212352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                            surfaceInfo.w, update.state.icon.bitmap.height(), paint);
2225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2232352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                if (surfaceInfo.h > uint32_t(update.state.icon.bitmap.height())) {
2245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    paint.setColor(0); // transparent fill color
2252352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                    surfaceCanvas.drawRectCoords(0, update.state.icon.bitmap.height(),
2265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            surfaceInfo.w, surfaceInfo.h, paint);
2275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = surface->unlockAndPost();
2305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2313762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d unlocking and posting sprite surface after drawing.", status);
2325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
2335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceDrawn = true;
2345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
2355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
2385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
2395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Set sprite surface properties and make them visible.
2415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    bool haveTransaction = false;
2425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
2435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
2445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        bool wantSurfaceVisibleAndDrawn = update.state.wantSurfaceVisible()
2465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                && update.state.surfaceDrawn;
2475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        bool becomingVisible = wantSurfaceVisibleAndDrawn && !update.state.surfaceVisible;
2485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        bool becomingHidden = !wantSurfaceVisibleAndDrawn && update.state.surfaceVisible;
2495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl != NULL && (becomingVisible || becomingHidden
2505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                || (wantSurfaceVisibleAndDrawn && (update.state.dirty & (DIRTY_ALPHA
2515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        | DIRTY_POSITION | DIRTY_TRANSFORMATION_MATRIX | DIRTY_LAYER
2525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        | DIRTY_VISIBILITY | DIRTY_HOTSPOT))))) {
2535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            status_t status;
2545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (!haveTransaction) {
255439863f3b3e725b5de1cba4940a21900369961c0Mathias Agopian                SurfaceComposerClient::openGlobalTransaction();
2565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                haveTransaction = true;
2575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (wantSurfaceVisibleAndDrawn
2605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    && (becomingVisible || (update.state.dirty & DIRTY_ALPHA))) {
2615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->setAlpha(update.state.alpha);
2625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2633762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d setting sprite surface alpha.", status);
2645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (wantSurfaceVisibleAndDrawn
2685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    && (becomingVisible || (update.state.dirty & (DIRTY_POSITION
2695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            | DIRTY_HOTSPOT)))) {
2705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->setPosition(
2712352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                        update.state.positionX - update.state.icon.hotSpotX,
2722352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                        update.state.positionY - update.state.icon.hotSpotY);
2735541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2743762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d setting sprite surface position.", status);
2755541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2765541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2775541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2785541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (wantSurfaceVisibleAndDrawn
2795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    && (becomingVisible
2805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            || (update.state.dirty & DIRTY_TRANSFORMATION_MATRIX))) {
2815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->setMatrix(
2825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.transformationMatrix.dsdx,
2835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.transformationMatrix.dtdx,
2845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.transformationMatrix.dsdy,
2855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.transformationMatrix.dtdy);
2865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2873762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d setting sprite surface transformation matrix.", status);
2885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            int32_t surfaceLayer = mOverlayLayer + update.state.layer;
2925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (wantSurfaceVisibleAndDrawn
2935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    && (becomingVisible || (update.state.dirty & DIRTY_LAYER))) {
2945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->setLayer(surfaceLayer);
2955541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2963762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d setting sprite surface layer.", status);
2975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2995541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (becomingVisible) {
3014fd42e5a90e88e34d2e870852a4d26457a712d16Jeff Brown                status = update.state.surfaceControl->show();
3025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
3033762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d showing sprite surface.", status);
3045541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
3055541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceVisible = true;
3065541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
3075541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
3085541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            } else if (becomingHidden) {
3095541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->hide();
3105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
3113762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d hiding sprite surface.", status);
3125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
3135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceVisible = false;
3145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
3155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
3165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
3175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
3185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (haveTransaction) {
321439863f3b3e725b5de1cba4940a21900369961c0Mathias Agopian        SurfaceComposerClient::closeGlobalTransaction();
3225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // If any surfaces were changed, write back the new surface properties to the sprites.
3255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (surfaceChanged) { // acquire lock
3265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        AutoMutex _l(mLock);
3275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        for (size_t i = 0; i < numSprites; i++) {
3295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            const SpriteUpdate& update = updates.itemAt(i);
3305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (update.surfaceChanged) {
3325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                update.sprite->setSurfaceLocked(update.state.surfaceControl,
3335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.surfaceWidth, update.state.surfaceHeight,
3345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.surfaceDrawn, update.state.surfaceVisible);
3355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
3365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
3375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } // release lock
3385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Clear the sprite update vector outside the lock.  It is very important that
3405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // we do not clear sprite references inside the lock since we could be releasing
3415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // the last remaining reference to the sprite here which would result in the
3425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // sprite being deleted and the lock being reacquired by the sprite destructor
3435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // while already held.
3445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    updates.clear();
3455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::doDisposeSurfaces() {
3485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Collect disposed surfaces.
3495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    Vector<sp<SurfaceControl> > disposedSurfaces;
3505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    { // acquire lock
3512352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        AutoMutex _l(mLock);
3522352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
3532352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        disposedSurfaces = mLocked.disposedSurfaces;
3542352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.disposedSurfaces.clear();
3555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } // release lock
3565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Release the last reference to each surface outside of the lock.
3585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // We don't want the surfaces to be deleted while we are holding our lock.
3595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    disposedSurfaces.clear();
3605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::ensureSurfaceComposerClient() {
3635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mSurfaceComposerClient == NULL) {
3645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mSurfaceComposerClient = new SurfaceComposerClient();
3655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownsp<SurfaceControl> SpriteController::obtainSurface(int32_t width, int32_t height) {
3695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    ensureSurfaceComposerClient();
3705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    sp<SurfaceControl> surfaceControl = mSurfaceComposerClient->createSurface(
37264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            String8("Sprite"), width, height, PIXEL_FORMAT_RGBA_8888,
37364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            ISurfaceComposerClient::eHidden);
3742352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (surfaceControl == NULL || !surfaceControl->isValid()
3752352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            || !surfaceControl->getSurface()->isValid()) {
3763762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Error creating sprite surface.");
3775541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        return NULL;
3785541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    return surfaceControl;
3805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown// --- SpriteController::SpriteImpl ---
3845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::SpriteImpl::SpriteImpl(const sp<SpriteController> controller) :
3862352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mController(controller) {
3875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::SpriteImpl::~SpriteImpl() {
3905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _m(mController->mLock);
3915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Let the controller take care of deleting the last reference to sprite
3935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // surfaces so that we do not block the caller on an IPC here.
3942352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.surfaceControl != NULL) {
3952352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mController->disposeSurfaceLocked(mLocked.state.surfaceControl);
3962352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.surfaceControl.clear();
3975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3995541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4002352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownvoid SpriteController::SpriteImpl::setIcon(const SpriteIcon& icon) {
4015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4032352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    uint32_t dirty;
4042352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (icon.isValid()) {
4052352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        icon.bitmap.copyTo(&mLocked.state.icon.bitmap, SkBitmap::kARGB_8888_Config);
4062352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
4072352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        if (!mLocked.state.icon.isValid()
4082352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                || mLocked.state.icon.hotSpotX != icon.hotSpotX
4092352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                || mLocked.state.icon.hotSpotY != icon.hotSpotY) {
4102352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            mLocked.state.icon.hotSpotX = icon.hotSpotX;
4112352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            mLocked.state.icon.hotSpotY = icon.hotSpotY;
4122352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            dirty = DIRTY_BITMAP | DIRTY_HOTSPOT;
4132352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        } else {
4142352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            dirty = DIRTY_BITMAP;
4152352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        }
4162352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    } else if (mLocked.state.icon.isValid()) {
4172352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.icon.bitmap.reset();
4182352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        dirty = DIRTY_BITMAP | DIRTY_HOTSPOT;
4195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } else {
4202352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        return; // setting to invalid icon and already invalid so nothing to do
4215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    invalidateLocked(dirty);
4245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setVisible(bool visible) {
4275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4292352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.visible != visible) {
4302352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.visible = visible;
4315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_VISIBILITY);
4325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setPosition(float x, float y) {
436