SpriteController.cpp revision 5541de9ea3513a12d1ac2ad07e7e04a3aa7741a0
15541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown/*
25541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * Copyright (C) 2011 The Android Open Source Project
35541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown *
45541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
55541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * you may not use this file except in compliance with the License.
65541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * You may obtain a copy of the License at
75541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown *
85541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
95541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown *
105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * Unless required by applicable law or agreed to in writing, software
115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * See the License for the specific language governing permissions and
145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown * limitations under the License.
155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown */
165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#define LOG_TAG "Sprites"
185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown//#define LOG_NDEBUG 0
205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include "SpriteController.h"
225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <cutils/log.h>
245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <utils/String8.h>
255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkBitmap.h>
275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkCanvas.h>
285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkColor.h>
295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkPaint.h>
305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown#include <SkXfermode.h>
315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownnamespace android {
335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown// --- SpriteController ---
355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::SpriteController(const sp<Looper>& looper, int32_t overlayLayer) :
375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mLooper(looper), mOverlayLayer(overlayLayer) {
385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    mHandler = new WeakMessageHandler(this);
395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::~SpriteController() {
425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    mLooper->removeMessages(mHandler);
435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mSurfaceComposerClient != NULL) {
455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mSurfaceComposerClient->dispose();
465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mSurfaceComposerClient.clear();
475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownsp<Sprite> SpriteController::createSprite() {
515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    return new SpriteImpl(this);
525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::invalidateSpriteLocked(const sp<SpriteImpl>& sprite) {
555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    bool wasEmpty = mInvalidatedSprites.isEmpty();
565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    mInvalidatedSprites.push(sprite);
575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (wasEmpty) {
585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES));
595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl) {
635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    bool wasEmpty = mDisposedSurfaces.isEmpty();
645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    mDisposedSurfaces.push(surfaceControl);
655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (wasEmpty) {
665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mLooper->sendMessage(mHandler, Message(MSG_DISPOSE_SURFACES));
675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::handleMessage(const Message& message) {
715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    switch (message.what) {
725541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    case MSG_UPDATE_SPRITES:
735541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        doUpdateSprites();
745541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        break;
755541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    case MSG_DISPOSE_SURFACES:
765541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        doDisposeSurfaces();
775541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        break;
785541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::doUpdateSprites() {
825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Collect information about sprite updates.
835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Each sprite update record includes a reference to its associated sprite so we can
845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // be certain the sprites will not be deleted while this function runs.  Sprites
855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // may invalidate themselves again during this time but we will handle those changes
865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // in the next iteration.
875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    Vector<SpriteUpdate> updates;
885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    size_t numSprites;
895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    { // acquire lock
905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        AutoMutex _l(mLock);
915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        numSprites = mInvalidatedSprites.size();
935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        for (size_t i = 0; i < numSprites; i++) {
945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            const sp<SpriteImpl>& sprite = mInvalidatedSprites.itemAt(i);
955541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            updates.push(SpriteUpdate(sprite, sprite->getStateLocked()));
975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            sprite->resetDirtyLocked();
985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
995541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mInvalidatedSprites.clear();
1005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } // release lock
1015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Create missing surfaces.
1035541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    bool surfaceChanged = false;
1045541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
1055541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
1065541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1075541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl == NULL && update.state.wantSurfaceVisible()) {
1085541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceWidth = update.state.bitmap.width();
1095541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceHeight = update.state.bitmap.height();
1105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceDrawn = false;
1115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceVisible = false;
1125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceControl = obtainSurface(
1135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceWidth, update.state.surfaceHeight);
1145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (update.state.surfaceControl != NULL) {
1155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                update.surfaceChanged = surfaceChanged = true;
1165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
1175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Resize sprites if needed, inside a global transaction.
1215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    bool haveGlobalTransaction = false;
1225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
1235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
1245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl != NULL && update.state.wantSurfaceVisible()) {
1265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            int32_t desiredWidth = update.state.bitmap.width();
1275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            int32_t desiredHeight = update.state.bitmap.height();
1285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (update.state.surfaceWidth < desiredWidth
1295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    || update.state.surfaceHeight < desiredHeight) {
1305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (!haveGlobalTransaction) {
1315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    SurfaceComposerClient::openGlobalTransaction();
1325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    haveGlobalTransaction = true;
1335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
1345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status_t status = update.state.surfaceControl->setSize(desiredWidth, desiredHeight);
1365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
1375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    LOGE("Error %d resizing sprite surface from %dx%d to %dx%d",
1385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            status, update.state.surfaceWidth, update.state.surfaceHeight,
1395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            desiredWidth, desiredHeight);
1405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
1415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceWidth = desiredWidth;
1425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceHeight = desiredHeight;
1435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceDrawn = false;
1445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
1455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    if (update.state.surfaceVisible) {
1475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        status = update.state.surfaceControl->hide();
1485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        if (status) {
1495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            LOGE("Error %d hiding sprite surface after resize.", status);
1505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        } else {
1515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            update.state.surfaceVisible = false;
1525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        }
1535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    }
1545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
1555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
1565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (haveGlobalTransaction) {
1595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SurfaceComposerClient::closeGlobalTransaction();
1605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
1615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Redraw sprites if needed.
1635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
1645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
1655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if ((update.state.dirty & DIRTY_BITMAP) && update.state.surfaceDrawn) {
1675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.state.surfaceDrawn = false;
1685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            update.surfaceChanged = surfaceChanged = true;
1695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
1705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl != NULL && !update.state.surfaceDrawn
1725541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                && update.state.wantSurfaceVisible()) {
1735541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            sp<Surface> surface = update.state.surfaceControl->getSurface();
1745541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            Surface::SurfaceInfo surfaceInfo;
1755541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            status_t status = surface->lock(&surfaceInfo);
1765541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (status) {
1775541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                LOGE("Error %d locking sprite surface before drawing.", status);
1785541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            } else {
1795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                SkBitmap surfaceBitmap;
1805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                ssize_t bpr = surfaceInfo.s * bytesPerPixel(surfaceInfo.format);
1815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                surfaceBitmap.setConfig(SkBitmap::kARGB_8888_Config,
1825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        surfaceInfo.w, surfaceInfo.h, bpr);
1835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                surfaceBitmap.setPixels(surfaceInfo.bits);
1845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                SkCanvas surfaceCanvas;
1865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                surfaceCanvas.setBitmapDevice(surfaceBitmap);
1875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                SkPaint paint;
1895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                paint.setXfermodeMode(SkXfermode::kSrc_Mode);
1905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                surfaceCanvas.drawBitmap(update.state.bitmap, 0, 0, &paint);
1915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
1925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (surfaceInfo.w > uint32_t(update.state.bitmap.width())) {
1935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    paint.setColor(0); // transparent fill color
1945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    surfaceCanvas.drawRectCoords(update.state.bitmap.width(), 0,
1955541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            surfaceInfo.w, update.state.bitmap.height(), paint);
1965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
1975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (surfaceInfo.h > uint32_t(update.state.bitmap.height())) {
1985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    paint.setColor(0); // transparent fill color
1995541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    surfaceCanvas.drawRectCoords(0, update.state.bitmap.height(),
2005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            surfaceInfo.w, surfaceInfo.h, paint);
2015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2035541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = surface->unlockAndPost();
2045541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2055541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    LOGE("Error %d unlocking and posting sprite surface after drawing.", status);
2065541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
2075541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceDrawn = true;
2085541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
2095541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
2125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
2135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Set sprite surface properties and make them visible.
2155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    bool haveTransaction = false;
2165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    for (size_t i = 0; i < numSprites; i++) {
2175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        SpriteUpdate& update = updates.editItemAt(i);
2185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        bool wantSurfaceVisibleAndDrawn = update.state.wantSurfaceVisible()
2205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                && update.state.surfaceDrawn;
2215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        bool becomingVisible = wantSurfaceVisibleAndDrawn && !update.state.surfaceVisible;
2225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        bool becomingHidden = !wantSurfaceVisibleAndDrawn && update.state.surfaceVisible;
2235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (update.state.surfaceControl != NULL && (becomingVisible || becomingHidden
2245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                || (wantSurfaceVisibleAndDrawn && (update.state.dirty & (DIRTY_ALPHA
2255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        | DIRTY_POSITION | DIRTY_TRANSFORMATION_MATRIX | DIRTY_LAYER
2265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        | DIRTY_VISIBILITY | DIRTY_HOTSPOT))))) {
2275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            status_t status;
2285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (!haveTransaction) {
2295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = mSurfaceComposerClient->openTransaction();
2305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    LOGE("Error %d opening transation to update sprite surface.", status);
2325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    break;
2335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                haveTransaction = true;
2355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (wantSurfaceVisibleAndDrawn
2385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    && (becomingVisible || (update.state.dirty & DIRTY_ALPHA))) {
2395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->setAlpha(update.state.alpha);
2405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    LOGE("Error %d setting sprite surface alpha.", status);
2425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (wantSurfaceVisibleAndDrawn
2465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    && (becomingVisible || (update.state.dirty & (DIRTY_POSITION
2475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            | DIRTY_HOTSPOT)))) {
2485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->setPosition(
2495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.positionX - update.state.hotSpotX,
2505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.positionY - update.state.hotSpotY);
2515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    LOGE("Error %d setting sprite surface position.", status);
2535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (wantSurfaceVisibleAndDrawn
2575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    && (becomingVisible
2585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                            || (update.state.dirty & DIRTY_TRANSFORMATION_MATRIX))) {
2595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->setMatrix(
2605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.transformationMatrix.dsdx,
2615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.transformationMatrix.dtdx,
2625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.transformationMatrix.dsdy,
2635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.transformationMatrix.dtdy);
2645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    LOGE("Error %d setting sprite surface transformation matrix.", status);
2665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            int32_t surfaceLayer = mOverlayLayer + update.state.layer;
2705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (wantSurfaceVisibleAndDrawn
2715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    && (becomingVisible || (update.state.dirty & DIRTY_LAYER))) {
2725541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->setLayer(surfaceLayer);
2735541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2745541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    LOGE("Error %d setting sprite surface layer.", status);
2755541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2765541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2775541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2785541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (becomingVisible) {
2795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->show(surfaceLayer);
2805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    LOGE("Error %d showing sprite surface.", status);
2825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
2835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceVisible = true;
2845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
2855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            } else if (becomingHidden) {
2875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                status = update.state.surfaceControl->hide();
2885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                if (status) {
2895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    LOGE("Error %d hiding sprite surface.", status);
2905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                } else {
2915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.state.surfaceVisible = false;
2925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                    update.surfaceChanged = surfaceChanged = true;
2935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                }
2945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
2955541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
2965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
2975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
2985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (haveTransaction) {
2995541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        status_t status = mSurfaceComposerClient->closeTransaction();
3005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (status) {
3015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            LOGE("Error %d closing transaction to update sprite surface.", status);
3025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
3035541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3045541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3055541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // If any surfaces were changed, write back the new surface properties to the sprites.
3065541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (surfaceChanged) { // acquire lock
3075541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        AutoMutex _l(mLock);
3085541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3095541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        for (size_t i = 0; i < numSprites; i++) {
3105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            const SpriteUpdate& update = updates.itemAt(i);
3115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            if (update.surfaceChanged) {
3135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                update.sprite->setSurfaceLocked(update.state.surfaceControl,
3145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.surfaceWidth, update.state.surfaceHeight,
3155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown                        update.state.surfaceDrawn, update.state.surfaceVisible);
3165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            }
3175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
3185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } // release lock
3195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Clear the sprite update vector outside the lock.  It is very important that
3215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // we do not clear sprite references inside the lock since we could be releasing
3225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // the last remaining reference to the sprite here which would result in the
3235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // sprite being deleted and the lock being reacquired by the sprite destructor
3245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // while already held.
3255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    updates.clear();
3265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::doDisposeSurfaces() {
3295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Collect disposed surfaces.
3305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    Vector<sp<SurfaceControl> > disposedSurfaces;
3315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    { // acquire lock
3325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        disposedSurfaces = mDisposedSurfaces;
3335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mDisposedSurfaces.clear();
3345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } // release lock
3355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Release the last reference to each surface outside of the lock.
3375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // We don't want the surfaces to be deleted while we are holding our lock.
3385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    disposedSurfaces.clear();
3395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::ensureSurfaceComposerClient() {
3425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mSurfaceComposerClient == NULL) {
3435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mSurfaceComposerClient = new SurfaceComposerClient();
3445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownsp<SurfaceControl> SpriteController::obtainSurface(int32_t width, int32_t height) {
3485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    ensureSurfaceComposerClient();
3495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    sp<SurfaceControl> surfaceControl = mSurfaceComposerClient->createSurface(
3515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            getpid(), String8("Sprite"), 0, width, height, PIXEL_FORMAT_RGBA_8888);
3525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (surfaceControl == NULL) {
3535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        LOGE("Error creating sprite surface.");
3545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        return NULL;
3555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    return surfaceControl;
3575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown// --- SpriteController::SpriteImpl ---
3615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::SpriteImpl::SpriteImpl(const sp<SpriteController> controller) :
3635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mController(controller), mTransactionNestingCount(0) {
3645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff BrownSpriteController::SpriteImpl::~SpriteImpl() {
3675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _m(mController->mLock);
3685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // Let the controller take care of deleting the last reference to sprite
3705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    // surfaces so that we do not block the caller on an IPC here.
3715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mState.surfaceControl != NULL) {
3725541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mController->disposeSurfaceLocked(mState.surfaceControl);
3735541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mState.surfaceControl.clear();
3745541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3755541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3765541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3775541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setBitmap(const SkBitmap* bitmap,
3785541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        float hotSpotX, float hotSpotY) {
3795541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
3805541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3815541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (bitmap) {
3825541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        bitmap->copyTo(&mState.bitmap, SkBitmap::kARGB_8888_Config);
3835541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    } else {
3845541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mState.bitmap.reset();
3855541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3865541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3875541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    uint32_t dirty = DIRTY_BITMAP;
3885541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mState.hotSpotX != hotSpotX || mState.hotSpotY != hotSpotY) {
3895541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mState.hotSpotX = hotSpotX;
3905541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mState.hotSpotY = hotSpotY;
3915541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        dirty |= DIRTY_HOTSPOT;
3925541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
3935541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3945541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    invalidateLocked(dirty);
3955541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
3965541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
3975541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setVisible(bool visible) {
3985541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
3995541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4005541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mState.visible != visible) {
4015541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mState.visible = visible;
4025541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_VISIBILITY);
4035541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4045541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4055541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4065541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setPosition(float x, float y) {
4075541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4085541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4095541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mState.positionX != x || mState.positionY != y) {
4105541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mState.positionX = x;
4115541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mState.positionY = y;
4125541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_POSITION);
4135541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4145541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4155541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4165541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setLayer(int32_t layer) {
4175541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4185541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4195541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mState.layer != layer) {
4205541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mState.layer = layer;
4215541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_LAYER);
4225541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4235541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4245541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4255541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setAlpha(float alpha) {
4265541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4275541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4285541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mState.alpha != alpha) {
4295541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mState.alpha = alpha;
4305541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_ALPHA);
4315541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4325541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4335541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4345541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::setTransformationMatrix(
4355541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        const SpriteTransformationMatrix& matrix) {
4365541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4375541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4385541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mState.transformationMatrix != matrix) {
4395541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mState.transformationMatrix = matrix;
4405541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        invalidateLocked(DIRTY_TRANSFORMATION_MATRIX);
4415541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4425541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4435541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4445541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::openTransaction() {
4455541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4465541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4475541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    mTransactionNestingCount += 1;
4485541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4495541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4505541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::closeTransaction() {
4515541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    AutoMutex _l(mController->mLock);
4525541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4535541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    LOG_ALWAYS_FATAL_IF(mTransactionNestingCount == 0,
4545541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            "Sprite closeTransaction() called but there is no open sprite transaction");
4555541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4565541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    mTransactionNestingCount -= 1;
4575541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mTransactionNestingCount == 0 && mState.dirty) {
4585541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mController->invalidateSpriteLocked(this);
4595541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4605541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4615541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4625541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brownvoid SpriteController::SpriteImpl::invalidateLocked(uint32_t dirty) {
4635541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    if (mTransactionNestingCount > 0) {
4645541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        bool wasDirty = mState.dirty;
4655541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        mState.dirty |= dirty;
4665541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        if (!wasDirty) {
4675541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown            mController->invalidateSpriteLocked(this);
4685541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown        }
4695541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown    }
4705541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown}
4715541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown
4725541de9ea3513a12d1ac2ad07e7e04a3aa7741a0Jeff Brown} // namespace android
473