Layer.cpp revision edbf3b6af777b721cd2a1ef461947e51e88241e1
1edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
2edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
4edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * you may not use this file except in compliance with the License.
6edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * You may obtain a copy of the License at
7edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
8edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
10edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * See the License for the specific language governing permissions and
14edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * limitations under the License.
15edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
16edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
17edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#define LOG_TAG "SurfaceFlinger"
18edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
19edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <stdlib.h>
20edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <stdint.h>
21edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <sys/types.h>
22edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
23edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <cutils/properties.h>
24edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
25edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/Errors.h>
26edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/Log.h>
27edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/StopWatch.h>
28edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
29edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <ui/PixelFormat.h>
30edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <ui/EGLDisplaySurface.h>
31edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
32edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "clz.h"
33edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "Layer.h"
34edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "LayerBitmap.h"
35edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "SurfaceFlinger.h"
36edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "VRamHeap.h"
37edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "DisplayHardware/DisplayHardware.h"
38edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
39edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
40edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#define DEBUG_RESIZE    0
41edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
42edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
43edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectnamespace android {
44edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
45edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ---------------------------------------------------------------------------
46edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
47edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectconst uint32_t Layer::typeInfo = LayerBaseClient::typeInfo | 4;
48edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectconst char* const Layer::typeID = "Layer";
49edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
50edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ---------------------------------------------------------------------------
51edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
52edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectLayer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i)
53edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    :   LayerBaseClient(flinger, display, c, i),
54edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mSecure(false),
55edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mFrontBufferIndex(1),
56edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mNeedsBlending(true),
57edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mResizeTransactionDone(false),
58edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mTextureName(-1U), mTextureWidth(0), mTextureHeight(0)
59edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
60edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // no OpenGL operation is possible here, since we might not be
61edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // in the OpenGL thread.
62edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
63edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
64edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectLayer::~Layer()
65edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
66edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    client->free(clientIndex());
67edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // this should always be called from the OpenGL thread
68edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (mTextureName != -1U) {
69edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        //glDeleteTextures(1, &mTextureName);
70edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        deletedTextures.add(mTextureName);
71edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
72edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
73edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
74edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid Layer::initStates(uint32_t w, uint32_t h, uint32_t flags)
75edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
76edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    LayerBase::initStates(w,h,flags);
77edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
78edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (flags & ISurfaceComposer::eDestroyBackbuffer)
79edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        lcblk->flags |= eNoCopyBack;
80edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
81edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
82edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectsp<LayerBaseClient::Surface> Layer::getSurface() const
83edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
84edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return mSurface;
85edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
86edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
87edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t Layer::setBuffers( Client* client,
88edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                            uint32_t w, uint32_t h,
89edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                            PixelFormat format, uint32_t flags)
90edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
91edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    PixelFormatInfo info;
92edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    status_t err = getPixelFormatInfo(format, &info);
93edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (err) return err;
94edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
95edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // TODO: if eHardware is explicitly requested, we should fail
96edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // on systems where we can't allocate memory that can be used with
97edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // DMA engines for instance.
98edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
99edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // FIXME: we always ask for hardware for now (this should come from copybit)
100edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    flags |= ISurfaceComposer::eHardware;
101edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
102edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const uint32_t memory_flags = flags &
103edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            (ISurfaceComposer::eGPU |
104edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project             ISurfaceComposer::eHardware |
105edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project             ISurfaceComposer::eSecure);
106edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
107edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // pixel-alignment. the final alignment may be bigger because
108edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // we always force a 4-byte aligned bpr.
109edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    uint32_t alignment = 1;
110edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
111edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (flags & ISurfaceComposer::eGPU) {
112edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // FIXME: this value should come from the h/w
113edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        alignment = 8;
114edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // FIXME: this is msm7201A specific, as its GPU only supports
115edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // BGRA_8888.
116edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (format == PIXEL_FORMAT_RGBA_8888) {
117edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            format = PIXEL_FORMAT_BGRA_8888;
118edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
119edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
120edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
121edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
122edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
123edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    sp<MemoryDealer> allocators[2];
124edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    for (int i=0 ; i<2 ; i++) {
125edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        allocators[i] = client->createAllocator(memory_flags);
126edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (allocators[i] == 0)
127edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            return NO_MEMORY;
128edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mBuffers[i].init(allocators[i]);
129edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        int err = mBuffers[i].setBits(w, h, alignment, format, LayerBitmap::SECURE_BITS);
130edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (err != NO_ERROR)
131edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            return err;
132edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mBuffers[i].clear(); // clear the bits for security
133edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mBuffers[i].getInfo(lcblk->surface + i);
134edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
135edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
136edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mSurface = new Surface(clientIndex(),
137edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            allocators[0]->getMemoryHeap(),
138edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            allocators[1]->getMemoryHeap(),
139edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            mIdentity);
140edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
141edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return NO_ERROR;
142edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
143edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
144edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid Layer::reloadTexture(const Region& dirty)
145edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
146edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (UNLIKELY(mTextureName == -1U)) {
147edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // create the texture name the first time
148edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // can't do that in the ctor, because it runs in another thread.
149edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mTextureName = createTexture();
150edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
151edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const GGLSurface& t(frontBuffer().surface());
152edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    loadTexture(dirty, mTextureName, t, mTextureWidth, mTextureHeight);
153edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
154edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
155edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
156edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid Layer::onDraw(const Region& clip) const
157edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
158edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (UNLIKELY(mTextureName == -1LU)) {
159edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        //LOGW("Layer %p doesn't have a texture", this);
160edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // the texture has not been created yet, this Layer has
161edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // in fact never been drawn into. this happens frequently with
162edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // SurfaceView.
163edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        clearWithOpenGL(clip);
164edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        return;
165edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
166edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
167edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const DisplayHardware& hw(graphicPlane(0).displayHardware());
168edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const LayerBitmap& front(frontBuffer());
169edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const GGLSurface& t(front.surface());
170edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
171edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    status_t err = NO_ERROR;
172edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const int can_use_copybit = canUseCopybit();
173edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (can_use_copybit)  {
174edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // StopWatch watch("copybit");
175edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        const State& s(drawingState());
176edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
177edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        copybit_image_t dst;
178edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        hw.getDisplaySurface(&dst);
179edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        const copybit_rect_t& drect
180edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds);
181edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
182edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        copybit_image_t src;
183edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        front.getBitmapSurface(&src);
184edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        copybit_rect_t srect = { 0, 0, t.width, t.height };
185edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
186edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        copybit_device_t* copybit = mFlinger->getBlitEngine();
187edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, getOrientation());
188edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
189edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        copybit->set_parameter(copybit, COPYBIT_DITHER,
190edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                s.flags & ISurfaceComposer::eLayerDither ?
191edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                        COPYBIT_ENABLE : COPYBIT_DISABLE);
192edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
193edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        region_iterator it(clip);
194edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
195edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
196edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
197edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (!can_use_copybit || err) {
198edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        drawWithOpenGL(clip, mTextureName, t);
199edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
200edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
201edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
202edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t Layer::reallocateBuffer(int32_t index, uint32_t w, uint32_t h)
203edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
204edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    LOGD_IF(DEBUG_RESIZE,
205edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                "reallocateBuffer (layer=%p), "
206edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                "requested (%dx%d), "
207edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                "index=%d, (%dx%d), (%dx%d)",
208edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                this,
209edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                int(w), int(h),
210edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                int(index),
211edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                int(mBuffers[0].width()), int(mBuffers[0].height()),
212edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                int(mBuffers[1].width()), int(mBuffers[1].height()));
213edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
214edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    status_t err = mBuffers[index].resize(w, h);
215edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (err == NO_ERROR) {
216edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mBuffers[index].getInfo(lcblk->surface + index);
217edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    } else {
218edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s",
219edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            index, w, h, err, strerror(err));
220edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // XXX: what to do, what to do? We could try to free some
221edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // hidden surfaces, instead of killing this one?
222edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
223edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return err;
224edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
225edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
226edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectuint32_t Layer::doTransaction(uint32_t flags)
227edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
228edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const Layer::State& front(drawingState());
229edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const Layer::State& temp(currentState());
230edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
231edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // the test front.{w|h} != temp.{w|h} is not enough because it is possible
232edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // that the size changed back to its previous value before the buffer
233edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // was resized (in the eLocked case below), in which case, we still
234edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // need to execute the code below so the clients have a chance to be
235edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // release. resze() deals with the fact that the size can be the same.
236edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
237edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    /*
238edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project     *  Various states we could be in...
239edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
240edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project         resize = state & eResizeRequested;
241edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project         if (backbufferChanged) {
242edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project             if (resize == 0) {
243edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                 // ERROR, the resized buffer doesn't have its resize flag set
244edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project             } else if (resize == mask) {
245edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                 // ERROR one of the buffer has already been resized
246edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project             } else if (resize == mask ^ eResizeRequested) {
247edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                 // ERROR, the resized buffer doesn't have its resize flag set
248edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project             } else if (resize == eResizeRequested) {
249edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                 // OK, Normal case, proceed with resize
250edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project             }
251edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project         } else {
252edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project             if (resize == 0) {
253edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                 // OK, nothing special, do nothing
254edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project             } else if (resize == mask) {
255edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                 // restarted transaction, do nothing
256edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project             } else if (resize == mask ^ eResizeRequested) {
257edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                 // restarted transaction, do nothing
258edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project             } else if (resize == eResizeRequested) {
259edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                 // OK, size reset to previous value, proceed with resize
260edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project             }
261edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project         }
262edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project     */
263edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
264edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // Index of the back buffer
265edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const bool backbufferChanged = (front.w != temp.w) || (front.h != temp.h);
266edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const uint32_t state = lcblk->swapState;
267edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const int32_t clientBackBufferIndex = layer_cblk_t::backBuffer(state);
268edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0;
269edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    uint32_t resizeFlags = state & eResizeRequested;
270edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
271edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (UNLIKELY(backbufferChanged && (resizeFlags != eResizeRequested))) {
272edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        LOGE(   "backbuffer size changed, but both resize flags are not set! "
273edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                "(layer=%p), state=%08x, requested (%dx%d), drawing (%d,%d), "
274edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                "index=%d, (%dx%d), (%dx%d)",
275edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                this,  state,
276edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                int(temp.w), int(temp.h),
277edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                int(drawingState().w), int(drawingState().h),
278edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                int(clientBackBufferIndex),
279edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                int(mBuffers[0].width()), int(mBuffers[0].height()),
280edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                int(mBuffers[1].width()), int(mBuffers[1].height()));
281edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // if we get there we're pretty screwed. the only reasonable
282edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // thing to do is to pretend we should do the resize since
283edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // backbufferChanged is set (this also will give a chance to
284edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // client to get unblocked)
285edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        resizeFlags = eResizeRequested;
286edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
287edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
288edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (resizeFlags == eResizeRequested)  {
289edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // NOTE: asserting that clientBackBufferIndex!=mFrontBufferIndex
290edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // here, would be wrong and misleading because by this point
291edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // mFrontBufferIndex has not been updated yet.
292edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
293edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        LOGD_IF(DEBUG_RESIZE,
294edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    "resize (layer=%p), state=%08x, "
295edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    "requested (%dx%d), "
296edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    "drawing (%d,%d), "
297edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    "index=%d, (%dx%d), (%dx%d)",
298edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    this,  state,
299edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    int(temp.w), int(temp.h),
300edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    int(drawingState().w), int(drawingState().h),
301edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    int(clientBackBufferIndex),
302edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    int(mBuffers[0].width()), int(mBuffers[0].height()),
303edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    int(mBuffers[1].width()), int(mBuffers[1].height()));
304edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
305edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (state & eLocked) {
306edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // if the buffer is locked, we can't resize anything because
307edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // - the backbuffer is currently in use by the user
308edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // - the front buffer is being shown
309edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // We just act as if the transaction didn't happen and we
310edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // reschedule it later...
311edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            flags |= eRestartTransaction;
312edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        } else {
313edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // This buffer needs to be resized
314edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            status_t err =
315edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                resize(clientBackBufferIndex, temp.w, temp.h, "transaction");
316edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            if (err == NO_ERROR) {
317edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0;
318edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                android_atomic_and(~mask, &(lcblk->swapState));
319edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                // since a buffer became available, we can let the client go...
320edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                mFlinger->scheduleBroadcast(client);
321edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                mResizeTransactionDone = true;
322edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
323edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                // we're being resized and there is a freeze display request,
324edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                // acquire a freeze lock, so that the screen stays put
325edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                // until we've redrawn at the new size; this is to avoid
326edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                // glitches upon orientation changes.
327edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                if (mFlinger->hasFreezeRequest()) {
328edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    // if the surface is hidden, don't try to acquire the
329edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    // freeze lock, since hidden surfaces may never redraw
330edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
331edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                        mFreezeLock = mFlinger->getFreezeLock();
332edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    }
333edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                }
334edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            }
335edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
336edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
337edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
338edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (temp.sequence != front.sequence) {
339edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) {
340edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // this surface is now hidden, so it shouldn't hold a freeze lock
341edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // (it may never redraw, which is fine if it is hidden)
342edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            mFreezeLock.clear();
343edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
344edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
345edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
346edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return LayerBase::doTransaction(flags);
347edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
348edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
349edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t Layer::resize(
350edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        int32_t clientBackBufferIndex,
351edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        uint32_t width, uint32_t height,
352edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        const char* what)
353edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
354edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    /*
355edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project     * handle resize (backbuffer and frontbuffer reallocation)
356edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project     */
357edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
358edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const LayerBitmap& clientBackBuffer(mBuffers[clientBackBufferIndex]);
359edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
360edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // if the new (transaction) size is != from the the backbuffer
361edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // then we need to reallocate the backbuffer
362edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    bool backbufferChanged = (clientBackBuffer.width()  != width) ||
363edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                             (clientBackBuffer.height() != height);
364edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
365edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    LOGD_IF(!backbufferChanged,
366edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            "(%s) eResizeRequested (layer=%p), but size not changed: "
367edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            "requested (%dx%d), drawing (%d,%d), current (%d,%d),"
368edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            "state=%08lx, index=%d, (%dx%d), (%dx%d)",
369edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            what, this,
370edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            int(width), int(height),
371edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            int(drawingState().w), int(drawingState().h),
372edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            int(currentState().w), int(currentState().h),
373edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            long(lcblk->swapState),
374edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            int(clientBackBufferIndex),
375edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            int(mBuffers[0].width()), int(mBuffers[0].height()),
376edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            int(mBuffers[1].width()), int(mBuffers[1].height()));
377edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
378edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // this can happen when changing the size back and forth quickly
379edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    status_t err = NO_ERROR;
380edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (backbufferChanged) {
381edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        err = reallocateBuffer(clientBackBufferIndex, width, height);
382edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
383edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (UNLIKELY(err != NO_ERROR)) {
384edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // couldn't reallocate the surface
385edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        android_atomic_write(eInvalidSurface, &lcblk->swapState);
386edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        memset(lcblk->surface+clientBackBufferIndex, 0, sizeof(surface_info_t));
387edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
388edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return err;
389edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
390edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
391edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid Layer::setSizeChanged(uint32_t w, uint32_t h)
392edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
393edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    LOGD_IF(DEBUG_RESIZE,
394edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            "setSizeChanged w=%d, h=%d (old: w=%d, h=%d)",
395edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            w, h, mCurrentState.w, mCurrentState.h);
396edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    android_atomic_or(eResizeRequested, &(lcblk->swapState));
397edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
398edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
399edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ----------------------------------------------------------------------------
400edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// pageflip handling...
401edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ----------------------------------------------------------------------------
402edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
403edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid Layer::lockPageFlip(bool& recomputeVisibleRegions)
404edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
405edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    uint32_t state = android_atomic_or(eBusy, &(lcblk->swapState));
406edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // preemptively block the client, because he might set
407edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // eFlipRequested at any time and want to use this buffer
408edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // for the next frame. This will be unset below if it
409edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // turns out we didn't need it.
410edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
411edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    uint32_t mask = eInvalidSurface | eFlipRequested | eResizeRequested;
412edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (!(state & mask))
413edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        return;
414edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
415edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (UNLIKELY(state & eInvalidSurface)) {
416edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // if eInvalidSurface is set, this means the surface
417edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // became invalid during a transaction (NO_MEMORY for instance)
418edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mFlinger->scheduleBroadcast(client);
419edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        return;
420edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
421edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
422edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (UNLIKELY(state & eFlipRequested)) {
423edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        uint32_t oldState;
424edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mPostedDirtyRegion = post(&oldState, recomputeVisibleRegions);
425edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (oldState & eNextFlipPending) {
426edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // Process another round (we know at least a buffer
427edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // is ready for that client).
428edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            mFlinger->signalEvent();
429edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
430edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
431edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
432edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
433edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectRegion Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions)
434edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
435edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // atomically swap buffers and (re)set eFlipRequested
436edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    int32_t oldValue, newValue;
437edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    layer_cblk_t * const lcblk = this->lcblk;
438edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    do {
439edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        oldValue = lcblk->swapState;
440edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // get the current value
441edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
442edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        LOG_ASSERT(oldValue&eFlipRequested,
443edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            "eFlipRequested not set, yet we're flipping! (state=0x%08lx)",
444edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            long(oldValue));
445edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
446edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        newValue = (oldValue ^ eIndex);
447edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // swap buffers
448edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
449edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        newValue &= ~(eFlipRequested | eNextFlipPending);
450edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // clear eFlipRequested and eNextFlipPending
451edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
452edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (oldValue & eNextFlipPending)
453edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            newValue |= eFlipRequested;
454edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // if eNextFlipPending is set (second buffer already has something
455edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // in it) we need to reset eFlipRequested because the client
456edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // might never do it
457edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
458edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
459edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    *previousSate = oldValue;
460edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
461edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const int32_t index = (newValue & eIndex) ^ 1;
462edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mFrontBufferIndex = index;
463edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
464edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // ... post the new front-buffer
465edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    Region dirty(lcblk->region + index);
466edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    dirty.andSelf(frontBuffer().bounds());
467edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
468edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    //LOGI("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n",
469edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    //    oldValue, newValue, mFrontBufferIndex);
470edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    //dirty.dump("dirty");
471edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
472edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (UNLIKELY(oldValue & eResizeRequested)) {
473edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
474edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        LOGD_IF(DEBUG_RESIZE,
475edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                     "post (layer=%p), state=%08x, "
476edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                     "index=%d, (%dx%d), (%dx%d)",
477edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                     this,  newValue,
478edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                     int(1-index),
479edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                     int(mBuffers[0].width()), int(mBuffers[0].height()),
480edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                     int(mBuffers[1].width()), int(mBuffers[1].height()));
481edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
482edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // here, we just posted the surface and we have resolved
483edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // the front/back buffer indices. The client is blocked, so
484edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // it cannot start using the new backbuffer.
485edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
486edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // If the backbuffer was resized in THIS round, we actually cannot
487edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // resize the frontbuffer because it has *just* been drawn (and we
488edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // would have nothing to draw). In this case we just skip the resize
489edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // it'll happen after the next page flip or during the next
490edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // transaction.
491edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
492edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        const uint32_t mask = (1-index) ? eResizeBuffer1 : eResizeBuffer0;
493edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (mResizeTransactionDone && (newValue & mask)) {
494edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // Resize the layer's second buffer only if the transaction
495edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // happened. It may not have happened yet if eResizeRequested
496edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // was set immediately after the "transactionRequested" test,
497edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // in which case the drawing state's size would be wrong.
498edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            mFreezeLock.clear();
499edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            const Layer::State& s(drawingState());
500edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            if (resize(1-index, s.w, s.h, "post") == NO_ERROR) {
501edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                do {
502edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    oldValue = lcblk->swapState;
503edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    if ((oldValue & eResizeRequested) == eResizeRequested) {
504edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                        // ugh, another resize was requested since we processed
505edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                        // the first buffer, don't free the client, and let
506edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                        // the next transaction handle everything.
507edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                        break;
508edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    }
509edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    newValue = oldValue & ~mask;
510edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
511edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            }
512edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            mResizeTransactionDone = false;
513edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            recomputeVisibleRegions = true;
514edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            this->contentDirty = true;
515edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
516edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
517edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
518edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    reloadTexture(dirty);
519edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
520edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return dirty;
521edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
522edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
523edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectPoint Layer::getPhysicalSize() const
524edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
525edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const LayerBitmap& front(frontBuffer());
526edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return Point(front.width(), front.height());
527edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
528edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
529edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid Layer::unlockPageFlip(
530edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        const Transform& planeTransform, Region& outDirtyRegion)
531edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
532edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    Region dirtyRegion(mPostedDirtyRegion);
533edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (!dirtyRegion.isEmpty()) {
534edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mPostedDirtyRegion.clear();
535edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // The dirty region is given in the layer's coordinate space
536edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // transform the dirty region by the surface's transformation
537edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // and the global transformation.
538edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        const Layer::State& s(drawingState());
539edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        const Transform tr(planeTransform * s.transform);
540edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        dirtyRegion = tr.transform(dirtyRegion);
541edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
542edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // At this point, the dirty region is in screen space.
543edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // Make sure it's constrained by the visible region (which
544edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // is in screen space as well).
545edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        dirtyRegion.andSelf(visibleRegionScreen);
546edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        outDirtyRegion.orSelf(dirtyRegion);
547edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
548edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // client could be blocked, so signal them so they get a
549edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // chance to reevaluate their condition.
550edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mFlinger->scheduleBroadcast(client);
551edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
552edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
553edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
554edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid Layer::finishPageFlip()
555edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
556edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (LIKELY(!(lcblk->swapState & eInvalidSurface))) {
557edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        LOGE_IF(!(lcblk->swapState & eBusy),
558edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                "layer %p wasn't locked!", this);
559edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        android_atomic_and(~eBusy, &(lcblk->swapState));
560edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
561edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mFlinger->scheduleBroadcast(client);
562edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
563edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
564edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
565edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ---------------------------------------------------------------------------
566edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
567edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
568edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}; // namespace android
569