SpriteController.cpp revision 4a9c3891d4f890109e02bc83fecf9bcdf56a9395
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>
2552800617946c456e78ed010c82d0ec4358368164Mathias Agopian#include <gui/Surface.h>
265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkBitmap.h>
285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkCanvas.h>
295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkColor.h>
305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkPaint.h>
315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkXfermode.h>
3252800617946c456e78ed010c82d0ec4358368164Mathias Agopian#include <android/native_window.h>
335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownnamespace android {
355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown// --- SpriteController ---
375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::SpriteController(const sp<Looper>& looper, int32_t overlayLayer) :
395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mLooper(looper), mOverlayLayer(overlayLayer) {
405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    mHandler = new WeakMessageHandler(this);
412352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
422352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.transactionNestingCount = 0;
432352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.deferredSpriteUpdate = false;
445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::~SpriteController() {
475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    mLooper->removeMessages(mHandler);
485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mSurfaceComposerClient != NULL) {
505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mSurfaceComposerClient->dispose();
515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mSurfaceComposerClient.clear();
525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownsp<Sprite> SpriteController::createSprite() {
565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    return new SpriteImpl(this);
575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
592352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownvoid SpriteController::openTransaction() {
602352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    AutoMutex _l(mLock);
612352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
622352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.transactionNestingCount += 1;
632352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown}
642352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
652352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownvoid SpriteController::closeTransaction() {
662352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    AutoMutex _l(mLock);
672352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
682352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    LOG_ALWAYS_FATAL_IF(mLocked.transactionNestingCount == 0,
692352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            "Sprite closeTransaction() called but there is no open sprite transaction");
702352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
712352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.transactionNestingCount -= 1;
722352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.transactionNestingCount == 0 && mLocked.deferredSpriteUpdate) {
732352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.deferredSpriteUpdate = false;
742352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES));
752352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    }
762352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown}
772352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
785541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::invalidateSpriteLocked(const sp<SpriteImpl>& sprite) {
792352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    bool wasEmpty = mLocked.invalidatedSprites.isEmpty();
802352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.invalidatedSprites.push(sprite);
815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (wasEmpty) {
822352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        if (mLocked.transactionNestingCount != 0) {
832352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            mLocked.deferredSpriteUpdate = true;
842352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        } else {
852352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES));
862352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        }
875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl) {
912352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    bool wasEmpty = mLocked.disposedSurfaces.isEmpty();
922352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.disposedSurfaces.push(surfaceControl);
935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (wasEmpty) {
945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mLooper->sendMessage(mHandler, Message(MSG_DISPOSE_SURFACES));
955541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::handleMessage(const Message& message) {
995541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    switch (message.what) {
1005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    case MSG_UPDATE_SPRITES:
1015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        doUpdateSprites();
1025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        break;
1035541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    case MSG_DISPOSE_SURFACES:
1045541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        doDisposeSurfaces();
1055541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        break;
1065541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1075541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
1085541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1095541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::doUpdateSprites() {
1105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Collect information about sprite updates.
1115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Each sprite update record includes a reference to its associated sprite so we can
1125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // be certain the sprites will not be deleted while this function runs.  Sprites
1135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // may invalidate themselves again during this time but we will handle those changes
1145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // in the next iteration.
1155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    Vector<SpriteUpdate> updates;
1165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    size_t numSprites;
1175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    { // acquire lock
1185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        AutoMutex _l(mLock);
1195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1202352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        numSprites = mLocked.invalidatedSprites.size();
1215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        for (size_t i = 0; i < numSprites; i++) {
1222352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            const sp<SpriteImpl>& sprite = mLocked.invalidatedSprites.itemAt(i);
1235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            updates.push(SpriteUpdate(sprite, sprite->getStateLocked()));
1255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            sprite->resetDirtyLocked();
1265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1272352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.invalidatedSprites.clear();
1285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } // release lock
1295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Create missing surfaces.
1315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    bool surfaceChanged = false;
1325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
1335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
1345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl == NULL && update.state.wantSurfaceVisible()) {
1362352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            update.state.surfaceWidth = update.state.icon.bitmap.width();
1372352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            update.state.surfaceHeight = update.state.icon.bitmap.height();
1385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceDrawn = false;
1395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceVisible = false;
1405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceControl = obtainSurface(
1415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceWidth, update.state.surfaceHeight);
1425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (update.state.surfaceControl != NULL) {
1435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                update.surfaceChanged = surfaceChanged = true;
1445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
1455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Resize sprites if needed, inside a global transaction.
1495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    bool haveGlobalTransaction = false;
1505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
1515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
1525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl != NULL && update.state.wantSurfaceVisible()) {
1542352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            int32_t desiredWidth = update.state.icon.bitmap.width();
1552352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            int32_t desiredHeight = update.state.icon.bitmap.height();
1565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (update.state.surfaceWidth < desiredWidth
1575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    || update.state.surfaceHeight < desiredHeight) {
1585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (!haveGlobalTransaction) {
1595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    SurfaceComposerClient::openGlobalTransaction();
1605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    haveGlobalTransaction = true;
1615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
1625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status_t status = update.state.surfaceControl->setSize(desiredWidth, desiredHeight);
1645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
1653762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d resizing sprite surface from %dx%d to %dx%d",
1665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            status, update.state.surfaceWidth, update.state.surfaceHeight,
1675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            desiredWidth, desiredHeight);
1685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
1695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceWidth = desiredWidth;
1705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceHeight = desiredHeight;
1715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceDrawn = false;
1725541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
1735541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1745541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    if (update.state.surfaceVisible) {
1755541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        status = update.state.surfaceControl->hide();
1765541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        if (status) {
1773762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                            ALOGE("Error %d hiding sprite surface after resize.", status);
1785541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        } else {
1795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            update.state.surfaceVisible = false;
1805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        }
1815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    }
1825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
1835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
1845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (haveGlobalTransaction) {
1875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SurfaceComposerClient::closeGlobalTransaction();
1885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Redraw sprites if needed.
1915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
1925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
1935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if ((update.state.dirty & DIRTY_BITMAP) && update.state.surfaceDrawn) {
1955541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceDrawn = false;
1965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.surfaceChanged = surfaceChanged = true;
1975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1995541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl != NULL && !update.state.surfaceDrawn
2005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                && update.state.wantSurfaceVisible()) {
2015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            sp<Surface> surface = update.state.surfaceControl->getSurface();
20252800617946c456e78ed010c82d0ec4358368164Mathias Agopian            ANativeWindow_Buffer outBuffer;
20352800617946c456e78ed010c82d0ec4358368164Mathias Agopian            status_t status = surface->lock(&outBuffer, NULL);
2045541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (status) {
2053762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                ALOGE("Error %d locking sprite surface before drawing.", status);
2065541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            } else {
2075541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                SkBitmap surfaceBitmap;
20852800617946c456e78ed010c82d0ec4358368164Mathias Agopian                ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
209b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed                surfaceBitmap.installPixels(SkImageInfo::MakeN32Premul(outBuffer.width, outBuffer.height),
210b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed                                            outBuffer.bits, bpr);
2115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
212fc615a0f643408956fc0dc1b997871e2b27cee7eDerek Sollenberger                SkCanvas surfaceCanvas(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
2184d8779fc5b0f371b413a605e10c6efb0aa25036cMichael Wright                if (outBuffer.width > update.state.icon.bitmap.width()) {
2195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    paint.setColor(0); // transparent fill color
2202352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                    surfaceCanvas.drawRectCoords(update.state.icon.bitmap.width(), 0,
22152800617946c456e78ed010c82d0ec4358368164Mathias Agopian                            outBuffer.width, update.state.icon.bitmap.height(), paint);
2225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2234d8779fc5b0f371b413a605e10c6efb0aa25036cMichael Wright                if (outBuffer.height > update.state.icon.bitmap.height()) {
2245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    paint.setColor(0); // transparent fill color
2252352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                    surfaceCanvas.drawRectCoords(0, update.state.icon.bitmap.height(),
22652800617946c456e78ed010c82d0ec4358368164Mathias Agopian                            outBuffer.width, outBuffer.height, 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);
37452800617946c456e78ed010c82d0ec4358368164Mathias Agopian    if (surfaceControl == NULL || !surfaceControl->isValid()) {
3753762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Error creating sprite surface.");
3765541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        return NULL;
3775541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3785541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    return surfaceControl;
3795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown// --- SpriteController::SpriteImpl ---
3835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::SpriteImpl::SpriteImpl(const sp<SpriteController> controller) :
3852352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mController(controller) {
3865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::SpriteImpl::~SpriteImpl() {
3895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _m(mController->mLock);
3905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Let the controller take care of deleting the last reference to sprite
3925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // surfaces so that we do not block the caller on an IPC here.
3932352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.surfaceControl != NULL) {
3942352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mController->disposeSurfaceLocked(mLocked.state.surfaceControl);
3952352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.surfaceControl.clear();
3965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3992352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownvoid SpriteController::SpriteImpl::setIcon(const SpriteIcon& icon) {
4005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4022352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    uint32_t dirty;
4032352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (icon.isValid()) {
4044a9c3891d4f890109e02bc83fecf9bcdf56a9395Mike Reed        icon.bitmap.copyTo(&mLocked.state.icon.bitmap, kN32_SkColorType);
4052352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
4062352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        if (!mLocked.state.icon.isValid()
4072352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                || mLocked.state.icon.hotSpotX != icon.hotSpotX
4082352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                || mLocked.state.icon.hotSpotY != icon.hotSpotY) {
4092352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            mLocked.state.icon.hotSpotX = icon.hotSpotX;
4102352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            mLocked.state.icon.hotSpotY = icon.hotSpotY;
4112352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            dirty = DIRTY_BITMAP | DIRTY_HOTSPOT;
4122352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        } else {
4132352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            dirty = DIRTY_BITMAP;
4142352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        }
4152352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    } else if (mLocked.state.icon.isValid()) {
4162352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.icon.bitmap.reset();
4172352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        dirty = DIRTY_BITMAP | DIRTY_HOTSPOT;
4185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } else {
4192352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        return; // setting to invalid icon and already invalid so nothing to do
4205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    invalidateLocked(dirty);
4235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setVisible(bool visible) {
4265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4282352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.visible != visible) {
4292352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.visible = visible;
4305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_VISIBILITY);
4315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setPosition(float x, float y) {
4355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4372352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.positionX != x || mLocked.state.positionY != y) {
4382352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.positionX = x;
4392352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.positionY = y;
4405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_POSITION);
4415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setLayer(int32_t layer) {
4455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4472352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.layer != layer) {
4482352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.layer = layer;
4495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_LAYER);
4505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setAlpha(float alpha) {
4545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4562352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.alpha != alpha) {
4572352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.alpha = alpha;
4585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_ALPHA);
4595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setTransformationMatrix(
4635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        const SpriteTransformationMatrix& matrix) {
4645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4662352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.transformationMatrix != matrix) {
4672352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.transformationMatrix = matrix;
4685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_TRANSFORMATION_MATRIX);
4695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4722352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownvoid SpriteController::SpriteImpl::invalidateLocked(uint32_t dirty) {
4732352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    bool wasDirty = mLocked.state.dirty;
4742352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.state.dirty |= dirty;
4755541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4762352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (!wasDirty) {
4775541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mController->invalidateSpriteLocked(this);
4785541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown} // namespace android
482