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//#define LOG_NDEBUG 0
195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include "SpriteController.h"
215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2252eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn#include <log/log.h>
235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <utils/String8.h>
2452800617946c456e78ed010c82d0ec4358368164Mathias Agopian#include <gui/Surface.h>
255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2652eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn// ToDo: Fix code to be warning free
276b83b76dd18e2a727936839b397e6ed2ed4f5a46Andreas Gampe#pragma GCC diagnostic push
286b83b76dd18e2a727936839b397e6ed2ed4f5a46Andreas Gampe#pragma GCC diagnostic ignored "-Wunused-parameter"
295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkBitmap.h>
305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkCanvas.h>
315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkColor.h>
325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkPaint.h>
336b83b76dd18e2a727936839b397e6ed2ed4f5a46Andreas Gampe#pragma GCC diagnostic pop
346b83b76dd18e2a727936839b397e6ed2ed4f5a46Andreas Gampe
3552800617946c456e78ed010c82d0ec4358368164Mathias Agopian#include <android/native_window.h>
365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownnamespace android {
385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown// --- SpriteController ---
405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::SpriteController(const sp<Looper>& looper, int32_t overlayLayer) :
425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mLooper(looper), mOverlayLayer(overlayLayer) {
435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    mHandler = new WeakMessageHandler(this);
442352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
452352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.transactionNestingCount = 0;
462352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.deferredSpriteUpdate = false;
475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::~SpriteController() {
505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    mLooper->removeMessages(mHandler);
515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mSurfaceComposerClient != NULL) {
535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mSurfaceComposerClient->dispose();
545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mSurfaceComposerClient.clear();
555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownsp<Sprite> SpriteController::createSprite() {
595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    return new SpriteImpl(this);
605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
622352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownvoid SpriteController::openTransaction() {
632352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    AutoMutex _l(mLock);
642352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
652352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.transactionNestingCount += 1;
662352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown}
672352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
682352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownvoid SpriteController::closeTransaction() {
692352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    AutoMutex _l(mLock);
702352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
712352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    LOG_ALWAYS_FATAL_IF(mLocked.transactionNestingCount == 0,
722352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            "Sprite closeTransaction() called but there is no open sprite transaction");
732352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
742352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.transactionNestingCount -= 1;
752352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.transactionNestingCount == 0 && mLocked.deferredSpriteUpdate) {
762352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.deferredSpriteUpdate = false;
772352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES));
782352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    }
792352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown}
802352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::invalidateSpriteLocked(const sp<SpriteImpl>& sprite) {
822352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    bool wasEmpty = mLocked.invalidatedSprites.isEmpty();
832352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.invalidatedSprites.push(sprite);
845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (wasEmpty) {
852352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        if (mLocked.transactionNestingCount != 0) {
862352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            mLocked.deferredSpriteUpdate = true;
872352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        } else {
882352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES));
892352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        }
905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl) {
942352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    bool wasEmpty = mLocked.disposedSurfaces.isEmpty();
952352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.disposedSurfaces.push(surfaceControl);
965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (wasEmpty) {
975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mLooper->sendMessage(mHandler, Message(MSG_DISPOSE_SURFACES));
985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
995541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
1005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::handleMessage(const Message& message) {
1025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    switch (message.what) {
1035541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    case MSG_UPDATE_SPRITES:
1045541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        doUpdateSprites();
1055541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        break;
1065541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    case MSG_DISPOSE_SURFACES:
1075541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        doDisposeSurfaces();
1085541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        break;
1095541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
1115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::doUpdateSprites() {
1135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Collect information about sprite updates.
1145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Each sprite update record includes a reference to its associated sprite so we can
1155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // be certain the sprites will not be deleted while this function runs.  Sprites
1165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // may invalidate themselves again during this time but we will handle those changes
1175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // in the next iteration.
1185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    Vector<SpriteUpdate> updates;
1195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    size_t numSprites;
1205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    { // acquire lock
1215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        AutoMutex _l(mLock);
1225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1232352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        numSprites = mLocked.invalidatedSprites.size();
1245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        for (size_t i = 0; i < numSprites; i++) {
1252352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            const sp<SpriteImpl>& sprite = mLocked.invalidatedSprites.itemAt(i);
1265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            updates.push(SpriteUpdate(sprite, sprite->getStateLocked()));
1285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            sprite->resetDirtyLocked();
1295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1302352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.invalidatedSprites.clear();
1315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } // release lock
1325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Create missing surfaces.
1345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    bool surfaceChanged = false;
1355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
1365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
1375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl == NULL && update.state.wantSurfaceVisible()) {
1392352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            update.state.surfaceWidth = update.state.icon.bitmap.width();
1402352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            update.state.surfaceHeight = update.state.icon.bitmap.height();
1415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceDrawn = false;
1425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceVisible = false;
1435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceControl = obtainSurface(
1445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceWidth, update.state.surfaceHeight);
1455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (update.state.surfaceControl != NULL) {
1465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                update.surfaceChanged = surfaceChanged = true;
1475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
1485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Resize sprites if needed, inside a global transaction.
1525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    bool haveGlobalTransaction = false;
1535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
1545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
1555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl != NULL && update.state.wantSurfaceVisible()) {
1572352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            int32_t desiredWidth = update.state.icon.bitmap.width();
1582352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            int32_t desiredHeight = update.state.icon.bitmap.height();
1595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (update.state.surfaceWidth < desiredWidth
1605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    || update.state.surfaceHeight < desiredHeight) {
1615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (!haveGlobalTransaction) {
1625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    SurfaceComposerClient::openGlobalTransaction();
1635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    haveGlobalTransaction = true;
1645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
1655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status_t status = update.state.surfaceControl->setSize(desiredWidth, desiredHeight);
1675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
1683762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d resizing sprite surface from %dx%d to %dx%d",
1695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            status, update.state.surfaceWidth, update.state.surfaceHeight,
1705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            desiredWidth, desiredHeight);
1715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
1725541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceWidth = desiredWidth;
1735541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceHeight = desiredHeight;
1745541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceDrawn = false;
1755541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
1765541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1775541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    if (update.state.surfaceVisible) {
1785541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        status = update.state.surfaceControl->hide();
1795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        if (status) {
1803762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                            ALOGE("Error %d hiding sprite surface after resize.", status);
1815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        } else {
1825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            update.state.surfaceVisible = false;
1835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        }
1845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    }
1855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
1865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
1875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (haveGlobalTransaction) {
1905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SurfaceComposerClient::closeGlobalTransaction();
1915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Redraw sprites if needed.
1945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
1955541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
1965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if ((update.state.dirty & DIRTY_BITMAP) && update.state.surfaceDrawn) {
1985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceDrawn = false;
1995541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.surfaceChanged = surfaceChanged = true;
2005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
2015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl != NULL && !update.state.surfaceDrawn
2035541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                && update.state.wantSurfaceVisible()) {
2045541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            sp<Surface> surface = update.state.surfaceControl->getSurface();
20552800617946c456e78ed010c82d0ec4358368164Mathias Agopian            ANativeWindow_Buffer outBuffer;
20652800617946c456e78ed010c82d0ec4358368164Mathias Agopian            status_t status = surface->lock(&outBuffer, NULL);
2075541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (status) {
2083762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                ALOGE("Error %d locking sprite surface before drawing.", status);
2095541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            } else {
2105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                SkBitmap surfaceBitmap;
21152800617946c456e78ed010c82d0ec4358368164Mathias Agopian                ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
212b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed                surfaceBitmap.installPixels(SkImageInfo::MakeN32Premul(outBuffer.width, outBuffer.height),
213b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed                                            outBuffer.bits, bpr);
2145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
215fc615a0f643408956fc0dc1b997871e2b27cee7eDerek Sollenberger                SkCanvas surfaceCanvas(surfaceBitmap);
2165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                SkPaint paint;
218260ab726486317496bc12a57d599ea96dcde3284Mike Reed                paint.setBlendMode(SkBlendMode::kSrc);
2192352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                surfaceCanvas.drawBitmap(update.state.icon.bitmap, 0, 0, &paint);
2205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2214d8779fc5b0f371b413a605e10c6efb0aa25036cMichael Wright                if (outBuffer.width > update.state.icon.bitmap.width()) {
2225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    paint.setColor(0); // transparent fill color
2232352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                    surfaceCanvas.drawRectCoords(update.state.icon.bitmap.width(), 0,
22452800617946c456e78ed010c82d0ec4358368164Mathias Agopian                            outBuffer.width, update.state.icon.bitmap.height(), paint);
2255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2264d8779fc5b0f371b413a605e10c6efb0aa25036cMichael Wright                if (outBuffer.height > update.state.icon.bitmap.height()) {
2275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    paint.setColor(0); // transparent fill color
2282352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                    surfaceCanvas.drawRectCoords(0, update.state.icon.bitmap.height(),
22952800617946c456e78ed010c82d0ec4358368164Mathias Agopian                            outBuffer.width, outBuffer.height, paint);
2305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = surface->unlockAndPost();
2335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2343762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d unlocking and posting sprite surface after drawing.", status);
2355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
2365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceDrawn = true;
2375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
2385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
2415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
2425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Set sprite surface properties and make them visible.
2445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    bool haveTransaction = false;
2455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
2465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
2475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        bool wantSurfaceVisibleAndDrawn = update.state.wantSurfaceVisible()
2495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                && update.state.surfaceDrawn;
2505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        bool becomingVisible = wantSurfaceVisibleAndDrawn && !update.state.surfaceVisible;
2515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        bool becomingHidden = !wantSurfaceVisibleAndDrawn && update.state.surfaceVisible;
2525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl != NULL && (becomingVisible || becomingHidden
2535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                || (wantSurfaceVisibleAndDrawn && (update.state.dirty & (DIRTY_ALPHA
2545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        | DIRTY_POSITION | DIRTY_TRANSFORMATION_MATRIX | DIRTY_LAYER
2555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        | DIRTY_VISIBILITY | DIRTY_HOTSPOT))))) {
2565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            status_t status;
2575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (!haveTransaction) {
258439863f3b3e725b5de1cba4940a21900369961c0Mathias Agopian                SurfaceComposerClient::openGlobalTransaction();
2595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                haveTransaction = true;
2605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (wantSurfaceVisibleAndDrawn
2635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    && (becomingVisible || (update.state.dirty & DIRTY_ALPHA))) {
2645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->setAlpha(update.state.alpha);
2655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2663762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d setting sprite surface alpha.", status);
2675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (wantSurfaceVisibleAndDrawn
2715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    && (becomingVisible || (update.state.dirty & (DIRTY_POSITION
2725541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            | DIRTY_HOTSPOT)))) {
2735541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->setPosition(
2742352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                        update.state.positionX - update.state.icon.hotSpotX,
2752352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                        update.state.positionY - update.state.icon.hotSpotY);
2765541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2773762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d setting sprite surface position.", status);
2785541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (wantSurfaceVisibleAndDrawn
2825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    && (becomingVisible
2835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            || (update.state.dirty & DIRTY_TRANSFORMATION_MATRIX))) {
2845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->setMatrix(
2855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.transformationMatrix.dsdx,
2865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.transformationMatrix.dtdx,
2875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.transformationMatrix.dsdy,
2885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.transformationMatrix.dtdy);
2895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2903762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d setting sprite surface transformation matrix.", status);
2915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            int32_t surfaceLayer = mOverlayLayer + update.state.layer;
2955541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (wantSurfaceVisibleAndDrawn
2965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    && (becomingVisible || (update.state.dirty & DIRTY_LAYER))) {
2975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->setLayer(surfaceLayer);
2985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2993762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d setting sprite surface layer.", status);
3005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
3015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
3025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3035541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (becomingVisible) {
3044fd42e5a90e88e34d2e870852a4d26457a712d16Jeff Brown                status = update.state.surfaceControl->show();
3055541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
3063762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d showing sprite surface.", status);
3075541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
3085541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceVisible = true;
3095541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
3105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
3115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            } else if (becomingHidden) {
3125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->hide();
3135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
3143762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d hiding sprite surface.", status);
3155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
3165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceVisible = false;
3175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
3185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
3195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
3205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
3215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (haveTransaction) {
324439863f3b3e725b5de1cba4940a21900369961c0Mathias Agopian        SurfaceComposerClient::closeGlobalTransaction();
3255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // If any surfaces were changed, write back the new surface properties to the sprites.
3285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (surfaceChanged) { // acquire lock
3295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        AutoMutex _l(mLock);
3305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        for (size_t i = 0; i < numSprites; i++) {
3325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            const SpriteUpdate& update = updates.itemAt(i);
3335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (update.surfaceChanged) {
3355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                update.sprite->setSurfaceLocked(update.state.surfaceControl,
3365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.surfaceWidth, update.state.surfaceHeight,
3375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.surfaceDrawn, update.state.surfaceVisible);
3385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
3395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
3405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } // release lock
3415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Clear the sprite update vector outside the lock.  It is very important that
3435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // we do not clear sprite references inside the lock since we could be releasing
3445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // the last remaining reference to the sprite here which would result in the
3455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // sprite being deleted and the lock being reacquired by the sprite destructor
3465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // while already held.
3475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    updates.clear();
3485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::doDisposeSurfaces() {
3515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Collect disposed surfaces.
3525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    Vector<sp<SurfaceControl> > disposedSurfaces;
3535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    { // acquire lock
3542352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        AutoMutex _l(mLock);
3552352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
3562352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        disposedSurfaces = mLocked.disposedSurfaces;
3572352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.disposedSurfaces.clear();
3585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } // release lock
3595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Release the last reference to each surface outside of the lock.
3615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // We don't want the surfaces to be deleted while we are holding our lock.
3625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    disposedSurfaces.clear();
3635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::ensureSurfaceComposerClient() {
3665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mSurfaceComposerClient == NULL) {
3675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mSurfaceComposerClient = new SurfaceComposerClient();
3685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownsp<SurfaceControl> SpriteController::obtainSurface(int32_t width, int32_t height) {
3725541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    ensureSurfaceComposerClient();
3735541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3745541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    sp<SurfaceControl> surfaceControl = mSurfaceComposerClient->createSurface(
37564a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            String8("Sprite"), width, height, PIXEL_FORMAT_RGBA_8888,
37668eccdade2aad22b7eb34a28572c204dcd54f7b9Riley Andrews            ISurfaceComposerClient::eHidden |
37768eccdade2aad22b7eb34a28572c204dcd54f7b9Riley Andrews            ISurfaceComposerClient::eCursorWindow);
37852800617946c456e78ed010c82d0ec4358368164Mathias Agopian    if (surfaceControl == NULL || !surfaceControl->isValid()) {
3793762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Error creating sprite surface.");
3805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        return NULL;
3815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    return surfaceControl;
3835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown// --- SpriteController::SpriteImpl ---
3875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::SpriteImpl::SpriteImpl(const sp<SpriteController> controller) :
3892352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mController(controller) {
3905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::SpriteImpl::~SpriteImpl() {
3935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _m(mController->mLock);
3945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3955541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Let the controller take care of deleting the last reference to sprite
3965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // surfaces so that we do not block the caller on an IPC here.
3972352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.surfaceControl != NULL) {
3982352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mController->disposeSurfaceLocked(mLocked.state.surfaceControl);
3992352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.surfaceControl.clear();
4005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4032352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownvoid SpriteController::SpriteImpl::setIcon(const SpriteIcon& icon) {
4045541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4055541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4062352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    uint32_t dirty;
4072352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (icon.isValid()) {
4084a9c3891d4f890109e02bc83fecf9bcdf56a9395Mike Reed        icon.bitmap.copyTo(&mLocked.state.icon.bitmap, kN32_SkColorType);
4092352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
4102352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        if (!mLocked.state.icon.isValid()
4112352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                || mLocked.state.icon.hotSpotX != icon.hotSpotX
4122352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                || mLocked.state.icon.hotSpotY != icon.hotSpotY) {
4132352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            mLocked.state.icon.hotSpotX = icon.hotSpotX;
4142352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            mLocked.state.icon.hotSpotY = icon.hotSpotY;
4152352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            dirty = DIRTY_BITMAP | DIRTY_HOTSPOT;
4162352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        } else {
4172352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            dirty = DIRTY_BITMAP;
4182352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        }
4192352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    } else if (mLocked.state.icon.isValid()) {
4202352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.icon.bitmap.reset();
4212352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        dirty = DIRTY_BITMAP | DIRTY_HOTSPOT;
4225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } else {
4232352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        return; // setting to invalid icon and already invalid so nothing to do
4245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    invalidateLocked(dirty);
4275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setVisible(bool visible) {
4305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4322352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.visible != visible) {
4332352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.visible = visible;
4345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_VISIBILITY);
4355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setPosition(float x, float y) {
4395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4412352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.positionX != x || mLocked.state.positionY != y) {
4422352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.positionX = x;
4432352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.positionY = y;
4445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_POSITION);
4455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setLayer(int32_t layer) {
4495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4512352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.layer != layer) {
4522352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.layer = layer;
4535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_LAYER);
4545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setAlpha(float alpha) {
4585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4602352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.alpha != alpha) {
4612352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.alpha = alpha;
4625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_ALPHA);
4635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setTransformationMatrix(
4675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        const SpriteTransformationMatrix& matrix) {
4685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4702352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.transformationMatrix != matrix) {
4712352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.transformationMatrix = matrix;
4725541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_TRANSFORMATION_MATRIX);
4735541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4745541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4755541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4762352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownvoid SpriteController::SpriteImpl::invalidateLocked(uint32_t dirty) {
4772352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    bool wasDirty = mLocked.state.dirty;
4782352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.state.dirty |= dirty;
4795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4802352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (!wasDirty) {
4815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mController->invalidateSpriteLocked(this);
4825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown} // namespace android
486