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
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>
335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkXfermode.h>
346b83b76dd18e2a727936839b397e6ed2ed4f5a46Andreas Gampe#pragma GCC diagnostic pop
356b83b76dd18e2a727936839b397e6ed2ed4f5a46Andreas Gampe
3652800617946c456e78ed010c82d0ec4358368164Mathias Agopian#include <android/native_window.h>
375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownnamespace android {
395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown// --- SpriteController ---
415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::SpriteController(const sp<Looper>& looper, int32_t overlayLayer) :
435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mLooper(looper), mOverlayLayer(overlayLayer) {
445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    mHandler = new WeakMessageHandler(this);
452352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
462352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.transactionNestingCount = 0;
472352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.deferredSpriteUpdate = false;
485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::~SpriteController() {
515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    mLooper->removeMessages(mHandler);
525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mSurfaceComposerClient != NULL) {
545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mSurfaceComposerClient->dispose();
555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mSurfaceComposerClient.clear();
565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownsp<Sprite> SpriteController::createSprite() {
605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    return new SpriteImpl(this);
615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
632352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownvoid SpriteController::openTransaction() {
642352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    AutoMutex _l(mLock);
652352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
662352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.transactionNestingCount += 1;
672352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown}
682352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
692352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownvoid SpriteController::closeTransaction() {
702352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    AutoMutex _l(mLock);
712352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
722352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    LOG_ALWAYS_FATAL_IF(mLocked.transactionNestingCount == 0,
732352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            "Sprite closeTransaction() called but there is no open sprite transaction");
742352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
752352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.transactionNestingCount -= 1;
762352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.transactionNestingCount == 0 && mLocked.deferredSpriteUpdate) {
772352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.deferredSpriteUpdate = false;
782352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES));
792352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    }
802352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown}
812352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::invalidateSpriteLocked(const sp<SpriteImpl>& sprite) {
832352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    bool wasEmpty = mLocked.invalidatedSprites.isEmpty();
842352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.invalidatedSprites.push(sprite);
855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (wasEmpty) {
862352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        if (mLocked.transactionNestingCount != 0) {
872352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            mLocked.deferredSpriteUpdate = true;
882352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        } else {
892352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES));
902352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        }
915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl) {
952352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    bool wasEmpty = mLocked.disposedSurfaces.isEmpty();
962352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.disposedSurfaces.push(surfaceControl);
975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (wasEmpty) {
985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mLooper->sendMessage(mHandler, Message(MSG_DISPOSE_SURFACES));
995541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
1015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::handleMessage(const Message& message) {
1035541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    switch (message.what) {
1045541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    case MSG_UPDATE_SPRITES:
1055541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        doUpdateSprites();
1065541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        break;
1075541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    case MSG_DISPOSE_SURFACES:
1085541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        doDisposeSurfaces();
1095541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        break;
1105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
1125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::doUpdateSprites() {
1145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Collect information about sprite updates.
1155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Each sprite update record includes a reference to its associated sprite so we can
1165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // be certain the sprites will not be deleted while this function runs.  Sprites
1175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // may invalidate themselves again during this time but we will handle those changes
1185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // in the next iteration.
1195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    Vector<SpriteUpdate> updates;
1205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    size_t numSprites;
1215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    { // acquire lock
1225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        AutoMutex _l(mLock);
1235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1242352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        numSprites = mLocked.invalidatedSprites.size();
1255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        for (size_t i = 0; i < numSprites; i++) {
1262352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            const sp<SpriteImpl>& sprite = mLocked.invalidatedSprites.itemAt(i);
1275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            updates.push(SpriteUpdate(sprite, sprite->getStateLocked()));
1295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            sprite->resetDirtyLocked();
1305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1312352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.invalidatedSprites.clear();
1325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } // release lock
1335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Create missing surfaces.
1355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    bool surfaceChanged = false;
1365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
1375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
1385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl == NULL && update.state.wantSurfaceVisible()) {
1402352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            update.state.surfaceWidth = update.state.icon.bitmap.width();
1412352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            update.state.surfaceHeight = update.state.icon.bitmap.height();
1425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceDrawn = false;
1435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceVisible = false;
1445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceControl = obtainSurface(
1455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceWidth, update.state.surfaceHeight);
1465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (update.state.surfaceControl != NULL) {
1475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                update.surfaceChanged = surfaceChanged = true;
1485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
1495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Resize sprites if needed, inside a global transaction.
1535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    bool haveGlobalTransaction = false;
1545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
1555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
1565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl != NULL && update.state.wantSurfaceVisible()) {
1582352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            int32_t desiredWidth = update.state.icon.bitmap.width();
1592352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            int32_t desiredHeight = update.state.icon.bitmap.height();
1605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (update.state.surfaceWidth < desiredWidth
1615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    || update.state.surfaceHeight < desiredHeight) {
1625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (!haveGlobalTransaction) {
1635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    SurfaceComposerClient::openGlobalTransaction();
1645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    haveGlobalTransaction = true;
1655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
1665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status_t status = update.state.surfaceControl->setSize(desiredWidth, desiredHeight);
1685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
1693762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d resizing sprite surface from %dx%d to %dx%d",
1705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            status, update.state.surfaceWidth, update.state.surfaceHeight,
1715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            desiredWidth, desiredHeight);
1725541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
1735541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceWidth = desiredWidth;
1745541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceHeight = desiredHeight;
1755541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceDrawn = false;
1765541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
1775541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1785541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    if (update.state.surfaceVisible) {
1795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        status = update.state.surfaceControl->hide();
1805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        if (status) {
1813762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                            ALOGE("Error %d hiding sprite surface after resize.", status);
1825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        } else {
1835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            update.state.surfaceVisible = false;
1845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        }
1855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    }
1865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
1875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
1885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (haveGlobalTransaction) {
1915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SurfaceComposerClient::closeGlobalTransaction();
1925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Redraw sprites if needed.
1955541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
1965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
1975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if ((update.state.dirty & DIRTY_BITMAP) && update.state.surfaceDrawn) {
1995541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceDrawn = false;
2005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.surfaceChanged = surfaceChanged = true;
2015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
2025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2035541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl != NULL && !update.state.surfaceDrawn
2045541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                && update.state.wantSurfaceVisible()) {
2055541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            sp<Surface> surface = update.state.surfaceControl->getSurface();
20652800617946c456e78ed010c82d0ec4358368164Mathias Agopian            ANativeWindow_Buffer outBuffer;
20752800617946c456e78ed010c82d0ec4358368164Mathias Agopian            status_t status = surface->lock(&outBuffer, NULL);
2085541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (status) {
2093762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                ALOGE("Error %d locking sprite surface before drawing.", status);
2105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            } else {
2115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                SkBitmap surfaceBitmap;
21252800617946c456e78ed010c82d0ec4358368164Mathias Agopian                ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
213b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed                surfaceBitmap.installPixels(SkImageInfo::MakeN32Premul(outBuffer.width, outBuffer.height),
214b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed                                            outBuffer.bits, bpr);
2155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
216fc615a0f643408956fc0dc1b997871e2b27cee7eDerek Sollenberger                SkCanvas surfaceCanvas(surfaceBitmap);
2175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                SkPaint paint;
2195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                paint.setXfermodeMode(SkXfermode::kSrc_Mode);
2202352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                surfaceCanvas.drawBitmap(update.state.icon.bitmap, 0, 0, &paint);
2215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2224d8779fc5b0f371b413a605e10c6efb0aa25036cMichael Wright                if (outBuffer.width > update.state.icon.bitmap.width()) {
2235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    paint.setColor(0); // transparent fill color
2242352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                    surfaceCanvas.drawRectCoords(update.state.icon.bitmap.width(), 0,
22552800617946c456e78ed010c82d0ec4358368164Mathias Agopian                            outBuffer.width, update.state.icon.bitmap.height(), paint);
2265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2274d8779fc5b0f371b413a605e10c6efb0aa25036cMichael Wright                if (outBuffer.height > update.state.icon.bitmap.height()) {
2285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    paint.setColor(0); // transparent fill color
2292352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                    surfaceCanvas.drawRectCoords(0, update.state.icon.bitmap.height(),
23052800617946c456e78ed010c82d0ec4358368164Mathias Agopian                            outBuffer.width, outBuffer.height, paint);
2315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = surface->unlockAndPost();
2345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2353762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d unlocking and posting sprite surface after drawing.", status);
2365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
2375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceDrawn = true;
2385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
2395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
2425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
2435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Set sprite surface properties and make them visible.
2455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    bool haveTransaction = false;
2465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
2475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
2485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        bool wantSurfaceVisibleAndDrawn = update.state.wantSurfaceVisible()
2505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                && update.state.surfaceDrawn;
2515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        bool becomingVisible = wantSurfaceVisibleAndDrawn && !update.state.surfaceVisible;
2525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        bool becomingHidden = !wantSurfaceVisibleAndDrawn && update.state.surfaceVisible;
2535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl != NULL && (becomingVisible || becomingHidden
2545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                || (wantSurfaceVisibleAndDrawn && (update.state.dirty & (DIRTY_ALPHA
2555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        | DIRTY_POSITION | DIRTY_TRANSFORMATION_MATRIX | DIRTY_LAYER
2565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        | DIRTY_VISIBILITY | DIRTY_HOTSPOT))))) {
2575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            status_t status;
2585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (!haveTransaction) {
259439863f3b3e725b5de1cba4940a21900369961c0Mathias Agopian                SurfaceComposerClient::openGlobalTransaction();
2605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                haveTransaction = true;
2615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (wantSurfaceVisibleAndDrawn
2645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    && (becomingVisible || (update.state.dirty & DIRTY_ALPHA))) {
2655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->setAlpha(update.state.alpha);
2665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2673762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d setting sprite surface alpha.", status);
2685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (wantSurfaceVisibleAndDrawn
2725541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    && (becomingVisible || (update.state.dirty & (DIRTY_POSITION
2735541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            | DIRTY_HOTSPOT)))) {
2745541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->setPosition(
2752352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                        update.state.positionX - update.state.icon.hotSpotX,
2762352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                        update.state.positionY - update.state.icon.hotSpotY);
2775541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2783762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d setting sprite surface position.", status);
2795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (wantSurfaceVisibleAndDrawn
2835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    && (becomingVisible
2845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            || (update.state.dirty & DIRTY_TRANSFORMATION_MATRIX))) {
2855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->setMatrix(
2865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.transformationMatrix.dsdx,
2875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.transformationMatrix.dtdx,
2885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.transformationMatrix.dsdy,
2895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.transformationMatrix.dtdy);
2905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2913762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d setting sprite surface transformation matrix.", status);
2925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2955541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            int32_t surfaceLayer = mOverlayLayer + update.state.layer;
2965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (wantSurfaceVisibleAndDrawn
2975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    && (becomingVisible || (update.state.dirty & DIRTY_LAYER))) {
2985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->setLayer(surfaceLayer);
2995541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
3003762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d setting sprite surface layer.", status);
3015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
3025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
3035541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3045541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (becomingVisible) {
3054fd42e5a90e88e34d2e870852a4d26457a712d16Jeff Brown                status = update.state.surfaceControl->show();
3065541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
3073762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d showing sprite surface.", status);
3085541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
3095541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceVisible = true;
3105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
3115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
3125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            } else if (becomingHidden) {
3135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->hide();
3145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
3153762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("Error %d hiding sprite surface.", status);
3165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
3175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceVisible = false;
3185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
3195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
3205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
3215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
3225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (haveTransaction) {
325439863f3b3e725b5de1cba4940a21900369961c0Mathias Agopian        SurfaceComposerClient::closeGlobalTransaction();
3265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // If any surfaces were changed, write back the new surface properties to the sprites.
3295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (surfaceChanged) { // acquire lock
3305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        AutoMutex _l(mLock);
3315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        for (size_t i = 0; i < numSprites; i++) {
3335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            const SpriteUpdate& update = updates.itemAt(i);
3345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (update.surfaceChanged) {
3365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                update.sprite->setSurfaceLocked(update.state.surfaceControl,
3375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.surfaceWidth, update.state.surfaceHeight,
3385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.surfaceDrawn, update.state.surfaceVisible);
3395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
3405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
3415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } // release lock
3425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Clear the sprite update vector outside the lock.  It is very important that
3445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // we do not clear sprite references inside the lock since we could be releasing
3455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // the last remaining reference to the sprite here which would result in the
3465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // sprite being deleted and the lock being reacquired by the sprite destructor
3475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // while already held.
3485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    updates.clear();
3495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::doDisposeSurfaces() {
3525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Collect disposed surfaces.
3535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    Vector<sp<SurfaceControl> > disposedSurfaces;
3545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    { // acquire lock
3552352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        AutoMutex _l(mLock);
3562352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
3572352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        disposedSurfaces = mLocked.disposedSurfaces;
3582352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.disposedSurfaces.clear();
3595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } // release lock
3605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Release the last reference to each surface outside of the lock.
3625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // We don't want the surfaces to be deleted while we are holding our lock.
3635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    disposedSurfaces.clear();
3645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::ensureSurfaceComposerClient() {
3675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mSurfaceComposerClient == NULL) {
3685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mSurfaceComposerClient = new SurfaceComposerClient();
3695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3725541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownsp<SurfaceControl> SpriteController::obtainSurface(int32_t width, int32_t height) {
3735541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    ensureSurfaceComposerClient();
3745541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3755541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    sp<SurfaceControl> surfaceControl = mSurfaceComposerClient->createSurface(
37664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            String8("Sprite"), width, height, PIXEL_FORMAT_RGBA_8888,
37768eccdade2aad22b7eb34a28572c204dcd54f7b9Riley Andrews            ISurfaceComposerClient::eHidden |
37868eccdade2aad22b7eb34a28572c204dcd54f7b9Riley Andrews            ISurfaceComposerClient::eCursorWindow);
37952800617946c456e78ed010c82d0ec4358368164Mathias Agopian    if (surfaceControl == NULL || !surfaceControl->isValid()) {
3803762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Error creating sprite surface.");
3815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        return NULL;
3825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    return surfaceControl;
3845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown// --- SpriteController::SpriteImpl ---
3885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::SpriteImpl::SpriteImpl(const sp<SpriteController> controller) :
3902352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mController(controller) {
3915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::SpriteImpl::~SpriteImpl() {
3945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _m(mController->mLock);
3955541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Let the controller take care of deleting the last reference to sprite
3975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // surfaces so that we do not block the caller on an IPC here.
3982352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.surfaceControl != NULL) {
3992352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mController->disposeSurfaceLocked(mLocked.state.surfaceControl);
4002352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.surfaceControl.clear();
4015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4035541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4042352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownvoid SpriteController::SpriteImpl::setIcon(const SpriteIcon& icon) {
4055541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4065541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4072352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    uint32_t dirty;
4082352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (icon.isValid()) {
4094a9c3891d4f890109e02bc83fecf9bcdf56a9395Mike Reed        icon.bitmap.copyTo(&mLocked.state.icon.bitmap, kN32_SkColorType);
4102352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
4112352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        if (!mLocked.state.icon.isValid()
4122352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                || mLocked.state.icon.hotSpotX != icon.hotSpotX
4132352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown                || mLocked.state.icon.hotSpotY != icon.hotSpotY) {
4142352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            mLocked.state.icon.hotSpotX = icon.hotSpotX;
4152352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            mLocked.state.icon.hotSpotY = icon.hotSpotY;
4162352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            dirty = DIRTY_BITMAP | DIRTY_HOTSPOT;
4172352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        } else {
4182352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown            dirty = DIRTY_BITMAP;
4192352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        }
4202352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    } else if (mLocked.state.icon.isValid()) {
4212352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.icon.bitmap.reset();
4222352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        dirty = DIRTY_BITMAP | DIRTY_HOTSPOT;
4235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } else {
4242352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        return; // setting to invalid icon and already invalid so nothing to do
4255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    invalidateLocked(dirty);
4285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setVisible(bool visible) {
4315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4332352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.visible != visible) {
4342352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.visible = visible;
4355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_VISIBILITY);
4365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setPosition(float x, float y) {
4405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4422352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.positionX != x || mLocked.state.positionY != y) {
4432352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.positionX = x;
4442352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.positionY = y;
4455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_POSITION);
4465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setLayer(int32_t layer) {
4505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4522352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.layer != layer) {
4532352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.layer = layer;
4545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_LAYER);
4555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setAlpha(float alpha) {
4595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4612352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.alpha != alpha) {
4622352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.alpha = alpha;
4635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_ALPHA);
4645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setTransformationMatrix(
4685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        const SpriteTransformationMatrix& matrix) {
4695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4712352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (mLocked.state.transformationMatrix != matrix) {
4722352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown        mLocked.state.transformationMatrix = matrix;
4735541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_TRANSFORMATION_MATRIX);
4745541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4755541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4765541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4772352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownvoid SpriteController::SpriteImpl::invalidateLocked(uint32_t dirty) {
4782352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    bool wasDirty = mLocked.state.dirty;
4792352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    mLocked.state.dirty |= dirty;
4805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4812352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown    if (!wasDirty) {
4825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mController->invalidateSpriteLocked(this);
4835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown} // namespace android
487