blob: f0b19f26e93ec3aeb340b8986aaf8e423dc4d898 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017#include <stdlib.h>
18#include <stdio.h>
19#include <stdint.h>
20#include <unistd.h>
21#include <fcntl.h>
22#include <errno.h>
23#include <math.h>
Jean-Baptiste Queru20763732009-01-26 11:51:12 -080024#include <limits.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025#include <sys/types.h>
26#include <sys/stat.h>
27#include <sys/ioctl.h>
28
29#include <cutils/log.h>
30#include <cutils/properties.h>
31
Mathias Agopian07952722009-05-19 19:08:10 -070032#include <binder/IPCThreadState.h>
33#include <binder/IServiceManager.h>
Mathias Agopiand763b5d2009-07-02 18:11:53 -070034#include <binder/MemoryHeapBase.h>
Mathias Agopian0dd593f2011-06-27 16:05:52 -070035#include <binder/PermissionCache.h>
Mathias Agopiand763b5d2009-07-02 18:11:53 -070036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037#include <utils/String8.h>
38#include <utils/String16.h>
39#include <utils/StopWatch.h>
40
Mathias Agopian6950e422009-10-05 17:07:12 -070041#include <ui/GraphicBufferAllocator.h>
Mathias Agopian04262e92010-09-13 22:57:58 -070042#include <ui/GraphicLog.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043#include <ui/PixelFormat.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044
45#include <pixelflinger/pixelflinger.h>
46#include <GLES/gl.h>
47
48#include "clz.h"
Mathias Agopian781953d2010-06-25 18:02:21 -070049#include "GLExtensions.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050#include "Layer.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051#include "LayerDim.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052#include "SurfaceFlinger.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053
54#include "DisplayHardware/DisplayHardware.h"
Mathias Agopiane0d5f5b2010-08-10 17:14:02 -070055#include "DisplayHardware/HWComposer.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056
Mathias Agopian7bb843c2011-04-20 14:20:59 -070057#include <private/surfaceflinger/SharedBufferStack.h>
58
Mathias Agopian627e7b52009-05-21 19:21:59 -070059/* ideally AID_GRAPHICS would be in a semi-public header
60 * or there would be a way to map a user/group name to its id
61 */
62#ifndef AID_GRAPHICS
63#define AID_GRAPHICS 1003
64#endif
65
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066#define DISPLAY_COUNT 1
67
68namespace android {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069// ---------------------------------------------------------------------------
70
Mathias Agopian0dd593f2011-06-27 16:05:52 -070071const String16 sHardwareTest("android.permission.HARDWARE_TEST");
72const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
73const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
74const String16 sDump("android.permission.DUMP");
75
76// ---------------------------------------------------------------------------
77
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078SurfaceFlinger::SurfaceFlinger()
79 : BnSurfaceComposer(), Thread(false),
80 mTransactionFlags(0),
81 mTransactionCount(0),
Mathias Agopian9779b222009-09-07 16:32:45 -070082 mResizeTransationPending(false),
Mathias Agopian1473f462009-04-10 14:24:30 -070083 mLayersRemoved(false),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 mBootTime(systemTime()),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 mVisibleRegionsDirty(false),
Mathias Agopiane0d5f5b2010-08-10 17:14:02 -070086 mHwWorkListDirty(false),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 mDeferReleaseConsole(false),
88 mFreezeDisplay(false),
Mathias Agopiand4e03f32010-10-14 14:54:06 -070089 mElectronBeamAnimationMode(0),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 mFreezeCount(0),
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -070091 mFreezeDisplayTime(0),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 mDebugRegion(0),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093 mDebugBackground(0),
Mathias Agopian6a969242010-09-22 18:58:01 -070094 mDebugDisableHWC(0),
Mathias Agopiana8d49172009-08-26 16:36:26 -070095 mDebugInSwapBuffers(0),
96 mLastSwapBufferTime(0),
97 mDebugInTransaction(0),
98 mLastTransactionTime(0),
Mathias Agopian6950e422009-10-05 17:07:12 -070099 mBootFinished(false),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100 mConsoleSignals(0),
101 mSecureFrameBuffer(0)
102{
103 init();
104}
105
106void SurfaceFlinger::init()
107{
108 LOGI("SurfaceFlinger is starting");
109
110 // debugging stuff...
111 char value[PROPERTY_VALUE_MAX];
112 property_get("debug.sf.showupdates", value, "0");
113 mDebugRegion = atoi(value);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 property_get("debug.sf.showbackground", value, "0");
115 mDebugBackground = atoi(value);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116
Mathias Agopiane5c0a7b2010-04-20 14:51:04 -0700117 LOGI_IF(mDebugRegion, "showupdates enabled");
118 LOGI_IF(mDebugBackground, "showbackground enabled");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119}
120
121SurfaceFlinger::~SurfaceFlinger()
122{
123 glDeleteTextures(1, &mWormholeTexName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124}
125
Mathias Agopiand763b5d2009-07-02 18:11:53 -0700126sp<IMemoryHeap> SurfaceFlinger::getCblk() const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127{
Mathias Agopiand763b5d2009-07-02 18:11:53 -0700128 return mServerHeap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129}
130
Mathias Agopian770492c2010-05-28 14:22:23 -0700131sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132{
Mathias Agopian593c05c2010-06-02 23:28:45 -0700133 sp<ISurfaceComposerClient> bclient;
134 sp<Client> client(new Client(this));
135 status_t err = client->initCheck();
136 if (err == NO_ERROR) {
137 bclient = client;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 return bclient;
140}
141
Jamie Gennisf7acf162011-01-12 18:30:40 -0800142sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
143{
144 sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
145 return gba;
146}
Mathias Agopian7623da42010-06-01 15:12:58 -0700147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
149{
150 LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy);
151 const GraphicPlane& plane(mGraphicPlanes[dpy]);
152 return plane;
153}
154
155GraphicPlane& SurfaceFlinger::graphicPlane(int dpy)
156{
157 return const_cast<GraphicPlane&>(
158 const_cast<SurfaceFlinger const *>(this)->graphicPlane(dpy));
159}
160
161void SurfaceFlinger::bootFinished()
162{
163 const nsecs_t now = systemTime();
164 const nsecs_t duration = now - mBootTime;
Andreas Hubere3c01832010-08-16 08:49:37 -0700165 LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
Mathias Agopian6950e422009-10-05 17:07:12 -0700166 mBootFinished = true;
Mathias Agopian627e7b52009-05-21 19:21:59 -0700167 property_set("ctl.stop", "bootanim");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168}
169
170void SurfaceFlinger::onFirstRef()
171{
172 run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
173
174 // Wait for the main thread to be done with its initialization
175 mReadyToRunBarrier.wait();
176}
177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178static inline uint16_t pack565(int r, int g, int b) {
179 return (r<<11)|(g<<5)|b;
180}
181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182status_t SurfaceFlinger::readyToRun()
183{
184 LOGI( "SurfaceFlinger's main thread ready to run. "
185 "Initializing graphics H/W...");
186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 // we only support one display currently
188 int dpy = 0;
189
190 {
191 // initialize the main display
192 GraphicPlane& plane(graphicPlane(dpy));
193 DisplayHardware* const hw = new DisplayHardware(this, dpy);
194 plane.setDisplayHardware(hw);
195 }
196
Mathias Agopiand763b5d2009-07-02 18:11:53 -0700197 // create the shared control-block
198 mServerHeap = new MemoryHeapBase(4096,
199 MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");
200 LOGE_IF(mServerHeap==0, "can't create shared memory dealer");
Andreas Hubere3c01832010-08-16 08:49:37 -0700201
Mathias Agopiand763b5d2009-07-02 18:11:53 -0700202 mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());
203 LOGE_IF(mServerCblk==0, "can't get to shared control block's address");
Andreas Hubere3c01832010-08-16 08:49:37 -0700204
Mathias Agopiand763b5d2009-07-02 18:11:53 -0700205 new(mServerCblk) surface_flinger_cblk_t;
206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 // initialize primary screen
208 // (other display should be initialized in the same manner, but
209 // asynchronously, as they could come and go. None of this is supported
210 // yet).
211 const GraphicPlane& plane(graphicPlane(dpy));
212 const DisplayHardware& hw = plane.displayHardware();
213 const uint32_t w = hw.getWidth();
214 const uint32_t h = hw.getHeight();
215 const uint32_t f = hw.getFormat();
216 hw.makeCurrent();
217
218 // initialize the shared control block
219 mServerCblk->connected |= 1<<dpy;
220 display_cblk_t* dcblk = mServerCblk->displays + dpy;
221 memset(dcblk, 0, sizeof(display_cblk_t));
Mathias Agopian66c77a52010-02-08 15:49:35 -0800222 dcblk->w = plane.getWidth();
223 dcblk->h = plane.getHeight();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 dcblk->format = f;
225 dcblk->orientation = ISurfaceComposer::eOrientationDefault;
226 dcblk->xdpi = hw.getDpiX();
227 dcblk->ydpi = hw.getDpiY();
228 dcblk->fps = hw.getRefreshRate();
229 dcblk->density = hw.getDensity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230
231 // Initialize OpenGL|ES
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
Andreas Hubere3c01832010-08-16 08:49:37 -0700233 glPixelStorei(GL_PACK_ALIGNMENT, 4);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 glEnableClientState(GL_VERTEX_ARRAY);
235 glEnable(GL_SCISSOR_TEST);
236 glShadeModel(GL_FLAT);
237 glDisable(GL_DITHER);
238 glDisable(GL_CULL_FACE);
239
240 const uint16_t g0 = pack565(0x0F,0x1F,0x0F);
241 const uint16_t g1 = pack565(0x17,0x2f,0x17);
242 const uint16_t textureData[4] = { g0, g1, g1, g0 };
243 glGenTextures(1, &mWormholeTexName);
244 glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
245 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
246 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
247 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
248 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
249 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,
250 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, textureData);
251
252 glViewport(0, 0, w, h);
253 glMatrixMode(GL_PROJECTION);
254 glLoadIdentity();
255 glOrthof(0, w, h, 0, 0, 1);
256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 mReadyToRunBarrier.open();
258
259 /*
260 * We're now ready to accept clients...
261 */
262
Mathias Agopian627e7b52009-05-21 19:21:59 -0700263 // start boot animation
264 property_set("ctl.start", "bootanim");
Andreas Hubere3c01832010-08-16 08:49:37 -0700265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 return NO_ERROR;
267}
268
269// ----------------------------------------------------------------------------
270#if 0
271#pragma mark -
272#pragma mark Events Handler
273#endif
274
275void SurfaceFlinger::waitForEvent()
276{
Mathias Agopian6ead5d92009-04-20 19:39:12 -0700277 while (true) {
278 nsecs_t timeout = -1;
Mathias Agopian0e449762009-12-01 17:23:28 -0800279 const nsecs_t freezeDisplayTimeout = ms2ns(5000);
Mathias Agopian6ead5d92009-04-20 19:39:12 -0700280 if (UNLIKELY(isFrozen())) {
281 // wait 5 seconds
Mathias Agopian6ead5d92009-04-20 19:39:12 -0700282 const nsecs_t now = systemTime();
283 if (mFreezeDisplayTime == 0) {
284 mFreezeDisplayTime = now;
285 }
286 nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime);
287 timeout = waitTime>0 ? waitTime : 0;
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700288 }
Mathias Agopian6ead5d92009-04-20 19:39:12 -0700289
Mathias Agopian898c4c92010-05-18 17:06:55 -0700290 sp<MessageBase> msg = mEventQueue.waitMessage(timeout);
Mathias Agopian0e449762009-12-01 17:23:28 -0800291
292 // see if we timed out
293 if (isFrozen()) {
294 const nsecs_t now = systemTime();
295 nsecs_t frozenTime = (now - mFreezeDisplayTime);
296 if (frozenTime >= freezeDisplayTimeout) {
297 // we timed out and are still frozen
298 LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d",
299 mFreezeDisplay, mFreezeCount);
300 mFreezeDisplayTime = 0;
301 mFreezeCount = 0;
302 mFreezeDisplay = false;
303 }
304 }
305
Mathias Agopian6ead5d92009-04-20 19:39:12 -0700306 if (msg != 0) {
Mathias Agopian6ead5d92009-04-20 19:39:12 -0700307 switch (msg->what) {
308 case MessageQueue::INVALIDATE:
309 // invalidate message, just return to the main loop
310 return;
311 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 }
314}
315
316void SurfaceFlinger::signalEvent() {
Mathias Agopian6ead5d92009-04-20 19:39:12 -0700317 mEventQueue.invalidate();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318}
319
Jamie Gennisd2acedf2011-03-08 12:18:54 -0800320bool SurfaceFlinger::authenticateSurface(const sp<ISurface>& surface) const {
321 Mutex::Autolock _l(mStateLock);
322 sp<IBinder> surfBinder(surface->asBinder());
323
324 // Check the visible layer list for the ISurface
325 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
326 size_t count = currentLayers.size();
327 for (size_t i=0 ; i<count ; i++) {
328 const sp<LayerBase>& layer(currentLayers[i]);
329 sp<LayerBaseClient> lbc(layer->getLayerBaseClient());
330 if (lbc != NULL && lbc->getSurfaceBinder() == surfBinder) {
331 return true;
332 }
333 }
334
335 // Check the layers in the purgatory. This check is here so that if a
336 // Surface gets destroyed before all the clients are done using it, the
337 // error will not be reported as "surface XYZ is not authenticated", but
338 // will instead fail later on when the client tries to use the surface,
339 // which should be reported as "surface XYZ returned an -ENODEV". The
340 // purgatorized layers are no less authentic than the visible ones, so this
341 // should not cause any harm.
342 size_t purgatorySize = mLayerPurgatory.size();
343 for (size_t i=0 ; i<purgatorySize ; i++) {
344 const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i));
345 sp<LayerBaseClient> lbc(layer->getLayerBaseClient());
346 if (lbc != NULL && lbc->getSurfaceBinder() == surfBinder) {
347 return true;
348 }
349 }
350
351 return false;
352}
353
Mathias Agopian898c4c92010-05-18 17:06:55 -0700354status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
355 nsecs_t reltime, uint32_t flags)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356{
Mathias Agopian898c4c92010-05-18 17:06:55 -0700357 return mEventQueue.postMessage(msg, reltime, flags);
358}
359
360status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
361 nsecs_t reltime, uint32_t flags)
362{
363 status_t res = mEventQueue.postMessage(msg, reltime, flags);
364 if (res == NO_ERROR) {
365 msg->wait();
366 }
367 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368}
369
370// ----------------------------------------------------------------------------
371#if 0
372#pragma mark -
373#pragma mark Main loop
374#endif
375
376bool SurfaceFlinger::threadLoop()
377{
378 waitForEvent();
379
Mathias Agopian69608112011-05-19 15:38:14 -0700380 // call Layer's destructor
381 handleDestroyLayers();
382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 // check for transactions
384 if (UNLIKELY(mConsoleSignals)) {
385 handleConsoleEvents();
386 }
387
388 if (LIKELY(mTransactionCount == 0)) {
389 // if we're in a global transaction, don't do anything.
390 const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
Mathias Agopian6dcb1552011-05-03 17:04:02 -0700391 uint32_t transactionFlags = peekTransactionFlags(mask);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 if (LIKELY(transactionFlags)) {
393 handleTransaction(transactionFlags);
394 }
395 }
396
397 // post surfaces (if needed)
398 handlePageFlip();
399
Mathias Agopiane0d5f5b2010-08-10 17:14:02 -0700400 if (UNLIKELY(mHwWorkListDirty)) {
401 // build the h/w work list
402 handleWorkList();
403 }
404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 const DisplayHardware& hw(graphicPlane(0).displayHardware());
Mathias Agopian81384bf2009-09-27 22:47:27 -0700406 if (LIKELY(hw.canDraw() && !isFrozen())) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 // repaint the framebuffer (if needed)
Mathias Agopian04262e92010-09-13 22:57:58 -0700408
409 const int index = hw.getCurrentBufferIndex();
410 GraphicLog& logger(GraphicLog::getInstance());
411
412 logger.log(GraphicLog::SF_REPAINT, index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 handleRepaint();
414
Mathias Agopianb1a18742009-09-17 16:18:16 -0700415 // inform the h/w that we're done compositing
Mathias Agopian04262e92010-09-13 22:57:58 -0700416 logger.log(GraphicLog::SF_COMPOSITION_COMPLETE, index);
Mathias Agopianb1a18742009-09-17 16:18:16 -0700417 hw.compositionComplete();
418
Mathias Agopian04262e92010-09-13 22:57:58 -0700419 logger.log(GraphicLog::SF_SWAP_BUFFERS, index);
Antti Hatala4c0a4a22010-09-08 06:37:14 -0700420 postFramebuffer();
421
Mathias Agopian04262e92010-09-13 22:57:58 -0700422 logger.log(GraphicLog::SF_REPAINT_DONE, index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 } else {
424 // pretend we did the post
Mathias Agopiana6b8c1c2010-12-15 14:41:59 -0800425 hw.compositionComplete();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 usleep(16667); // 60 fps period
427 }
428 return true;
429}
430
431void SurfaceFlinger::postFramebuffer()
432{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 if (!mInvalidRegion.isEmpty()) {
434 const DisplayHardware& hw(graphicPlane(0).displayHardware());
Mathias Agopiana8d49172009-08-26 16:36:26 -0700435 const nsecs_t now = systemTime();
436 mDebugInSwapBuffers = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 hw.flip(mInvalidRegion);
Mathias Agopiana8d49172009-08-26 16:36:26 -0700438 mLastSwapBufferTime = systemTime() - now;
439 mDebugInSwapBuffers = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 mInvalidRegion.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 }
442}
443
444void SurfaceFlinger::handleConsoleEvents()
445{
446 // something to do with the console
447 const DisplayHardware& hw = graphicPlane(0).displayHardware();
448
449 int what = android_atomic_and(0, &mConsoleSignals);
450 if (what & eConsoleAcquired) {
451 hw.acquireScreen();
Mathias Agopian2d2b8032010-10-12 16:05:48 -0700452 // this is a temporary work-around, eventually this should be called
453 // by the power-manager
Mathias Agopiand4e03f32010-10-14 14:54:06 -0700454 SurfaceFlinger::turnElectronBeamOn(mElectronBeamAnimationMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455 }
456
Mathias Agopianaab758e2010-10-11 12:37:43 -0700457 if (mDeferReleaseConsole && hw.isScreenAcquired()) {
Mathias Agopianed81f222009-04-14 23:02:51 -0700458 // We got the release signal before the acquire signal
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 mDeferReleaseConsole = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 hw.releaseScreen();
461 }
462
463 if (what & eConsoleReleased) {
Mathias Agopianaab758e2010-10-11 12:37:43 -0700464 if (hw.isScreenAcquired()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465 hw.releaseScreen();
466 } else {
467 mDeferReleaseConsole = true;
468 }
469 }
470
471 mDirtyRegion.set(hw.bounds());
472}
473
474void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
475{
Mathias Agopian69608112011-05-19 15:38:14 -0700476 Mutex::Autolock _l(mStateLock);
477 const nsecs_t now = systemTime();
478 mDebugInTransaction = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479
Mathias Agopian69608112011-05-19 15:38:14 -0700480 // Here we're guaranteed that some transaction flags are set
481 // so we can call handleTransactionLocked() unconditionally.
482 // We call getTransactionFlags(), which will also clear the flags,
483 // with mStateLock held to guarantee that mCurrentState won't change
484 // until the transaction is committed.
Mathias Agopianff1d4102010-08-10 17:19:56 -0700485
Mathias Agopian69608112011-05-19 15:38:14 -0700486 const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
487 transactionFlags = getTransactionFlags(mask);
488 handleTransactionLocked(transactionFlags);
Mathias Agopian6dcb1552011-05-03 17:04:02 -0700489
Mathias Agopian69608112011-05-19 15:38:14 -0700490 mLastTransactionTime = systemTime() - now;
491 mDebugInTransaction = 0;
492 invalidateHwcGeometry();
493 // here the transaction has been committed
Mathias Agopian2d5ee252009-06-04 18:46:21 -0700494}
495
Mathias Agopian69608112011-05-19 15:38:14 -0700496void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
Mathias Agopian2d5ee252009-06-04 18:46:21 -0700497{
498 const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800499 const size_t count = currentLayers.size();
500
501 /*
502 * Traversal of the children
503 * (perform the transaction for each of them if needed)
504 */
505
506 const bool layersNeedTransaction = transactionFlags & eTraversalNeeded;
507 if (layersNeedTransaction) {
508 for (size_t i=0 ; i<count ; i++) {
Mathias Agopian1473f462009-04-10 14:24:30 -0700509 const sp<LayerBase>& layer = currentLayers[i];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
511 if (!trFlags) continue;
512
513 const uint32_t flags = layer->doTransaction(0);
514 if (flags & Layer::eVisibleRegion)
515 mVisibleRegionsDirty = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800516 }
517 }
518
519 /*
520 * Perform our own transaction if needed
521 */
522
523 if (transactionFlags & eTransactionNeeded) {
524 if (mCurrentState.orientation != mDrawingState.orientation) {
525 // the orientation has changed, recompute all visible regions
526 // and invalidate everything.
527
528 const int dpy = 0;
529 const int orientation = mCurrentState.orientation;
Mathias Agopianeb0c86e2009-03-27 18:11:38 -0700530 const uint32_t type = mCurrentState.orientationType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800531 GraphicPlane& plane(graphicPlane(dpy));
532 plane.setOrientation(orientation);
533
534 // update the shared control block
535 const DisplayHardware& hw(plane.displayHardware());
536 volatile display_cblk_t* dcblk = mServerCblk->displays + dpy;
537 dcblk->orientation = orientation;
Mathias Agopian66c77a52010-02-08 15:49:35 -0800538 dcblk->w = plane.getWidth();
539 dcblk->h = plane.getHeight();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540
541 mVisibleRegionsDirty = true;
542 mDirtyRegion.set(hw.bounds());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 }
544
545 if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) {
546 // freezing or unfreezing the display -> trigger animation if needed
547 mFreezeDisplay = mCurrentState.freezeDisplay;
Mathias Agopian31901cc2010-03-01 17:51:17 -0800548 if (mFreezeDisplay)
549 mFreezeDisplayTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 }
551
Mathias Agopiana3aa6c92009-04-22 15:23:34 -0700552 if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) {
553 // layers have been added
554 mVisibleRegionsDirty = true;
555 }
556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 // some layers might have been removed, so
558 // we need to update the regions they're exposing.
Mathias Agopian1473f462009-04-10 14:24:30 -0700559 if (mLayersRemoved) {
Mathias Agopian248b5bd2009-09-10 19:41:18 -0700560 mLayersRemoved = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800561 mVisibleRegionsDirty = true;
Mathias Agopiana3aa6c92009-04-22 15:23:34 -0700562 const LayerVector& previousLayers(mDrawingState.layersSortedByZ);
Mathias Agopian2d5ee252009-06-04 18:46:21 -0700563 const size_t count = previousLayers.size();
564 for (size_t i=0 ; i<count ; i++) {
Mathias Agopiana3aa6c92009-04-22 15:23:34 -0700565 const sp<LayerBase>& layer(previousLayers[i]);
566 if (currentLayers.indexOf( layer ) < 0) {
567 // this layer is not visible anymore
Mathias Agopian33863dd2009-07-28 14:20:21 -0700568 mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen);
Mathias Agopiana3aa6c92009-04-22 15:23:34 -0700569 }
570 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800572 }
573
574 commitTransaction();
575}
576
Mathias Agopian69608112011-05-19 15:38:14 -0700577void SurfaceFlinger::destroyLayer(LayerBase const* layer)
578{
579 Mutex::Autolock _l(mDestroyedLayerLock);
580 mDestroyedLayers.add(layer);
581 signalEvent();
582}
583
584void SurfaceFlinger::handleDestroyLayers()
585{
586 Vector<LayerBase const *> destroyedLayers;
587
588 { // scope for the lock
589 Mutex::Autolock _l(mDestroyedLayerLock);
590 destroyedLayers = mDestroyedLayers;
591 mDestroyedLayers.clear();
592 }
593
594 // call destructors without a lock held
595 const size_t count = destroyedLayers.size();
596 for (size_t i=0 ; i<count ; i++) {
597 //LOGD("destroying %s", destroyedLayers[i]->getName().string());
598 delete destroyedLayers[i];
599 }
600}
601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602sp<FreezeLock> SurfaceFlinger::getFreezeLock() const
603{
604 return new FreezeLock(const_cast<SurfaceFlinger *>(this));
605}
606
607void SurfaceFlinger::computeVisibleRegions(
Mathias Agopianf0ff9062011-03-11 16:54:47 -0800608 const LayerVector& currentLayers, Region& dirtyRegion, Region& opaqueRegion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800609{
610 const GraphicPlane& plane(graphicPlane(0));
611 const Transform& planeTransform(plane.transform());
Mathias Agopian9c041bb2010-03-16 16:41:46 -0700612 const DisplayHardware& hw(plane.displayHardware());
613 const Region screenRegion(hw.bounds());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800614
615 Region aboveOpaqueLayers;
616 Region aboveCoveredLayers;
617 Region dirty;
618
619 bool secureFrameBuffer = false;
620
621 size_t i = currentLayers.size();
622 while (i--) {
Mathias Agopian1473f462009-04-10 14:24:30 -0700623 const sp<LayerBase>& layer = currentLayers[i];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 layer->validateVisibility(planeTransform);
625
626 // start with the whole surface at its current location
Mathias Agopian12cedff2009-07-28 10:57:27 -0700627 const Layer::State& s(layer->drawingState());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628
Mathias Agopian9c041bb2010-03-16 16:41:46 -0700629 /*
630 * opaqueRegion: area of a surface that is fully opaque.
631 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 Region opaqueRegion;
Mathias Agopian9c041bb2010-03-16 16:41:46 -0700633
634 /*
635 * visibleRegion: area of a surface that is visible on screen
636 * and not fully transparent. This is essentially the layer's
637 * footprint minus the opaque regions above it.
638 * Areas covered by a translucent surface are considered visible.
639 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800640 Region visibleRegion;
Mathias Agopian9c041bb2010-03-16 16:41:46 -0700641
642 /*
643 * coveredRegion: area of a surface that is covered by all
644 * visible regions above it (which includes the translucent areas).
645 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 Region coveredRegion;
Mathias Agopian9c041bb2010-03-16 16:41:46 -0700647
648
649 // handle hidden surfaces by setting the visible region to empty
Mathias Agopian12cedff2009-07-28 10:57:27 -0700650 if (LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) {
Mathias Agopian7bb843c2011-04-20 14:20:59 -0700651 const bool translucent = !layer->isOpaque();
Mathias Agopian12cedff2009-07-28 10:57:27 -0700652 const Rect bounds(layer->visibleBounds());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653 visibleRegion.set(bounds);
Mathias Agopian9c041bb2010-03-16 16:41:46 -0700654 visibleRegion.andSelf(screenRegion);
655 if (!visibleRegion.isEmpty()) {
656 // Remove the transparent area from the visible region
657 if (translucent) {
658 visibleRegion.subtractSelf(layer->transparentRegionScreen);
659 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800660
Mathias Agopian9c041bb2010-03-16 16:41:46 -0700661 // compute the opaque region
662 const int32_t layerOrientation = layer->getOrientation();
663 if (s.alpha==255 && !translucent &&
664 ((layerOrientation & Transform::ROT_INVALID) == false)) {
665 // the opaque region is the layer's footprint
666 opaqueRegion = visibleRegion;
667 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668 }
669 }
670
Mathias Agopian9c041bb2010-03-16 16:41:46 -0700671 // Clip the covered region to the visible region
672 coveredRegion = aboveCoveredLayers.intersect(visibleRegion);
673
674 // Update aboveCoveredLayers for next (lower) layer
675 aboveCoveredLayers.orSelf(visibleRegion);
676
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800677 // subtract the opaque region covered by the layers above us
678 visibleRegion.subtractSelf(aboveOpaqueLayers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679
680 // compute this layer's dirty region
681 if (layer->contentDirty) {
682 // we need to invalidate the whole region
683 dirty = visibleRegion;
684 // as well, as the old visible region
685 dirty.orSelf(layer->visibleRegionScreen);
686 layer->contentDirty = false;
687 } else {
Mathias Agopian0aed7e92009-06-28 02:54:16 -0700688 /* compute the exposed region:
Mathias Agopian9c041bb2010-03-16 16:41:46 -0700689 * the exposed region consists of two components:
690 * 1) what's VISIBLE now and was COVERED before
691 * 2) what's EXPOSED now less what was EXPOSED before
692 *
693 * note that (1) is conservative, we start with the whole
694 * visible region but only keep what used to be covered by
695 * something -- which mean it may have been exposed.
696 *
697 * (2) handles areas that were not covered by anything but got
698 * exposed because of a resize.
Mathias Agopian0aed7e92009-06-28 02:54:16 -0700699 */
Mathias Agopian9c041bb2010-03-16 16:41:46 -0700700 const Region newExposed = visibleRegion - coveredRegion;
701 const Region oldVisibleRegion = layer->visibleRegionScreen;
702 const Region oldCoveredRegion = layer->coveredRegionScreen;
703 const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
704 dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705 }
706 dirty.subtractSelf(aboveOpaqueLayers);
707
708 // accumulate to the screen dirty region
709 dirtyRegion.orSelf(dirty);
710
Mathias Agopian9c041bb2010-03-16 16:41:46 -0700711 // Update aboveOpaqueLayers for next (lower) layer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712 aboveOpaqueLayers.orSelf(opaqueRegion);
Andreas Hubere3c01832010-08-16 08:49:37 -0700713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714 // Store the visible region is screen space
715 layer->setVisibleRegion(visibleRegion);
716 layer->setCoveredRegion(coveredRegion);
717
Mathias Agopian12cedff2009-07-28 10:57:27 -0700718 // If a secure layer is partially visible, lock-down the screen!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 if (layer->isSecure() && !visibleRegion.isEmpty()) {
720 secureFrameBuffer = true;
721 }
722 }
723
Mathias Agopian12cedff2009-07-28 10:57:27 -0700724 // invalidate the areas where a layer was removed
725 dirtyRegion.orSelf(mDirtyRegionRemovedLayer);
726 mDirtyRegionRemovedLayer.clear();
727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728 mSecureFrameBuffer = secureFrameBuffer;
729 opaqueRegion = aboveOpaqueLayers;
730}
731
732
733void SurfaceFlinger::commitTransaction()
734{
735 mDrawingState = mCurrentState;
Mathias Agopian9779b222009-09-07 16:32:45 -0700736 mResizeTransationPending = false;
737 mTransactionCV.broadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738}
739
740void SurfaceFlinger::handlePageFlip()
741{
742 bool visibleRegions = mVisibleRegionsDirty;
Mathias Agopianf0ff9062011-03-11 16:54:47 -0800743 const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 visibleRegions |= lockPageFlip(currentLayers);
745
746 const DisplayHardware& hw = graphicPlane(0).displayHardware();
747 const Region screenRegion(hw.bounds());
748 if (visibleRegions) {
749 Region opaqueRegion;
750 computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
Mathias Agopianff1d4102010-08-10 17:19:56 -0700751
752 /*
753 * rebuild the visible layer list
754 */
Mathias Agopianf0ff9062011-03-11 16:54:47 -0800755 const size_t count = currentLayers.size();
Mathias Agopianff1d4102010-08-10 17:19:56 -0700756 mVisibleLayersSortedByZ.clear();
Mathias Agopianff1d4102010-08-10 17:19:56 -0700757 mVisibleLayersSortedByZ.setCapacity(count);
758 for (size_t i=0 ; i<count ; i++) {
759 if (!currentLayers[i]->visibleRegionScreen.isEmpty())
760 mVisibleLayersSortedByZ.add(currentLayers[i]);
761 }
762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 mWormholeRegion = screenRegion.subtract(opaqueRegion);
764 mVisibleRegionsDirty = false;
Mathias Agopianfb4dcb12011-01-13 17:53:01 -0800765 invalidateHwcGeometry();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 }
767
768 unlockPageFlip(currentLayers);
769 mDirtyRegion.andSelf(screenRegion);
770}
771
Mathias Agopianfb4dcb12011-01-13 17:53:01 -0800772void SurfaceFlinger::invalidateHwcGeometry()
773{
774 mHwWorkListDirty = true;
775}
776
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
778{
779 bool recomputeVisibleRegions = false;
780 size_t count = currentLayers.size();
Mathias Agopian1473f462009-04-10 14:24:30 -0700781 sp<LayerBase> const* layers = currentLayers.array();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 for (size_t i=0 ; i<count ; i++) {
Mathias Agopian7623da42010-06-01 15:12:58 -0700783 const sp<LayerBase>& layer(layers[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 layer->lockPageFlip(recomputeVisibleRegions);
785 }
786 return recomputeVisibleRegions;
787}
788
789void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
790{
791 const GraphicPlane& plane(graphicPlane(0));
792 const Transform& planeTransform(plane.transform());
793 size_t count = currentLayers.size();
Mathias Agopian1473f462009-04-10 14:24:30 -0700794 sp<LayerBase> const* layers = currentLayers.array();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795 for (size_t i=0 ; i<count ; i++) {
Mathias Agopian7623da42010-06-01 15:12:58 -0700796 const sp<LayerBase>& layer(layers[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 layer->unlockPageFlip(planeTransform, mDirtyRegion);
798 }
799}
800
Mathias Agopiane0d5f5b2010-08-10 17:14:02 -0700801void SurfaceFlinger::handleWorkList()
802{
803 mHwWorkListDirty = false;
804 HWComposer& hwc(graphicPlane(0).displayHardware().getHwComposer());
805 if (hwc.initCheck() == NO_ERROR) {
806 const Vector< sp<LayerBase> >& currentLayers(mVisibleLayersSortedByZ);
807 const size_t count = currentLayers.size();
808 hwc.createWorkList(count);
Mathias Agopianf8e705d2010-08-12 15:03:26 -0700809 hwc_layer_t* const cur(hwc.getLayers());
810 for (size_t i=0 ; cur && i<count ; i++) {
811 currentLayers[i]->setGeometry(&cur[i]);
Mathias Agopian6a969242010-09-22 18:58:01 -0700812 if (mDebugDisableHWC) {
813 cur[i].compositionType = HWC_FRAMEBUFFER;
814 cur[i].flags |= HWC_SKIP_LAYER;
815 }
Mathias Agopiane0d5f5b2010-08-10 17:14:02 -0700816 }
817 }
818}
Mathias Agopian8c9687a2009-06-26 19:06:36 -0700819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820void SurfaceFlinger::handleRepaint()
821{
Mathias Agopian8c9687a2009-06-26 19:06:36 -0700822 // compute the invalid region
823 mInvalidRegion.orSelf(mDirtyRegion);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824
825 if (UNLIKELY(mDebugRegion)) {
826 debugFlashRegions();
827 }
828
Mathias Agopian8c9687a2009-06-26 19:06:36 -0700829 // set the frame buffer
830 const DisplayHardware& hw(graphicPlane(0).displayHardware());
831 glMatrixMode(GL_MODELVIEW);
832 glLoadIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833
834 uint32_t flags = hw.getFlags();
Andreas Hubere3c01832010-08-16 08:49:37 -0700835 if ((flags & DisplayHardware::SWAP_RECTANGLE) ||
836 (flags & DisplayHardware::BUFFER_PRESERVED))
Mathias Agopian2e20bff2009-05-04 19:29:25 -0700837 {
Mathias Agopianecfa7cc2009-06-29 18:49:56 -0700838 // we can redraw only what's dirty, but since SWAP_RECTANGLE only
839 // takes a rectangle, we must make sure to update that whole
840 // rectangle in that case
841 if (flags & DisplayHardware::SWAP_RECTANGLE) {
Mathias Agopian7623da42010-06-01 15:12:58 -0700842 // TODO: we really should be able to pass a region to
Mathias Agopianecfa7cc2009-06-29 18:49:56 -0700843 // SWAP_RECTANGLE so that we don't have to redraw all this.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 mDirtyRegion.set(mInvalidRegion.bounds());
845 } else {
Mathias Agopianecfa7cc2009-06-29 18:49:56 -0700846 // in the BUFFER_PRESERVED case, obviously, we can update only
847 // what's needed and nothing more.
848 // NOTE: this is NOT a common case, as preserving the backbuffer
849 // is costly and usually involves copying the whole update back.
850 }
851 } else {
Mathias Agopianf2d28b72009-09-24 14:57:26 -0700852 if (flags & DisplayHardware::PARTIAL_UPDATES) {
Mathias Agopianecfa7cc2009-06-29 18:49:56 -0700853 // We need to redraw the rectangle that will be updated
854 // (pushed to the framebuffer).
Mathias Agopianf2d28b72009-09-24 14:57:26 -0700855 // This is needed because PARTIAL_UPDATES only takes one
Mathias Agopianecfa7cc2009-06-29 18:49:56 -0700856 // rectangle instead of a region (see DisplayHardware::flip())
857 mDirtyRegion.set(mInvalidRegion.bounds());
858 } else {
859 // we need to redraw everything (the whole screen)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 mDirtyRegion.set(hw.bounds());
861 mInvalidRegion = mDirtyRegion;
862 }
863 }
864
865 // compose all surfaces
866 composeSurfaces(mDirtyRegion);
867
868 // clear the dirty regions
869 mDirtyRegion.clear();
870}
871
872void SurfaceFlinger::composeSurfaces(const Region& dirty)
873{
874 if (UNLIKELY(!mWormholeRegion.isEmpty())) {
875 // should never happen unless the window manager has a bug
876 // draw something...
877 drawWormhole();
878 }
Mathias Agopiane0d5f5b2010-08-10 17:14:02 -0700879
880 status_t err = NO_ERROR;
Mathias Agopianff1d4102010-08-10 17:19:56 -0700881 const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
Mathias Agopianf8e705d2010-08-12 15:03:26 -0700882 size_t count = layers.size();
Mathias Agopiane0d5f5b2010-08-10 17:14:02 -0700883
884 const DisplayHardware& hw(graphicPlane(0).displayHardware());
885 HWComposer& hwc(hw.getHwComposer());
Mathias Agopianf8e705d2010-08-12 15:03:26 -0700886 hwc_layer_t* const cur(hwc.getLayers());
Mathias Agopiane0d5f5b2010-08-10 17:14:02 -0700887
Mathias Agopianf8e705d2010-08-12 15:03:26 -0700888 LOGE_IF(cur && hwc.getNumLayers() != count,
889 "HAL number of layers (%d) doesn't match surfaceflinger (%d)",
890 hwc.getNumLayers(), count);
891
892 // just to be extra-safe, use the smallest count
Erik Gilling0cf2f432010-08-12 23:21:40 -0700893 if (hwc.initCheck() == NO_ERROR) {
894 count = count < hwc.getNumLayers() ? count : hwc.getNumLayers();
895 }
Mathias Agopianf8e705d2010-08-12 15:03:26 -0700896
897 /*
898 * update the per-frame h/w composer data for each layer
899 * and build the transparent region of the FB
900 */
901 Region transparent;
902 if (cur) {
903 for (size_t i=0 ; i<count ; i++) {
904 const sp<LayerBase>& layer(layers[i]);
905 layer->setPerFrameData(&cur[i]);
Mathias Agopiane0d5f5b2010-08-10 17:14:02 -0700906 }
907 err = hwc.prepare();
908 LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
Mathias Agopiane0d5f5b2010-08-10 17:14:02 -0700909
Mathias Agopian45491692011-01-19 15:24:23 -0800910 if (err == NO_ERROR) {
911 for (size_t i=0 ; i<count ; i++) {
912 if (cur[i].hints & HWC_HINT_CLEAR_FB) {
913 const sp<LayerBase>& layer(layers[i]);
Mathias Agopian7bb843c2011-04-20 14:20:59 -0700914 if (layer->isOpaque()) {
Mathias Agopian45491692011-01-19 15:24:23 -0800915 transparent.orSelf(layer->visibleRegionScreen);
916 }
917 }
918 }
919
920 /*
921 * clear the area of the FB that need to be transparent
922 */
923 transparent.andSelf(dirty);
924 if (!transparent.isEmpty()) {
925 glClearColor(0,0,0,0);
926 Region::const_iterator it = transparent.begin();
927 Region::const_iterator const end = transparent.end();
928 const int32_t height = hw.getHeight();
929 while (it != end) {
930 const Rect& r(*it++);
931 const GLint sy = height - (r.top + r.height());
932 glScissor(r.left, sy, r.width(), r.height());
933 glClear(GL_COLOR_BUFFER_BIT);
934 }
935 }
Mathias Agopiane0d5f5b2010-08-10 17:14:02 -0700936 }
937 }
Mathias Agopianf8e705d2010-08-12 15:03:26 -0700938
939
940 /*
941 * and then, render the layers targeted at the framebuffer
942 */
943 for (size_t i=0 ; i<count ; i++) {
944 if (cur) {
Antti Hatala982f58b2010-09-09 02:32:30 -0700945 if ((cur[i].compositionType != HWC_FRAMEBUFFER) &&
946 !(cur[i].flags & HWC_SKIP_LAYER)) {
Mathias Agopianf8e705d2010-08-12 15:03:26 -0700947 // skip layers handled by the HAL
948 continue;
949 }
950 }
Mathias Agopian6a969242010-09-22 18:58:01 -0700951
Mathias Agopianf8e705d2010-08-12 15:03:26 -0700952 const sp<LayerBase>& layer(layers[i]);
953 const Region clip(dirty.intersect(layer->visibleRegionScreen));
954 if (!clip.isEmpty()) {
955 layer->draw(clip);
956 }
957 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958}
959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960void SurfaceFlinger::debugFlashRegions()
961{
Mathias Agopianf8b4b442010-06-14 21:20:00 -0700962 const DisplayHardware& hw(graphicPlane(0).displayHardware());
963 const uint32_t flags = hw.getFlags();
Mathias Agopian2e20bff2009-05-04 19:29:25 -0700964
Mathias Agopianf8b4b442010-06-14 21:20:00 -0700965 if (!((flags & DisplayHardware::SWAP_RECTANGLE) ||
966 (flags & DisplayHardware::BUFFER_PRESERVED))) {
967 const Region repaint((flags & DisplayHardware::PARTIAL_UPDATES) ?
968 mDirtyRegion.bounds() : hw.bounds());
969 composeSurfaces(repaint);
970 }
971
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972 glDisable(GL_BLEND);
973 glDisable(GL_DITHER);
974 glDisable(GL_SCISSOR_TEST);
975
Mathias Agopiandff8e582009-05-04 14:17:04 -0700976 static int toggle = 0;
977 toggle = 1 - toggle;
978 if (toggle) {
Mathias Agopianf8b4b442010-06-14 21:20:00 -0700979 glColor4f(1, 0, 1, 1);
Mathias Agopiandff8e582009-05-04 14:17:04 -0700980 } else {
Mathias Agopianf8b4b442010-06-14 21:20:00 -0700981 glColor4f(1, 1, 0, 1);
Mathias Agopiandff8e582009-05-04 14:17:04 -0700982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983
Mathias Agopian6158b1b2009-05-11 00:03:41 -0700984 Region::const_iterator it = mDirtyRegion.begin();
985 Region::const_iterator const end = mDirtyRegion.end();
986 while (it != end) {
987 const Rect& r = *it++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 GLfloat vertices[][2] = {
989 { r.left, r.top },
990 { r.left, r.bottom },
991 { r.right, r.bottom },
992 { r.right, r.top }
993 };
994 glVertexPointer(2, GL_FLOAT, 0, vertices);
995 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
996 }
Mathias Agopianf8b4b442010-06-14 21:20:00 -0700997
Mathias Agopian8c9687a2009-06-26 19:06:36 -0700998 if (mInvalidRegion.isEmpty()) {
999 mDirtyRegion.dump("mDirtyRegion");
1000 mInvalidRegion.dump("mInvalidRegion");
1001 }
1002 hw.flip(mInvalidRegion);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003
1004 if (mDebugRegion > 1)
Mathias Agopianf8b4b442010-06-14 21:20:00 -07001005 usleep(mDebugRegion * 1000);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006
1007 glEnable(GL_SCISSOR_TEST);
1008 //mDirtyRegion.dump("mDirtyRegion");
1009}
1010
1011void SurfaceFlinger::drawWormhole() const
1012{
1013 const Region region(mWormholeRegion.intersect(mDirtyRegion));
1014 if (region.isEmpty())
1015 return;
1016
1017 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1018 const int32_t width = hw.getWidth();
1019 const int32_t height = hw.getHeight();
1020
1021 glDisable(GL_BLEND);
1022 glDisable(GL_DITHER);
1023
1024 if (LIKELY(!mDebugBackground)) {
Mathias Agopianf8b4b442010-06-14 21:20:00 -07001025 glClearColor(0,0,0,0);
Mathias Agopian6158b1b2009-05-11 00:03:41 -07001026 Region::const_iterator it = region.begin();
1027 Region::const_iterator const end = region.end();
1028 while (it != end) {
1029 const Rect& r = *it++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030 const GLint sy = height - (r.top + r.height());
1031 glScissor(r.left, sy, r.width(), r.height());
1032 glClear(GL_COLOR_BUFFER_BIT);
1033 }
1034 } else {
1035 const GLshort vertices[][2] = { { 0, 0 }, { width, 0 },
1036 { width, height }, { 0, height } };
1037 const GLshort tcoords[][2] = { { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 } };
1038 glVertexPointer(2, GL_SHORT, 0, vertices);
1039 glTexCoordPointer(2, GL_SHORT, 0, tcoords);
1040 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
Michael I. Golde20a56d2010-09-15 15:46:24 -07001041#if defined(GL_OES_EGL_image_external)
Mathias Agopian781953d2010-06-25 18:02:21 -07001042 if (GLExtensions::getInstance().haveTextureExternal()) {
1043 glDisable(GL_TEXTURE_EXTERNAL_OES);
1044 }
Mathias Agopianf8b4b442010-06-14 21:20:00 -07001045#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001046 glEnable(GL_TEXTURE_2D);
1047 glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
1048 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1049 glMatrixMode(GL_TEXTURE);
1050 glLoadIdentity();
1051 glScalef(width*(1.0f/32.0f), height*(1.0f/32.0f), 1);
Mathias Agopian6158b1b2009-05-11 00:03:41 -07001052 Region::const_iterator it = region.begin();
1053 Region::const_iterator const end = region.end();
1054 while (it != end) {
1055 const Rect& r = *it++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 const GLint sy = height - (r.top + r.height());
1057 glScissor(r.left, sy, r.width(), r.height());
1058 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1059 }
1060 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
Mathias Agopian7bb843c2011-04-20 14:20:59 -07001061 glDisable(GL_TEXTURE_2D);
Mathias Agopian04a709e42010-12-14 18:38:36 -08001062 glLoadIdentity();
1063 glMatrixMode(GL_MODELVIEW);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064 }
1065}
1066
1067void SurfaceFlinger::debugShowFPS() const
1068{
1069 static int mFrameCount;
1070 static int mLastFrameCount = 0;
1071 static nsecs_t mLastFpsTime = 0;
1072 static float mFps = 0;
1073 mFrameCount++;
1074 nsecs_t now = systemTime();
1075 nsecs_t diff = now - mLastFpsTime;
1076 if (diff > ms2ns(250)) {
1077 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
1078 mLastFpsTime = now;
1079 mLastFrameCount = mFrameCount;
1080 }
1081 // XXX: mFPS has the value we want
1082 }
1083
Mathias Agopian1473f462009-04-10 14:24:30 -07001084status_t SurfaceFlinger::addLayer(const sp<LayerBase>& layer)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001085{
1086 Mutex::Autolock _l(mStateLock);
1087 addLayer_l(layer);
1088 setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
1089 return NO_ERROR;
1090}
1091
Mathias Agopian593c05c2010-06-02 23:28:45 -07001092status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer)
1093{
Mathias Agopian1efba9a2010-08-10 18:09:09 -07001094 ssize_t i = mCurrentState.layersSortedByZ.add(layer);
Mathias Agopian593c05c2010-06-02 23:28:45 -07001095 return (i < 0) ? status_t(i) : status_t(NO_ERROR);
1096}
1097
1098ssize_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
1099 const sp<LayerBaseClient>& lbc)
1100{
Mathias Agopian593c05c2010-06-02 23:28:45 -07001101 // attach this layer to the client
Mathias Agopian5fa7ad62011-05-03 16:21:41 -07001102 size_t name = client->attachLayer(lbc);
1103
1104 Mutex::Autolock _l(mStateLock);
Mathias Agopian593c05c2010-06-02 23:28:45 -07001105
1106 // add this layer to the current state list
1107 addLayer_l(lbc);
1108
Mathias Agopian5fa7ad62011-05-03 16:21:41 -07001109 return ssize_t(name);
Mathias Agopian593c05c2010-06-02 23:28:45 -07001110}
1111
Mathias Agopian1473f462009-04-10 14:24:30 -07001112status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113{
1114 Mutex::Autolock _l(mStateLock);
Mathias Agopian2d5ee252009-06-04 18:46:21 -07001115 status_t err = purgatorizeLayer_l(layer);
1116 if (err == NO_ERROR)
1117 setTransactionFlags(eTransactionNeeded);
1118 return err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119}
1120
Mathias Agopian1473f462009-04-10 14:24:30 -07001121status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122{
Mathias Agopian7623da42010-06-01 15:12:58 -07001123 sp<LayerBaseClient> lbc(layerBase->getLayerBaseClient());
1124 if (lbc != 0) {
Mathias Agopiand35c6662011-01-25 20:17:45 -08001125 mLayerMap.removeItem( lbc->getSurfaceBinder() );
Mathias Agopian7623da42010-06-01 15:12:58 -07001126 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
1128 if (index >= 0) {
Mathias Agopian1473f462009-04-10 14:24:30 -07001129 mLayersRemoved = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 return NO_ERROR;
1131 }
Mathias Agopian2d5ee252009-06-04 18:46:21 -07001132 return status_t(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001133}
1134
Mathias Agopian6cf0db22009-04-17 19:36:26 -07001135status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase)
1136{
Mathias Agopianf4dfe1b2011-01-14 17:37:42 -08001137 // First add the layer to the purgatory list, which makes sure it won't
1138 // go away, then remove it from the main list (through a transaction).
Mathias Agopian6cf0db22009-04-17 19:36:26 -07001139 ssize_t err = removeLayer_l(layerBase);
Mathias Agopianf4dfe1b2011-01-14 17:37:42 -08001140 if (err >= 0) {
1141 mLayerPurgatory.add(layerBase);
1142 }
Mathias Agopian2e4b68d2009-09-23 16:44:00 -07001143
Mathias Agopian0c4cec72009-10-02 18:12:30 -07001144 layerBase->onRemoved();
1145
Mathias Agopian2d5ee252009-06-04 18:46:21 -07001146 // it's possible that we don't find a layer, because it might
1147 // have been destroyed already -- this is not technically an error
Mathias Agopian593c05c2010-06-02 23:28:45 -07001148 // from the user because there is a race between Client::destroySurface(),
1149 // ~Client() and ~ISurface().
Mathias Agopian6cf0db22009-04-17 19:36:26 -07001150 return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err;
1151}
1152
Mathias Agopian593c05c2010-06-02 23:28:45 -07001153status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001154{
Mathias Agopian593c05c2010-06-02 23:28:45 -07001155 layer->forceVisibilityTransaction();
1156 setTransactionFlags(eTraversalNeeded);
1157 return NO_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158}
1159
Mathias Agopian6dcb1552011-05-03 17:04:02 -07001160uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t flags)
1161{
1162 return android_atomic_release_load(&mTransactionFlags);
1163}
1164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001165uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
1166{
1167 return android_atomic_and(~flags, &mTransactionFlags) & flags;
1168}
1169
Mathias Agopian898c4c92010-05-18 17:06:55 -07001170uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001171{
1172 uint32_t old = android_atomic_or(flags, &mTransactionFlags);
1173 if ((old & flags)==0) { // wake the server up
Mathias Agopian898c4c92010-05-18 17:06:55 -07001174 signalEvent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 }
1176 return old;
1177}
1178
1179void SurfaceFlinger::openGlobalTransaction()
1180{
1181 android_atomic_inc(&mTransactionCount);
1182}
1183
1184void SurfaceFlinger::closeGlobalTransaction()
1185{
1186 if (android_atomic_dec(&mTransactionCount) == 1) {
1187 signalEvent();
Mathias Agopian9779b222009-09-07 16:32:45 -07001188
Andreas Hubere3c01832010-08-16 08:49:37 -07001189 // if there is a transaction with a resize, wait for it to
Mathias Agopian9779b222009-09-07 16:32:45 -07001190 // take effect before returning.
1191 Mutex::Autolock _l(mStateLock);
1192 while (mResizeTransationPending) {
Mathias Agopian98a9c562009-09-30 14:42:13 -07001193 status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
1194 if (CC_UNLIKELY(err != NO_ERROR)) {
1195 // just in case something goes wrong in SF, return to the
1196 // called after a few seconds.
1197 LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
1198 mResizeTransationPending = false;
1199 break;
1200 }
Mathias Agopian9779b222009-09-07 16:32:45 -07001201 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001202 }
1203}
1204
1205status_t SurfaceFlinger::freezeDisplay(DisplayID dpy, uint32_t flags)
1206{
1207 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1208 return BAD_VALUE;
1209
1210 Mutex::Autolock _l(mStateLock);
1211 mCurrentState.freezeDisplay = 1;
1212 setTransactionFlags(eTransactionNeeded);
1213
1214 // flags is intended to communicate some sort of animation behavior
Mathias Agopianed81f222009-04-14 23:02:51 -07001215 // (for instance fading)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001216 return NO_ERROR;
1217}
1218
1219status_t SurfaceFlinger::unfreezeDisplay(DisplayID dpy, uint32_t flags)
1220{
1221 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1222 return BAD_VALUE;
1223
1224 Mutex::Autolock _l(mStateLock);
1225 mCurrentState.freezeDisplay = 0;
1226 setTransactionFlags(eTransactionNeeded);
1227
1228 // flags is intended to communicate some sort of animation behavior
Mathias Agopianed81f222009-04-14 23:02:51 -07001229 // (for instance fading)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001230 return NO_ERROR;
1231}
1232
Andreas Hubere3c01832010-08-16 08:49:37 -07001233int SurfaceFlinger::setOrientation(DisplayID dpy,
Mathias Agopianeb0c86e2009-03-27 18:11:38 -07001234 int orientation, uint32_t flags)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001235{
1236 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1237 return BAD_VALUE;
1238
1239 Mutex::Autolock _l(mStateLock);
1240 if (mCurrentState.orientation != orientation) {
1241 if (uint32_t(orientation)<=eOrientation270 || orientation==42) {
Mathias Agopianeb0c86e2009-03-27 18:11:38 -07001242 mCurrentState.orientationType = flags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 mCurrentState.orientation = orientation;
1244 setTransactionFlags(eTransactionNeeded);
1245 mTransactionCV.wait(mStateLock);
1246 } else {
1247 orientation = BAD_VALUE;
1248 }
1249 }
1250 return orientation;
1251}
1252
Mathias Agopian9638e5c2011-04-20 14:19:32 -07001253sp<ISurface> SurfaceFlinger::createSurface(
1254 ISurfaceComposerClient::surface_data_t* params,
1255 const String8& name,
1256 const sp<Client>& client,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001257 DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
1258 uint32_t flags)
1259{
Mathias Agopian1473f462009-04-10 14:24:30 -07001260 sp<LayerBaseClient> layer;
Mathias Agopian7bb843c2011-04-20 14:20:59 -07001261 sp<ISurface> surfaceHandle;
Mathias Agopian4d2dbeb2009-07-09 18:16:43 -07001262
1263 if (int32_t(w|h) < 0) {
1264 LOGE("createSurface() failed, w or h is negative (w=%d, h=%d)",
1265 int(w), int(h));
1266 return surfaceHandle;
1267 }
Andreas Hubere3c01832010-08-16 08:49:37 -07001268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001269 //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
Mathias Agopian7623da42010-06-01 15:12:58 -07001270 sp<Layer> normalLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001271 switch (flags & eFXSurfaceMask) {
1272 case eFXSurfaceNormal:
Mathias Agopiand2112302010-12-07 19:38:17 -08001273 normalLayer = createNormalSurface(client, d, w, h, flags, format);
1274 layer = normalLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001275 break;
1276 case eFXSurfaceBlur:
Mathias Agopianc3802d22010-12-08 17:13:19 -08001277 // for now we treat Blur as Dim, until we can implement it
1278 // efficiently.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001279 case eFXSurfaceDim:
Mathias Agopian593c05c2010-06-02 23:28:45 -07001280 layer = createDimSurface(client, d, w, h, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001281 break;
1282 }
1283
Mathias Agopian1473f462009-04-10 14:24:30 -07001284 if (layer != 0) {
Mathias Agopian593c05c2010-06-02 23:28:45 -07001285 layer->initStates(w, h, flags);
Mathias Agopian5d26c1e2010-03-01 16:09:43 -08001286 layer->setName(name);
Mathias Agopian593c05c2010-06-02 23:28:45 -07001287 ssize_t token = addClientLayer(client, layer);
Mathias Agopian7623da42010-06-01 15:12:58 -07001288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001289 surfaceHandle = layer->getSurface();
Andreas Hubere3c01832010-08-16 08:49:37 -07001290 if (surfaceHandle != 0) {
Mathias Agopian593c05c2010-06-02 23:28:45 -07001291 params->token = token;
Mathias Agopian7bb843c2011-04-20 14:20:59 -07001292 params->identity = layer->getIdentity();
Mathias Agopian18b6b492009-08-19 17:46:26 -07001293 params->width = w;
1294 params->height = h;
1295 params->format = format;
Mathias Agopian7623da42010-06-01 15:12:58 -07001296 if (normalLayer != 0) {
1297 Mutex::Autolock _l(mStateLock);
Mathias Agopian7bb843c2011-04-20 14:20:59 -07001298 mLayerMap.add(layer->getSurfaceBinder(), normalLayer);
Mathias Agopian7623da42010-06-01 15:12:58 -07001299 }
Mathias Agopian18b6b492009-08-19 17:46:26 -07001300 }
Mathias Agopian7623da42010-06-01 15:12:58 -07001301
Mathias Agopian593c05c2010-06-02 23:28:45 -07001302 setTransactionFlags(eTransactionNeeded);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303 }
1304
1305 return surfaceHandle;
1306}
1307
Mathias Agopian7623da42010-06-01 15:12:58 -07001308sp<Layer> SurfaceFlinger::createNormalSurface(
Mathias Agopian6edf5af2009-06-19 17:00:27 -07001309 const sp<Client>& client, DisplayID display,
Mathias Agopian593c05c2010-06-02 23:28:45 -07001310 uint32_t w, uint32_t h, uint32_t flags,
Mathias Agopian18b6b492009-08-19 17:46:26 -07001311 PixelFormat& format)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001312{
1313 // initialize the surfaces
1314 switch (format) { // TODO: take h/w into account
1315 case PIXEL_FORMAT_TRANSPARENT:
1316 case PIXEL_FORMAT_TRANSLUCENT:
1317 format = PIXEL_FORMAT_RGBA_8888;
1318 break;
1319 case PIXEL_FORMAT_OPAQUE:
Mathias Agopian4cfb3a62010-06-30 15:43:47 -07001320#ifdef NO_RGBX_8888
1321 format = PIXEL_FORMAT_RGB_565;
1322#else
Mathias Agopian59962ce2010-04-05 18:01:24 -07001323 format = PIXEL_FORMAT_RGBX_8888;
Mathias Agopian4cfb3a62010-06-30 15:43:47 -07001324#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001325 break;
1326 }
1327
Mathias Agopian4cfb3a62010-06-30 15:43:47 -07001328#ifdef NO_RGBX_8888
1329 if (format == PIXEL_FORMAT_RGBX_8888)
1330 format = PIXEL_FORMAT_RGBA_8888;
1331#endif
1332
Mathias Agopian593c05c2010-06-02 23:28:45 -07001333 sp<Layer> layer = new Layer(this, display, client);
Mathias Agopian6edf5af2009-06-19 17:00:27 -07001334 status_t err = layer->setBuffers(w, h, format, flags);
Mathias Agopian593c05c2010-06-02 23:28:45 -07001335 if (LIKELY(err != NO_ERROR)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001336 LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err));
Mathias Agopian1473f462009-04-10 14:24:30 -07001337 layer.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001338 }
1339 return layer;
1340}
1341
Mathias Agopian7623da42010-06-01 15:12:58 -07001342sp<LayerDim> SurfaceFlinger::createDimSurface(
Mathias Agopian6edf5af2009-06-19 17:00:27 -07001343 const sp<Client>& client, DisplayID display,
Mathias Agopian593c05c2010-06-02 23:28:45 -07001344 uint32_t w, uint32_t h, uint32_t flags)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001345{
Mathias Agopian593c05c2010-06-02 23:28:45 -07001346 sp<LayerDim> layer = new LayerDim(this, display, client);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001347 layer->initStates(w, h, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348 return layer;
1349}
1350
Mathias Agopian593c05c2010-06-02 23:28:45 -07001351status_t SurfaceFlinger::removeSurface(const sp<Client>& client, SurfaceID sid)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352{
Mathias Agopian6cf0db22009-04-17 19:36:26 -07001353 /*
1354 * called by the window manager, when a surface should be marked for
1355 * destruction.
Andreas Hubere3c01832010-08-16 08:49:37 -07001356 *
Mathias Agopiana3aa6c92009-04-22 15:23:34 -07001357 * The surface is removed from the current and drawing lists, but placed
1358 * in the purgatory queue, so it's not destroyed right-away (we need
1359 * to wait for all client's references to go away first).
Mathias Agopian6cf0db22009-04-17 19:36:26 -07001360 */
Mathias Agopian6cf0db22009-04-17 19:36:26 -07001361
Mathias Agopian248b5bd2009-09-10 19:41:18 -07001362 status_t err = NAME_NOT_FOUND;
Mathias Agopiana3aa6c92009-04-22 15:23:34 -07001363 Mutex::Autolock _l(mStateLock);
Mathias Agopian593c05c2010-06-02 23:28:45 -07001364 sp<LayerBaseClient> layer = client->getLayerUser(sid);
Mathias Agopian248b5bd2009-09-10 19:41:18 -07001365 if (layer != 0) {
1366 err = purgatorizeLayer_l(layer);
1367 if (err == NO_ERROR) {
Mathias Agopian248b5bd2009-09-10 19:41:18 -07001368 setTransactionFlags(eTransactionNeeded);
1369 }
Mathias Agopian6cf0db22009-04-17 19:36:26 -07001370 }
1371 return err;
1372}
1373
Mathias Agopian69608112011-05-19 15:38:14 -07001374status_t SurfaceFlinger::destroySurface(const wp<LayerBaseClient>& layer)
Mathias Agopian6cf0db22009-04-17 19:36:26 -07001375{
Mathias Agopian359140c2009-07-02 17:33:40 -07001376 // called by ~ISurface() when all references are gone
Mathias Agopian69608112011-05-19 15:38:14 -07001377 status_t err = NO_ERROR;
1378 sp<LayerBaseClient> l(layer.promote());
1379 if (l != NULL) {
1380 Mutex::Autolock _l(mStateLock);
1381 err = removeLayer_l(l);
1382 if (err == NAME_NOT_FOUND) {
1383 // The surface wasn't in the current list, which means it was
1384 // removed already, which means it is in the purgatory,
1385 // and need to be removed from there.
1386 ssize_t idx = mLayerPurgatory.remove(l);
1387 LOGE_IF(idx < 0,
1388 "layer=%p is not in the purgatory list", l.get());
Mathias Agopian6ead5d92009-04-20 19:39:12 -07001389 }
Mathias Agopian69608112011-05-19 15:38:14 -07001390 LOGE_IF(err<0 && err != NAME_NOT_FOUND,
1391 "error removing layer=%p (%s)", l.get(), strerror(-err));
1392 }
1393 return err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001394}
1395
1396status_t SurfaceFlinger::setClientState(
Mathias Agopian593c05c2010-06-02 23:28:45 -07001397 const sp<Client>& client,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001398 int32_t count,
1399 const layer_state_t* states)
1400{
1401 Mutex::Autolock _l(mStateLock);
1402 uint32_t flags = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001403 for (int i=0 ; i<count ; i++) {
Mathias Agopian593c05c2010-06-02 23:28:45 -07001404 const layer_state_t& s(states[i]);
1405 sp<LayerBaseClient> layer(client->getLayerUser(s.surface));
Mathias Agopian1473f462009-04-10 14:24:30 -07001406 if (layer != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407 const uint32_t what = s.what;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 if (what & ePositionChanged) {
1409 if (layer->setPosition(s.x, s.y))
1410 flags |= eTraversalNeeded;
1411 }
1412 if (what & eLayerChanged) {
Mathias Agopian1efba9a2010-08-10 18:09:09 -07001413 ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414 if (layer->setLayer(s.z)) {
Mathias Agopian1efba9a2010-08-10 18:09:09 -07001415 mCurrentState.layersSortedByZ.removeAt(idx);
1416 mCurrentState.layersSortedByZ.add(layer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 // we need traversal (state changed)
1418 // AND transaction (list changed)
1419 flags |= eTransactionNeeded|eTraversalNeeded;
1420 }
1421 }
1422 if (what & eSizeChanged) {
Mathias Agopian9779b222009-09-07 16:32:45 -07001423 if (layer->setSize(s.w, s.h)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 flags |= eTraversalNeeded;
Mathias Agopian9779b222009-09-07 16:32:45 -07001425 mResizeTransationPending = true;
1426 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 }
1428 if (what & eAlphaChanged) {
1429 if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
1430 flags |= eTraversalNeeded;
1431 }
1432 if (what & eMatrixChanged) {
1433 if (layer->setMatrix(s.matrix))
1434 flags |= eTraversalNeeded;
1435 }
1436 if (what & eTransparentRegionChanged) {
1437 if (layer->setTransparentRegionHint(s.transparentRegion))
1438 flags |= eTraversalNeeded;
1439 }
1440 if (what & eVisibilityChanged) {
1441 if (layer->setFlags(s.flags, s.mask))
1442 flags |= eTraversalNeeded;
1443 }
1444 }
1445 }
1446 if (flags) {
1447 setTransactionFlags(flags);
1448 }
1449 return NO_ERROR;
1450}
1451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452void SurfaceFlinger::screenReleased(int dpy)
1453{
1454 // this may be called by a signal handler, we can't do too much in here
1455 android_atomic_or(eConsoleReleased, &mConsoleSignals);
1456 signalEvent();
1457}
1458
1459void SurfaceFlinger::screenAcquired(int dpy)
1460{
1461 // this may be called by a signal handler, we can't do too much in here
1462 android_atomic_or(eConsoleAcquired, &mConsoleSignals);
1463 signalEvent();
1464}
1465
1466status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
1467{
Erik Gilling94720d72010-12-01 16:38:01 -08001468 const size_t SIZE = 4096;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 char buffer[SIZE];
1470 String8 result;
Mathias Agopian0dd593f2011-06-27 16:05:52 -07001471
1472 if (!PermissionCache::checkCallingPermission(sDump)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 snprintf(buffer, SIZE, "Permission Denial: "
1474 "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
1475 IPCThreadState::self()->getCallingPid(),
1476 IPCThreadState::self()->getCallingUid());
1477 result.append(buffer);
1478 } else {
Mathias Agopiana8d49172009-08-26 16:36:26 -07001479
1480 // figure out if we're stuck somewhere
1481 const nsecs_t now = systemTime();
1482 const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
1483 const nsecs_t inTransaction(mDebugInTransaction);
1484 nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0;
1485 nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0;
1486
1487 // Try to get the main lock, but don't insist if we can't
1488 // (this would indicate SF is stuck, but we want to be able to
1489 // print something in dumpsys).
1490 int retry = 3;
1491 while (mStateLock.tryLock()<0 && --retry>=0) {
1492 usleep(1000000);
1493 }
1494 const bool locked(retry >= 0);
1495 if (!locked) {
Andreas Hubere3c01832010-08-16 08:49:37 -07001496 snprintf(buffer, SIZE,
Mathias Agopiana8d49172009-08-26 16:36:26 -07001497 "SurfaceFlinger appears to be unresponsive, "
1498 "dumping anyways (no locks held)\n");
1499 result.append(buffer);
1500 }
1501
Mathias Agopian06a61e22011-01-19 16:15:53 -08001502 /*
1503 * Dump the visible layer list
1504 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
1506 const size_t count = currentLayers.size();
Mathias Agopian06a61e22011-01-19 16:15:53 -08001507 snprintf(buffer, SIZE, "Visible layers (count = %d)\n", count);
1508 result.append(buffer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 for (size_t i=0 ; i<count ; i++) {
Mathias Agopian9bce8732010-04-20 17:55:49 -07001510 const sp<LayerBase>& layer(currentLayers[i]);
1511 layer->dump(result, buffer, SIZE);
1512 const Layer::State& s(layer->drawingState());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 s.transparentRegion.dump(result, "transparentRegion");
1514 layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
1515 layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
1516 }
Mathias Agopian9bce8732010-04-20 17:55:49 -07001517
Mathias Agopian06a61e22011-01-19 16:15:53 -08001518 /*
1519 * Dump the layers in the purgatory
1520 */
1521
1522 const size_t purgatorySize = mLayerPurgatory.size();
1523 snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize);
1524 result.append(buffer);
1525 for (size_t i=0 ; i<purgatorySize ; i++) {
1526 const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i));
1527 layer->shortDump(result, buffer, SIZE);
1528 }
1529
1530 /*
1531 * Dump SurfaceFlinger global state
1532 */
1533
1534 snprintf(buffer, SIZE, "SurfaceFlinger global state\n");
1535 result.append(buffer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001536 mWormholeRegion.dump(result, "WormholeRegion");
1537 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1538 snprintf(buffer, SIZE,
1539 " display frozen: %s, freezeCount=%d, orientation=%d, canDraw=%d\n",
1540 mFreezeDisplay?"yes":"no", mFreezeCount,
1541 mCurrentState.orientation, hw.canDraw());
1542 result.append(buffer);
Mathias Agopiana8d49172009-08-26 16:36:26 -07001543 snprintf(buffer, SIZE,
1544 " last eglSwapBuffers() time: %f us\n"
1545 " last transaction time : %f us\n",
1546 mLastSwapBufferTime/1000.0, mLastTransactionTime/1000.0);
1547 result.append(buffer);
Mathias Agopian9bce8732010-04-20 17:55:49 -07001548
Mathias Agopiana8d49172009-08-26 16:36:26 -07001549 if (inSwapBuffersDuration || !locked) {
1550 snprintf(buffer, SIZE, " eglSwapBuffers time: %f us\n",
1551 inSwapBuffersDuration/1000.0);
1552 result.append(buffer);
1553 }
Mathias Agopian9bce8732010-04-20 17:55:49 -07001554
Mathias Agopiana8d49172009-08-26 16:36:26 -07001555 if (inTransactionDuration || !locked) {
1556 snprintf(buffer, SIZE, " transaction time: %f us\n",
1557 inTransactionDuration/1000.0);
1558 result.append(buffer);
1559 }
Mathias Agopian9bce8732010-04-20 17:55:49 -07001560
Mathias Agopian06a61e22011-01-19 16:15:53 -08001561 /*
1562 * Dump HWComposer state
1563 */
Mathias Agopian6a969242010-09-22 18:58:01 -07001564 HWComposer& hwc(hw.getHwComposer());
1565 snprintf(buffer, SIZE, " h/w composer %s and %s\n",
1566 hwc.initCheck()==NO_ERROR ? "present" : "not present",
1567 mDebugDisableHWC ? "disabled" : "enabled");
1568 result.append(buffer);
Mathias Agopian90da4dd2010-09-23 18:13:21 -07001569 hwc.dump(result, buffer, SIZE);
Mathias Agopian6a969242010-09-22 18:58:01 -07001570
Mathias Agopian06a61e22011-01-19 16:15:53 -08001571 /*
1572 * Dump gralloc state
1573 */
Mathias Agopian6950e422009-10-05 17:07:12 -07001574 const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
Mathias Agopian1473f462009-04-10 14:24:30 -07001575 alloc.dump(result);
Erik Gilling94720d72010-12-01 16:38:01 -08001576 hw.dump(result);
Mathias Agopiana8d49172009-08-26 16:36:26 -07001577
1578 if (locked) {
1579 mStateLock.unlock();
1580 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581 }
1582 write(fd, result.string(), result.size());
1583 return NO_ERROR;
1584}
1585
1586status_t SurfaceFlinger::onTransact(
1587 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1588{
1589 switch (code) {
1590 case CREATE_CONNECTION:
1591 case OPEN_GLOBAL_TRANSACTION:
1592 case CLOSE_GLOBAL_TRANSACTION:
1593 case SET_ORIENTATION:
1594 case FREEZE_DISPLAY:
1595 case UNFREEZE_DISPLAY:
1596 case BOOT_FINISHED:
Mathias Agopianaab758e2010-10-11 12:37:43 -07001597 case TURN_ELECTRON_BEAM_OFF:
Mathias Agopian2d2b8032010-10-12 16:05:48 -07001598 case TURN_ELECTRON_BEAM_ON:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 {
1600 // codes that require permission check
1601 IPCThreadState* ipc = IPCThreadState::self();
1602 const int pid = ipc->getCallingPid();
Mathias Agopian627e7b52009-05-21 19:21:59 -07001603 const int uid = ipc->getCallingUid();
Mathias Agopian0dd593f2011-06-27 16:05:52 -07001604 if ((uid != AID_GRAPHICS) &&
1605 !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
Mathias Agopian151e8592009-06-15 18:24:59 -07001606 LOGE("Permission Denial: "
1607 "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
1608 return PERMISSION_DENIED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001609 }
Mathias Agopianca5edbe2010-09-24 11:26:58 -07001610 break;
1611 }
1612 case CAPTURE_SCREEN:
1613 {
1614 // codes that require permission check
1615 IPCThreadState* ipc = IPCThreadState::self();
1616 const int pid = ipc->getCallingPid();
1617 const int uid = ipc->getCallingUid();
Mathias Agopian0dd593f2011-06-27 16:05:52 -07001618 if ((uid != AID_GRAPHICS) &&
1619 !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {
Mathias Agopianca5edbe2010-09-24 11:26:58 -07001620 LOGE("Permission Denial: "
1621 "can't read framebuffer pid=%d, uid=%d", pid, uid);
1622 return PERMISSION_DENIED;
1623 }
1624 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001625 }
1626 }
Mathias Agopianca5edbe2010-09-24 11:26:58 -07001627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001628 status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
1629 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
Mathias Agopian8c9687a2009-06-26 19:06:36 -07001630 CHECK_INTERFACE(ISurfaceComposer, data, reply);
Mathias Agopian0dd593f2011-06-27 16:05:52 -07001631 if (UNLIKELY(!PermissionCache::checkCallingPermission(sHardwareTest))) {
Mathias Agopian151e8592009-06-15 18:24:59 -07001632 IPCThreadState* ipc = IPCThreadState::self();
1633 const int pid = ipc->getCallingPid();
1634 const int uid = ipc->getCallingUid();
1635 LOGE("Permission Denial: "
1636 "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 return PERMISSION_DENIED;
1638 }
1639 int n;
1640 switch (code) {
Mathias Agopian17f638b2009-04-16 20:04:08 -07001641 case 1000: // SHOW_CPU, NOT SUPPORTED ANYMORE
Mathias Agopian04262e92010-09-13 22:57:58 -07001642 case 1001: // SHOW_FPS, NOT SUPPORTED ANYMORE
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 return NO_ERROR;
1644 case 1002: // SHOW_UPDATES
1645 n = data.readInt32();
1646 mDebugRegion = n ? n : (mDebugRegion ? 0 : 1);
1647 return NO_ERROR;
1648 case 1003: // SHOW_BACKGROUND
1649 n = data.readInt32();
1650 mDebugBackground = n ? 1 : 0;
1651 return NO_ERROR;
Mathias Agopian6a969242010-09-22 18:58:01 -07001652 case 1008: // toggle use of hw composer
1653 n = data.readInt32();
1654 mDebugDisableHWC = n ? 1 : 0;
Mathias Agopianfb4dcb12011-01-13 17:53:01 -08001655 invalidateHwcGeometry();
Mathias Agopian6a969242010-09-22 18:58:01 -07001656 // fall-through...
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 case 1004:{ // repaint everything
1658 Mutex::Autolock _l(mStateLock);
1659 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1660 mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe
1661 signalEvent();
Mathias Agopian9779b222009-09-07 16:32:45 -07001662 return NO_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001663 }
Mathias Agopian9779b222009-09-07 16:32:45 -07001664 case 1005:{ // force transaction
1665 setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
1666 return NO_ERROR;
1667 }
Mathias Agopian04262e92010-09-13 22:57:58 -07001668 case 1006:{ // enable/disable GraphicLog
1669 int enabled = data.readInt32();
1670 GraphicLog::getInstance().setEnabled(enabled);
1671 return NO_ERROR;
1672 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 case 1007: // set mFreezeCount
1674 mFreezeCount = data.readInt32();
Mathias Agopian0e449762009-12-01 17:23:28 -08001675 mFreezeDisplayTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 return NO_ERROR;
1677 case 1010: // interrogate.
Mathias Agopian17f638b2009-04-16 20:04:08 -07001678 reply->writeInt32(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 reply->writeInt32(0);
1680 reply->writeInt32(mDebugRegion);
1681 reply->writeInt32(mDebugBackground);
1682 return NO_ERROR;
1683 case 1013: {
1684 Mutex::Autolock _l(mStateLock);
1685 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1686 reply->writeInt32(hw.getPageFlipCount());
1687 }
1688 return NO_ERROR;
1689 }
1690 }
1691 return err;
1692}
1693
Mathias Agopianaab758e2010-10-11 12:37:43 -07001694// ---------------------------------------------------------------------------
1695
Mathias Agopian2d2b8032010-10-12 16:05:48 -07001696status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy,
1697 GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
Mathias Agopianaab758e2010-10-11 12:37:43 -07001698{
Mathias Agopianaab758e2010-10-11 12:37:43 -07001699 if (!GLExtensions::getInstance().haveFramebufferObject())
1700 return INVALID_OPERATION;
1701
1702 // get screen geometry
Mathias Agopianaab758e2010-10-11 12:37:43 -07001703 const DisplayHardware& hw(graphicPlane(dpy).displayHardware());
Mathias Agopianaab758e2010-10-11 12:37:43 -07001704 const uint32_t hw_w = hw.getWidth();
1705 const uint32_t hw_h = hw.getHeight();
Mathias Agopianaab758e2010-10-11 12:37:43 -07001706 GLfloat u = 1;
1707 GLfloat v = 1;
1708
1709 // make sure to clear all GL error flags
1710 while ( glGetError() != GL_NO_ERROR ) ;
1711
1712 // create a FBO
1713 GLuint name, tname;
1714 glGenTextures(1, &tname);
1715 glBindTexture(GL_TEXTURE_2D, tname);
Mathias Agopian2d2b8032010-10-12 16:05:48 -07001716 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
1717 hw_w, hw_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
Mathias Agopianaab758e2010-10-11 12:37:43 -07001718 if (glGetError() != GL_NO_ERROR) {
Mathias Agopiana6cd6d32010-10-14 12:19:37 -07001719 while ( glGetError() != GL_NO_ERROR ) ;
Mathias Agopianaab758e2010-10-11 12:37:43 -07001720 GLint tw = (2 << (31 - clz(hw_w)));
1721 GLint th = (2 << (31 - clz(hw_h)));
Mathias Agopian2d2b8032010-10-12 16:05:48 -07001722 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
1723 tw, th, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
Mathias Agopianaab758e2010-10-11 12:37:43 -07001724 u = GLfloat(hw_w) / tw;
1725 v = GLfloat(hw_h) / th;
1726 }
1727 glGenFramebuffersOES(1, &name);
1728 glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
Mathias Agopian2d2b8032010-10-12 16:05:48 -07001729 glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
1730 GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0);
Mathias Agopianaab758e2010-10-11 12:37:43 -07001731
Mathias Agopian2d2b8032010-10-12 16:05:48 -07001732 // redraw the screen entirely...
1733 glClearColor(0,0,0,1);
1734 glClear(GL_COLOR_BUFFER_BIT);
1735 const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
1736 const size_t count = layers.size();
1737 for (size_t i=0 ; i<count ; ++i) {
1738 const sp<LayerBase>& layer(layers[i]);
1739 layer->drawForSreenShot();
1740 }
1741
1742 // back to main framebuffer
1743 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
1744 glDisable(GL_SCISSOR_TEST);
1745 glDeleteFramebuffersOES(1, &name);
1746
1747 *textureName = tname;
1748 *uOut = u;
1749 *vOut = v;
1750 return NO_ERROR;
1751}
1752
1753// ---------------------------------------------------------------------------
1754
1755status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
1756{
1757 status_t result = PERMISSION_DENIED;
1758
1759 if (!GLExtensions::getInstance().haveFramebufferObject())
1760 return INVALID_OPERATION;
1761
1762 // get screen geometry
1763 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1764 const uint32_t hw_w = hw.getWidth();
1765 const uint32_t hw_h = hw.getHeight();
1766 const Region screenBounds(hw.bounds());
1767
1768 GLfloat u, v;
1769 GLuint tname;
1770 result = renderScreenToTextureLocked(0, &tname, &u, &v);
1771 if (result != NO_ERROR) {
1772 return result;
1773 }
1774
1775 GLfloat vtx[8];
1776 const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
Mathias Agopian2d2b8032010-10-12 16:05:48 -07001777 glBindTexture(GL_TEXTURE_2D, tname);
1778 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1779 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1780 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1781 glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
1782 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1783 glVertexPointer(2, GL_FLOAT, 0, vtx);
1784
1785 class s_curve_interpolator {
1786 const float nbFrames, s, v;
1787 public:
1788 s_curve_interpolator(int nbFrames, float s)
1789 : nbFrames(1.0f / (nbFrames-1)), s(s),
1790 v(1.0f + expf(-s + 0.5f*s)) {
1791 }
1792 float operator()(int f) {
1793 const float x = f * nbFrames;
1794 return ((1.0f/(1.0f + expf(-x*s + 0.5f*s))) - 0.5f) * v + 0.5f;
1795 }
1796 };
1797
1798 class v_stretch {
1799 const GLfloat hw_w, hw_h;
1800 public:
1801 v_stretch(uint32_t hw_w, uint32_t hw_h)
1802 : hw_w(hw_w), hw_h(hw_h) {
1803 }
1804 void operator()(GLfloat* vtx, float v) {
1805 const GLfloat w = hw_w + (hw_w * v);
1806 const GLfloat h = hw_h - (hw_h * v);
1807 const GLfloat x = (hw_w - w) * 0.5f;
1808 const GLfloat y = (hw_h - h) * 0.5f;
1809 vtx[0] = x; vtx[1] = y;
1810 vtx[2] = x; vtx[3] = y + h;
1811 vtx[4] = x + w; vtx[5] = y + h;
1812 vtx[6] = x + w; vtx[7] = y;
1813 }
1814 };
1815
1816 class h_stretch {
1817 const GLfloat hw_w, hw_h;
1818 public:
1819 h_stretch(uint32_t hw_w, uint32_t hw_h)
1820 : hw_w(hw_w), hw_h(hw_h) {
1821 }
1822 void operator()(GLfloat* vtx, float v) {
1823 const GLfloat w = hw_w - (hw_w * v);
1824 const GLfloat h = 1.0f;
1825 const GLfloat x = (hw_w - w) * 0.5f;
1826 const GLfloat y = (hw_h - h) * 0.5f;
1827 vtx[0] = x; vtx[1] = y;
1828 vtx[2] = x; vtx[3] = y + h;
1829 vtx[4] = x + w; vtx[5] = y + h;
1830 vtx[6] = x + w; vtx[7] = y;
1831 }
1832 };
1833
1834 // the full animation is 24 frames
1835 const int nbFrames = 12;
1836 s_curve_interpolator itr(nbFrames, 7.5f);
1837 s_curve_interpolator itg(nbFrames, 8.0f);
1838 s_curve_interpolator itb(nbFrames, 8.5f);
1839
1840 v_stretch vverts(hw_w, hw_h);
1841 glEnable(GL_BLEND);
1842 glBlendFunc(GL_ONE, GL_ONE);
1843 for (int i=0 ; i<nbFrames ; i++) {
1844 float x, y, w, h;
1845 const float vr = itr(i);
1846 const float vg = itg(i);
1847 const float vb = itb(i);
1848
1849 // clear screen
1850 glColorMask(1,1,1,1);
Mathias Agopianaab758e2010-10-11 12:37:43 -07001851 glClear(GL_COLOR_BUFFER_BIT);
Mathias Agopianaab758e2010-10-11 12:37:43 -07001852 glEnable(GL_TEXTURE_2D);
Mathias Agopianaab758e2010-10-11 12:37:43 -07001853
Mathias Agopian2d2b8032010-10-12 16:05:48 -07001854 // draw the red plane
1855 vverts(vtx, vr);
1856 glColorMask(1,0,0,1);
1857 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
Mathias Agopianaab758e2010-10-11 12:37:43 -07001858
Mathias Agopian2d2b8032010-10-12 16:05:48 -07001859 // draw the green plane
1860 vverts(vtx, vg);
1861 glColorMask(0,1,0,1);
1862 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
Mathias Agopianaab758e2010-10-11 12:37:43 -07001863
Mathias Agopian2d2b8032010-10-12 16:05:48 -07001864 // draw the blue plane
1865 vverts(vtx, vb);
1866 glColorMask(0,0,1,1);
1867 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
Mathias Agopianaab758e2010-10-11 12:37:43 -07001868
Mathias Agopian2d2b8032010-10-12 16:05:48 -07001869 // draw the white highlight (we use the last vertices)
Mathias Agopianaab758e2010-10-11 12:37:43 -07001870 glDisable(GL_TEXTURE_2D);
1871 glColorMask(1,1,1,1);
Mathias Agopian2d2b8032010-10-12 16:05:48 -07001872 glColor4f(vg, vg, vg, 1);
1873 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1874 hw.flip(screenBounds);
Mathias Agopianaab758e2010-10-11 12:37:43 -07001875 }
1876
Mathias Agopian2d2b8032010-10-12 16:05:48 -07001877 h_stretch hverts(hw_w, hw_h);
1878 glDisable(GL_BLEND);
1879 glDisable(GL_TEXTURE_2D);
1880 glColorMask(1,1,1,1);
1881 for (int i=0 ; i<nbFrames ; i++) {
1882 const float v = itg(i);
1883 hverts(vtx, v);
1884 glClear(GL_COLOR_BUFFER_BIT);
1885 glColor4f(1-v, 1-v, 1-v, 1);
1886 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1887 hw.flip(screenBounds);
1888 }
1889
1890 glColorMask(1,1,1,1);
1891 glEnable(GL_SCISSOR_TEST);
1892 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1893 glDeleteTextures(1, &tname);
Mathias Agopian7bb843c2011-04-20 14:20:59 -07001894 glDisable(GL_TEXTURE_2D);
Mathias Agopian2d2b8032010-10-12 16:05:48 -07001895 return NO_ERROR;
1896}
1897
1898status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
1899{
1900 status_t result = PERMISSION_DENIED;
1901
1902 if (!GLExtensions::getInstance().haveFramebufferObject())
1903 return INVALID_OPERATION;
1904
1905
1906 // get screen geometry
1907 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1908 const uint32_t hw_w = hw.getWidth();
1909 const uint32_t hw_h = hw.getHeight();
1910 const Region screenBounds(hw.bounds());
1911
1912 GLfloat u, v;
1913 GLuint tname;
1914 result = renderScreenToTextureLocked(0, &tname, &u, &v);
1915 if (result != NO_ERROR) {
1916 return result;
1917 }
1918
1919 // back to main framebuffer
1920 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
1921 glDisable(GL_SCISSOR_TEST);
1922
1923 GLfloat vtx[8];
1924 const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
Mathias Agopian2d2b8032010-10-12 16:05:48 -07001925 glBindTexture(GL_TEXTURE_2D, tname);
1926 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1927 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1928 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1929 glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
1930 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1931 glVertexPointer(2, GL_FLOAT, 0, vtx);
1932
1933 class s_curve_interpolator {
1934 const float nbFrames, s, v;
1935 public:
1936 s_curve_interpolator(int nbFrames, float s)
1937 : nbFrames(1.0f / (nbFrames-1)), s(s),
1938 v(1.0f + expf(-s + 0.5f*s)) {
1939 }
1940 float operator()(int f) {
1941 const float x = f * nbFrames;
1942 return ((1.0f/(1.0f + expf(-x*s + 0.5f*s))) - 0.5f) * v + 0.5f;
1943 }
1944 };
1945
1946 class v_stretch {
1947 const GLfloat hw_w, hw_h;
1948 public:
1949 v_stretch(uint32_t hw_w, uint32_t hw_h)
1950 : hw_w(hw_w), hw_h(hw_h) {
1951 }
1952 void operator()(GLfloat* vtx, float v) {
1953 const GLfloat w = hw_w + (hw_w * v);
1954 const GLfloat h = hw_h - (hw_h * v);
1955 const GLfloat x = (hw_w - w) * 0.5f;
1956 const GLfloat y = (hw_h - h) * 0.5f;
1957 vtx[0] = x; vtx[1] = y;
1958 vtx[2] = x; vtx[3] = y + h;
1959 vtx[4] = x + w; vtx[5] = y + h;
1960 vtx[6] = x + w; vtx[7] = y;
1961 }
1962 };
1963
1964 class h_stretch {
1965 const GLfloat hw_w, hw_h;
1966 public:
1967 h_stretch(uint32_t hw_w, uint32_t hw_h)
1968 : hw_w(hw_w), hw_h(hw_h) {
1969 }
1970 void operator()(GLfloat* vtx, float v) {
1971 const GLfloat w = hw_w - (hw_w * v);
1972 const GLfloat h = 1.0f;
1973 const GLfloat x = (hw_w - w) * 0.5f;
1974 const GLfloat y = (hw_h - h) * 0.5f;
1975 vtx[0] = x; vtx[1] = y;
1976 vtx[2] = x; vtx[3] = y + h;
1977 vtx[4] = x + w; vtx[5] = y + h;
1978 vtx[6] = x + w; vtx[7] = y;
1979 }
1980 };
1981
Mathias Agopiandfa08fb2010-10-14 12:33:07 -07001982 // the full animation is 12 frames
1983 int nbFrames = 8;
Mathias Agopian2d2b8032010-10-12 16:05:48 -07001984 s_curve_interpolator itr(nbFrames, 7.5f);
1985 s_curve_interpolator itg(nbFrames, 8.0f);
1986 s_curve_interpolator itb(nbFrames, 8.5f);
1987
1988 h_stretch hverts(hw_w, hw_h);
1989 glDisable(GL_BLEND);
1990 glDisable(GL_TEXTURE_2D);
1991 glColorMask(1,1,1,1);
1992 for (int i=nbFrames-1 ; i>=0 ; i--) {
1993 const float v = itg(i);
1994 hverts(vtx, v);
1995 glClear(GL_COLOR_BUFFER_BIT);
1996 glColor4f(1-v, 1-v, 1-v, 1);
1997 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1998 hw.flip(screenBounds);
1999 }
2000
Mathias Agopiandfa08fb2010-10-14 12:33:07 -07002001 nbFrames = 4;
Mathias Agopian2d2b8032010-10-12 16:05:48 -07002002 v_stretch vverts(hw_w, hw_h);
2003 glEnable(GL_BLEND);
2004 glBlendFunc(GL_ONE, GL_ONE);
2005 for (int i=nbFrames-1 ; i>=0 ; i--) {
2006 float x, y, w, h;
2007 const float vr = itr(i);
2008 const float vg = itg(i);
2009 const float vb = itb(i);
2010
2011 // clear screen
2012 glColorMask(1,1,1,1);
2013 glClear(GL_COLOR_BUFFER_BIT);
2014 glEnable(GL_TEXTURE_2D);
2015
2016 // draw the red plane
2017 vverts(vtx, vr);
2018 glColorMask(1,0,0,1);
2019 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
2020
2021 // draw the green plane
2022 vverts(vtx, vg);
2023 glColorMask(0,1,0,1);
2024 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
2025
2026 // draw the blue plane
2027 vverts(vtx, vb);
2028 glColorMask(0,0,1,1);
2029 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
2030
2031 hw.flip(screenBounds);
2032 }
2033
2034 glColorMask(1,1,1,1);
2035 glEnable(GL_SCISSOR_TEST);
2036 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
Mathias Agopianaab758e2010-10-11 12:37:43 -07002037 glDeleteTextures(1, &tname);
Mathias Agopian7bb843c2011-04-20 14:20:59 -07002038 glDisable(GL_TEXTURE_2D);
Mathias Agopianaab758e2010-10-11 12:37:43 -07002039
Mathias Agopian2d2b8032010-10-12 16:05:48 -07002040 return NO_ERROR;
2041}
2042
2043// ---------------------------------------------------------------------------
2044
Mathias Agopiand4e03f32010-10-14 14:54:06 -07002045status_t SurfaceFlinger::turnElectronBeamOffImplLocked(int32_t mode)
Mathias Agopian2d2b8032010-10-12 16:05:48 -07002046{
2047 DisplayHardware& hw(graphicPlane(0).editDisplayHardware());
2048 if (!hw.canDraw()) {
2049 // we're already off
2050 return NO_ERROR;
2051 }
Mathias Agopiand4e03f32010-10-14 14:54:06 -07002052 if (mode & ISurfaceComposer::eElectronBeamAnimationOff) {
2053 electronBeamOffAnimationImplLocked();
2054 }
2055
2056 // always clear the whole screen at the end of the animation
2057 glClearColor(0,0,0,1);
2058 glDisable(GL_SCISSOR_TEST);
2059 glClear(GL_COLOR_BUFFER_BIT);
2060 glEnable(GL_SCISSOR_TEST);
2061 hw.flip( Region(hw.bounds()) );
2062
Mathias Agopiana6cd6d32010-10-14 12:19:37 -07002063 hw.setCanDraw(false);
2064 return NO_ERROR;
Mathias Agopianaab758e2010-10-11 12:37:43 -07002065}
2066
2067status_t SurfaceFlinger::turnElectronBeamOff(int32_t mode)
2068{
Mathias Agopianaab758e2010-10-11 12:37:43 -07002069 class MessageTurnElectronBeamOff : public MessageBase {
2070 SurfaceFlinger* flinger;
Mathias Agopiand4e03f32010-10-14 14:54:06 -07002071 int32_t mode;
Mathias Agopianaab758e2010-10-11 12:37:43 -07002072 status_t result;
2073 public:
Mathias Agopiand4e03f32010-10-14 14:54:06 -07002074 MessageTurnElectronBeamOff(SurfaceFlinger* flinger, int32_t mode)
2075 : flinger(flinger), mode(mode), result(PERMISSION_DENIED) {
Mathias Agopianaab758e2010-10-11 12:37:43 -07002076 }
2077 status_t getResult() const {
2078 return result;
2079 }
2080 virtual bool handler() {
2081 Mutex::Autolock _l(flinger->mStateLock);
Mathias Agopiand4e03f32010-10-14 14:54:06 -07002082 result = flinger->turnElectronBeamOffImplLocked(mode);
Mathias Agopianaab758e2010-10-11 12:37:43 -07002083 return true;
2084 }
2085 };
2086
Mathias Agopiand4e03f32010-10-14 14:54:06 -07002087 sp<MessageBase> msg = new MessageTurnElectronBeamOff(this, mode);
Mathias Agopianaab758e2010-10-11 12:37:43 -07002088 status_t res = postMessageSync(msg);
2089 if (res == NO_ERROR) {
2090 res = static_cast<MessageTurnElectronBeamOff*>( msg.get() )->getResult();
Mathias Agopian2d2b8032010-10-12 16:05:48 -07002091
2092 // work-around: when the power-manager calls us we activate the
2093 // animation. eventually, the "on" animation will be called
2094 // by the power-manager itself
Mathias Agopiand4e03f32010-10-14 14:54:06 -07002095 mElectronBeamAnimationMode = mode;
Mathias Agopianaab758e2010-10-11 12:37:43 -07002096 }
2097 return res;
2098}
2099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002100// ---------------------------------------------------------------------------
Mathias Agopian7623da42010-06-01 15:12:58 -07002101
Mathias Agopiand4e03f32010-10-14 14:54:06 -07002102status_t SurfaceFlinger::turnElectronBeamOnImplLocked(int32_t mode)
Mathias Agopian2d2b8032010-10-12 16:05:48 -07002103{
2104 DisplayHardware& hw(graphicPlane(0).editDisplayHardware());
2105 if (hw.canDraw()) {
2106 // we're already on
2107 return NO_ERROR;
2108 }
Mathias Agopiand4e03f32010-10-14 14:54:06 -07002109 if (mode & ISurfaceComposer::eElectronBeamAnimationOn) {
2110 electronBeamOnAnimationImplLocked();
2111 }
Mathias Agopiana6cd6d32010-10-14 12:19:37 -07002112 hw.setCanDraw(true);
Mathias Agopian8b6a0542010-10-14 12:46:24 -07002113
2114 // make sure to redraw the whole screen when the animation is done
2115 mDirtyRegion.set(hw.bounds());
2116 signalEvent();
2117
Mathias Agopiana6cd6d32010-10-14 12:19:37 -07002118 return NO_ERROR;
Mathias Agopian2d2b8032010-10-12 16:05:48 -07002119}
2120
2121status_t SurfaceFlinger::turnElectronBeamOn(int32_t mode)
2122{
Mathias Agopian2d2b8032010-10-12 16:05:48 -07002123 class MessageTurnElectronBeamOn : public MessageBase {
2124 SurfaceFlinger* flinger;
Mathias Agopiand4e03f32010-10-14 14:54:06 -07002125 int32_t mode;
Mathias Agopian2d2b8032010-10-12 16:05:48 -07002126 status_t result;
2127 public:
Mathias Agopiand4e03f32010-10-14 14:54:06 -07002128 MessageTurnElectronBeamOn(SurfaceFlinger* flinger, int32_t mode)
2129 : flinger(flinger), mode(mode), result(PERMISSION_DENIED) {
Mathias Agopian2d2b8032010-10-12 16:05:48 -07002130 }
2131 status_t getResult() const {
2132 return result;
2133 }
2134 virtual bool handler() {
2135 Mutex::Autolock _l(flinger->mStateLock);
Mathias Agopiand4e03f32010-10-14 14:54:06 -07002136 result = flinger->turnElectronBeamOnImplLocked(mode);
Mathias Agopian2d2b8032010-10-12 16:05:48 -07002137 return true;
2138 }
2139 };
2140
Mathias Agopiand4e03f32010-10-14 14:54:06 -07002141 postMessageAsync( new MessageTurnElectronBeamOn(this, mode) );
Mathias Agopian2d2b8032010-10-12 16:05:48 -07002142 return NO_ERROR;
2143}
2144
2145// ---------------------------------------------------------------------------
2146
Mathias Agopian38ed2e32010-09-29 13:02:36 -07002147status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy,
2148 sp<IMemoryHeap>* heap,
2149 uint32_t* w, uint32_t* h, PixelFormat* f,
Mathias Agopian3dd25a62010-12-10 16:22:31 -08002150 uint32_t sw, uint32_t sh,
2151 uint32_t minLayerZ, uint32_t maxLayerZ)
Mathias Agopian38ed2e32010-09-29 13:02:36 -07002152{
2153 status_t result = PERMISSION_DENIED;
2154
2155 // only one display supported for now
2156 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
2157 return BAD_VALUE;
2158
Jamie Gennisf72606c2011-03-09 17:05:02 -08002159 // make sure none of the layers are protected
2160 const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
2161 const size_t count = layers.size();
2162 for (size_t i=0 ; i<count ; ++i) {
2163 const sp<LayerBase>& layer(layers[i]);
2164 const uint32_t z = layer->drawingState().z;
2165 if (z >= minLayerZ && z <= maxLayerZ) {
2166 if (layer->isProtected()) {
2167 return INVALID_OPERATION;
2168 }
2169 }
2170 }
2171
Mathias Agopian38ed2e32010-09-29 13:02:36 -07002172 if (!GLExtensions::getInstance().haveFramebufferObject())
2173 return INVALID_OPERATION;
2174
2175 // get screen geometry
2176 const DisplayHardware& hw(graphicPlane(dpy).displayHardware());
2177 const uint32_t hw_w = hw.getWidth();
2178 const uint32_t hw_h = hw.getHeight();
2179
2180 if ((sw > hw_w) || (sh > hw_h))
2181 return BAD_VALUE;
2182
2183 sw = (!sw) ? hw_w : sw;
2184 sh = (!sh) ? hw_h : sh;
2185 const size_t size = sw * sh * 4;
2186
Mathias Agopian32ae0942011-03-02 18:45:50 -08002187 //LOGD("screenshot: sw=%d, sh=%d, minZ=%d, maxZ=%d",
2188 // sw, sh, minLayerZ, maxLayerZ);
Mathias Agopiancd2cfb62011-01-16 14:05:02 -08002189
Mathias Agopian38ed2e32010-09-29 13:02:36 -07002190 // make sure to clear all GL error flags
2191 while ( glGetError() != GL_NO_ERROR ) ;
2192
2193 // create a FBO
2194 GLuint name, tname;
2195 glGenRenderbuffersOES(1, &tname);
2196 glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname);
2197 glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, sw, sh);
2198 glGenFramebuffersOES(1, &name);
2199 glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
2200 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
2201 GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname);
2202
2203 GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
Mathias Agopiancd2cfb62011-01-16 14:05:02 -08002204
Mathias Agopian38ed2e32010-09-29 13:02:36 -07002205 if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
2206
2207 // invert everything, b/c glReadPixel() below will invert the FB
2208 glViewport(0, 0, sw, sh);
Mathias Agopian1c4e4fc02010-12-16 18:46:17 -08002209 glScissor(0, 0, sw, sh);
Mathias Agopian38ed2e32010-09-29 13:02:36 -07002210 glMatrixMode(GL_PROJECTION);
2211 glPushMatrix();
2212 glLoadIdentity();
2213 glOrthof(0, hw_w, 0, hw_h, 0, 1);
2214 glMatrixMode(GL_MODELVIEW);
2215
2216 // redraw the screen entirely...
2217 glClearColor(0,0,0,1);
2218 glClear(GL_COLOR_BUFFER_BIT);
Mathias Agopian1c4e4fc02010-12-16 18:46:17 -08002219
Mathias Agopian38ed2e32010-09-29 13:02:36 -07002220 for (size_t i=0 ; i<count ; ++i) {
2221 const sp<LayerBase>& layer(layers[i]);
Mathias Agopian3dd25a62010-12-10 16:22:31 -08002222 const uint32_t z = layer->drawingState().z;
2223 if (z >= minLayerZ && z <= maxLayerZ) {
2224 layer->drawForSreenShot();
2225 }
Mathias Agopian38ed2e32010-09-29 13:02:36 -07002226 }
2227
2228 // XXX: this is needed on tegra
2229 glScissor(0, 0, sw, sh);
2230
2231 // check for errors and return screen capture
2232 if (glGetError() != GL_NO_ERROR) {
2233 // error while rendering
2234 result = INVALID_OPERATION;
2235 } else {
2236 // allocate shared memory large enough to hold the
2237 // screen capture
2238 sp<MemoryHeapBase> base(
2239 new MemoryHeapBase(size, 0, "screen-capture") );
2240 void* const ptr = base->getBase();
2241 if (ptr) {
2242 // capture the screen with glReadPixels()
2243 glReadPixels(0, 0, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, ptr);
2244 if (glGetError() == GL_NO_ERROR) {
2245 *heap = base;
2246 *w = sw;
2247 *h = sh;
2248 *f = PIXEL_FORMAT_RGBA_8888;
2249 result = NO_ERROR;
2250 }
2251 } else {
2252 result = NO_MEMORY;
2253 }
2254 }
Mathias Agopian38ed2e32010-09-29 13:02:36 -07002255 glEnable(GL_SCISSOR_TEST);
2256 glViewport(0, 0, hw_w, hw_h);
2257 glMatrixMode(GL_PROJECTION);
2258 glPopMatrix();
2259 glMatrixMode(GL_MODELVIEW);
Mathias Agopian38ed2e32010-09-29 13:02:36 -07002260 } else {
2261 result = BAD_VALUE;
2262 }
2263
2264 // release FBO resources
2265 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
2266 glDeleteRenderbuffersOES(1, &tname);
2267 glDeleteFramebuffersOES(1, &name);
Mathias Agopiana6b8c1c2010-12-15 14:41:59 -08002268
2269 hw.compositionComplete();
2270
Mathias Agopian32ae0942011-03-02 18:45:50 -08002271 // LOGD("screenshot: result = %s", result<0 ? strerror(result) : "OK");
Mathias Agopiancd2cfb62011-01-16 14:05:02 -08002272
Mathias Agopian38ed2e32010-09-29 13:02:36 -07002273 return result;
2274}
2275
2276
Mathias Agopianca5edbe2010-09-24 11:26:58 -07002277status_t SurfaceFlinger::captureScreen(DisplayID dpy,
2278 sp<IMemoryHeap>* heap,
Mathias Agopian38ed2e32010-09-29 13:02:36 -07002279 uint32_t* width, uint32_t* height, PixelFormat* format,
Mathias Agopian3dd25a62010-12-10 16:22:31 -08002280 uint32_t sw, uint32_t sh,
2281 uint32_t minLayerZ, uint32_t maxLayerZ)
Mathias Agopianca5edbe2010-09-24 11:26:58 -07002282{
2283 // only one display supported for now
2284 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
2285 return BAD_VALUE;
2286
2287 if (!GLExtensions::getInstance().haveFramebufferObject())
2288 return INVALID_OPERATION;
2289
2290 class MessageCaptureScreen : public MessageBase {
2291 SurfaceFlinger* flinger;
2292 DisplayID dpy;
2293 sp<IMemoryHeap>* heap;
2294 uint32_t* w;
2295 uint32_t* h;
2296 PixelFormat* f;
Mathias Agopian38ed2e32010-09-29 13:02:36 -07002297 uint32_t sw;
2298 uint32_t sh;
Mathias Agopian3dd25a62010-12-10 16:22:31 -08002299 uint32_t minLayerZ;
2300 uint32_t maxLayerZ;
Mathias Agopianca5edbe2010-09-24 11:26:58 -07002301 status_t result;
2302 public:
2303 MessageCaptureScreen(SurfaceFlinger* flinger, DisplayID dpy,
Mathias Agopian38ed2e32010-09-29 13:02:36 -07002304 sp<IMemoryHeap>* heap, uint32_t* w, uint32_t* h, PixelFormat* f,
Mathias Agopian3dd25a62010-12-10 16:22:31 -08002305 uint32_t sw, uint32_t sh,
2306 uint32_t minLayerZ, uint32_t maxLayerZ)
Mathias Agopianca5edbe2010-09-24 11:26:58 -07002307 : flinger(flinger), dpy(dpy),
Mathias Agopian3dd25a62010-12-10 16:22:31 -08002308 heap(heap), w(w), h(h), f(f), sw(sw), sh(sh),
2309 minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
2310 result(PERMISSION_DENIED)
Mathias Agopianca5edbe2010-09-24 11:26:58 -07002311 {
2312 }
2313 status_t getResult() const {
2314 return result;
2315 }
2316 virtual bool handler() {
2317 Mutex::Autolock _l(flinger->mStateLock);
2318
2319 // if we have secure windows, never allow the screen capture
2320 if (flinger->mSecureFrameBuffer)
2321 return true;
2322
Mathias Agopian38ed2e32010-09-29 13:02:36 -07002323 result = flinger->captureScreenImplLocked(dpy,
Mathias Agopian3dd25a62010-12-10 16:22:31 -08002324 heap, w, h, f, sw, sh, minLayerZ, maxLayerZ);
Mathias Agopianca5edbe2010-09-24 11:26:58 -07002325
Mathias Agopianca5edbe2010-09-24 11:26:58 -07002326 return true;
2327 }
2328 };
2329
2330 sp<MessageBase> msg = new MessageCaptureScreen(this,
Mathias Agopian3dd25a62010-12-10 16:22:31 -08002331 dpy, heap, width, height, format, sw, sh, minLayerZ, maxLayerZ);
Mathias Agopianca5edbe2010-09-24 11:26:58 -07002332 status_t res = postMessageSync(msg);
2333 if (res == NO_ERROR) {
2334 res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult();
2335 }
2336 return res;
2337}
2338
2339// ---------------------------------------------------------------------------
2340
Mathias Agopian7623da42010-06-01 15:12:58 -07002341sp<Layer> SurfaceFlinger::getLayer(const sp<ISurface>& sur) const
2342{
2343 sp<Layer> result;
2344 Mutex::Autolock _l(mStateLock);
2345 result = mLayerMap.valueFor( sur->asBinder() ).promote();
2346 return result;
2347}
2348
2349// ---------------------------------------------------------------------------
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002350
Mathias Agopian593c05c2010-06-02 23:28:45 -07002351Client::Client(const sp<SurfaceFlinger>& flinger)
Mathias Agopian7623da42010-06-01 15:12:58 -07002352 : mFlinger(flinger), mNameGenerator(1)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002353{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354}
2355
Mathias Agopian593c05c2010-06-02 23:28:45 -07002356Client::~Client()
2357{
Mathias Agopian593c05c2010-06-02 23:28:45 -07002358 const size_t count = mLayers.size();
2359 for (size_t i=0 ; i<count ; i++) {
2360 sp<LayerBaseClient> layer(mLayers.valueAt(i).promote());
2361 if (layer != 0) {
2362 mFlinger->removeLayer(layer);
2363 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002364 }
2365}
2366
Mathias Agopian593c05c2010-06-02 23:28:45 -07002367status_t Client::initCheck() const {
Mathias Agopian7623da42010-06-01 15:12:58 -07002368 return NO_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369}
Mathias Agopian1473f462009-04-10 14:24:30 -07002370
Mathias Agopian5fa7ad62011-05-03 16:21:41 -07002371size_t Client::attachLayer(const sp<LayerBaseClient>& layer)
Mathias Agopian593c05c2010-06-02 23:28:45 -07002372{
Mathias Agopian5fa7ad62011-05-03 16:21:41 -07002373 Mutex::Autolock _l(mLock);
2374 size_t name = mNameGenerator++;
Mathias Agopian593c05c2010-06-02 23:28:45 -07002375 mLayers.add(name, layer);
2376 return name;
2377}
2378
Mathias Agopian7623da42010-06-01 15:12:58 -07002379void Client::detachLayer(const LayerBaseClient* layer)
Mathias Agopian593c05c2010-06-02 23:28:45 -07002380{
Mathias Agopian5fa7ad62011-05-03 16:21:41 -07002381 Mutex::Autolock _l(mLock);
Mathias Agopian593c05c2010-06-02 23:28:45 -07002382 // we do a linear search here, because this doesn't happen often
2383 const size_t count = mLayers.size();
2384 for (size_t i=0 ; i<count ; i++) {
2385 if (mLayers.valueAt(i) == layer) {
2386 mLayers.removeItemsAt(i, 1);
2387 break;
2388 }
2389 }
2390}
Mathias Agopian5fa7ad62011-05-03 16:21:41 -07002391sp<LayerBaseClient> Client::getLayerUser(int32_t i) const
2392{
2393 Mutex::Autolock _l(mLock);
Mathias Agopian1473f462009-04-10 14:24:30 -07002394 sp<LayerBaseClient> lbc;
Mathias Agopian5fa7ad62011-05-03 16:21:41 -07002395 wp<LayerBaseClient> layer(mLayers.valueFor(i));
Mathias Agopian593c05c2010-06-02 23:28:45 -07002396 if (layer != 0) {
2397 lbc = layer.promote();
2398 LOGE_IF(lbc==0, "getLayerUser(name=%d) is dead", int(i));
Mathias Agopian1473f462009-04-10 14:24:30 -07002399 }
2400 return lbc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002401}
2402
Mathias Agopian7bb843c2011-04-20 14:20:59 -07002403
2404status_t Client::onTransact(
2405 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2406{
2407 // these must be checked
2408 IPCThreadState* ipc = IPCThreadState::self();
2409 const int pid = ipc->getCallingPid();
2410 const int uid = ipc->getCallingUid();
2411 const int self_pid = getpid();
2412 if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) {
2413 // we're called from a different process, do the real check
Mathias Agopian0dd593f2011-06-27 16:05:52 -07002414 if (!PermissionCache::checkCallingPermission(sAccessSurfaceFlinger))
Mathias Agopian7bb843c2011-04-20 14:20:59 -07002415 {
2416 LOGE("Permission Denial: "
2417 "can't openGlobalTransaction pid=%d, uid=%d", pid, uid);
2418 return PERMISSION_DENIED;
2419 }
2420 }
2421 return BnSurfaceComposerClient::onTransact(code, data, reply, flags);
Mathias Agopian7623da42010-06-01 15:12:58 -07002422}
Mathias Agopian7bb843c2011-04-20 14:20:59 -07002423
2424
Mathias Agopian593c05c2010-06-02 23:28:45 -07002425sp<ISurface> Client::createSurface(
Mathias Agopian9638e5c2011-04-20 14:19:32 -07002426 ISurfaceComposerClient::surface_data_t* params,
Mathias Agopian7623da42010-06-01 15:12:58 -07002427 const String8& name,
2428 DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002429 uint32_t flags)
2430{
Mathias Agopian7bb843c2011-04-20 14:20:59 -07002431 /*
2432 * createSurface must be called from the GL thread so that it can
2433 * have access to the GL context.
2434 */
2435
2436 class MessageCreateSurface : public MessageBase {
2437 sp<ISurface> result;
2438 SurfaceFlinger* flinger;
2439 ISurfaceComposerClient::surface_data_t* params;
2440 Client* client;
2441 const String8& name;
2442 DisplayID display;
2443 uint32_t w, h;
2444 PixelFormat format;
2445 uint32_t flags;
2446 public:
2447 MessageCreateSurface(SurfaceFlinger* flinger,
2448 ISurfaceComposerClient::surface_data_t* params,
2449 const String8& name, Client* client,
2450 DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
2451 uint32_t flags)
2452 : flinger(flinger), params(params), client(client), name(name),
2453 display(display), w(w), h(h), format(format), flags(flags)
2454 {
2455 }
2456 sp<ISurface> getResult() const { return result; }
2457 virtual bool handler() {
2458 result = flinger->createSurface(params, name, client,
2459 display, w, h, format, flags);
2460 return true;
2461 }
2462 };
2463
2464 sp<MessageBase> msg = new MessageCreateSurface(mFlinger.get(),
2465 params, name, this, display, w, h, format, flags);
2466 mFlinger->postMessageSync(msg);
2467 return static_cast<MessageCreateSurface*>( msg.get() )->getResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002468}
Mathias Agopian593c05c2010-06-02 23:28:45 -07002469status_t Client::destroySurface(SurfaceID sid) {
2470 return mFlinger->removeSurface(this, sid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002471}
Mathias Agopian593c05c2010-06-02 23:28:45 -07002472status_t Client::setState(int32_t count, const layer_state_t* states) {
2473 return mFlinger->setClientState(this, count, states);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002474}
2475
2476// ---------------------------------------------------------------------------
2477
Jamie Gennisf7acf162011-01-12 18:30:40 -08002478GraphicBufferAlloc::GraphicBufferAlloc() {}
2479
2480GraphicBufferAlloc::~GraphicBufferAlloc() {}
2481
2482sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,
2483 PixelFormat format, uint32_t usage) {
2484 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
2485 status_t err = graphicBuffer->initCheck();
Mathias Agopian7bb843c2011-04-20 14:20:59 -07002486 if (err != 0 || graphicBuffer->handle == 0) {
2487 GraphicBuffer::dumpAllocationsToSystemLog();
2488 LOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
2489 "failed (%s), handle=%p",
2490 w, h, strerror(-err), graphicBuffer->handle);
Jamie Gennisf7acf162011-01-12 18:30:40 -08002491 return 0;
2492 }
Jamie Gennisf7acf162011-01-12 18:30:40 -08002493 return graphicBuffer;
2494}
2495
Jamie Gennisf7acf162011-01-12 18:30:40 -08002496// ---------------------------------------------------------------------------
2497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002498GraphicPlane::GraphicPlane()
2499 : mHw(0)
2500{
2501}
2502
2503GraphicPlane::~GraphicPlane() {
2504 delete mHw;
2505}
2506
2507bool GraphicPlane::initialized() const {
2508 return mHw ? true : false;
2509}
2510
Mathias Agopian66c77a52010-02-08 15:49:35 -08002511int GraphicPlane::getWidth() const {
2512 return mWidth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002513}
2514
Mathias Agopian66c77a52010-02-08 15:49:35 -08002515int GraphicPlane::getHeight() const {
2516 return mHeight;
2517}
2518
2519void GraphicPlane::setDisplayHardware(DisplayHardware *hw)
2520{
2521 mHw = hw;
2522
2523 // initialize the display orientation transform.
2524 // it's a constant that should come from the display driver.
2525 int displayOrientation = ISurfaceComposer::eOrientationDefault;
2526 char property[PROPERTY_VALUE_MAX];
2527 if (property_get("ro.sf.hwrotation", property, NULL) > 0) {
2528 //displayOrientation
2529 switch (atoi(property)) {
2530 case 90:
2531 displayOrientation = ISurfaceComposer::eOrientation90;
2532 break;
2533 case 270:
2534 displayOrientation = ISurfaceComposer::eOrientation270;
2535 break;
2536 }
2537 }
2538
2539 const float w = hw->getWidth();
2540 const float h = hw->getHeight();
2541 GraphicPlane::orientationToTransfrom(displayOrientation, w, h,
2542 &mDisplayTransform);
2543 if (displayOrientation & ISurfaceComposer::eOrientationSwapMask) {
2544 mDisplayWidth = h;
2545 mDisplayHeight = w;
2546 } else {
2547 mDisplayWidth = w;
2548 mDisplayHeight = h;
2549 }
2550
2551 setOrientation(ISurfaceComposer::eOrientationDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552}
2553
2554status_t GraphicPlane::orientationToTransfrom(
2555 int orientation, int w, int h, Transform* tr)
Mathias Agopian8c20ca32010-02-22 03:15:57 -08002556{
2557 uint32_t flags = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002558 switch (orientation) {
2559 case ISurfaceComposer::eOrientationDefault:
Mathias Agopian8c20ca32010-02-22 03:15:57 -08002560 flags = Transform::ROT_0;
2561 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 case ISurfaceComposer::eOrientation90:
Mathias Agopian8c20ca32010-02-22 03:15:57 -08002563 flags = Transform::ROT_90;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002564 break;
2565 case ISurfaceComposer::eOrientation180:
Mathias Agopian8c20ca32010-02-22 03:15:57 -08002566 flags = Transform::ROT_180;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002567 break;
2568 case ISurfaceComposer::eOrientation270:
Mathias Agopian8c20ca32010-02-22 03:15:57 -08002569 flags = Transform::ROT_270;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 break;
2571 default:
2572 return BAD_VALUE;
2573 }
Mathias Agopian8c20ca32010-02-22 03:15:57 -08002574 tr->set(flags, w, h);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002575 return NO_ERROR;
2576}
2577
2578status_t GraphicPlane::setOrientation(int orientation)
2579{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002580 // If the rotation can be handled in hardware, this is where
2581 // the magic should happen.
Mathias Agopian66c77a52010-02-08 15:49:35 -08002582
2583 const DisplayHardware& hw(displayHardware());
2584 const float w = mDisplayWidth;
2585 const float h = mDisplayHeight;
2586 mWidth = int(w);
2587 mHeight = int(h);
2588
2589 Transform orientationTransform;
Mathias Agopian8c20ca32010-02-22 03:15:57 -08002590 GraphicPlane::orientationToTransfrom(orientation, w, h,
2591 &orientationTransform);
2592 if (orientation & ISurfaceComposer::eOrientationSwapMask) {
2593 mWidth = int(h);
2594 mHeight = int(w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002595 }
Mathias Agopian8c20ca32010-02-22 03:15:57 -08002596
Mathias Agopian3552f532009-03-27 17:58:20 -07002597 mOrientation = orientation;
Mathias Agopian66c77a52010-02-08 15:49:35 -08002598 mGlobalTransform = mDisplayTransform * orientationTransform;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002599 return NO_ERROR;
2600}
2601
2602const DisplayHardware& GraphicPlane::displayHardware() const {
2603 return *mHw;
2604}
2605
Mathias Agopianaab758e2010-10-11 12:37:43 -07002606DisplayHardware& GraphicPlane::editDisplayHardware() {
2607 return *mHw;
2608}
2609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002610const Transform& GraphicPlane::transform() const {
2611 return mGlobalTransform;
2612}
2613
Mathias Agopian1473f462009-04-10 14:24:30 -07002614EGLDisplay GraphicPlane::getEGLDisplay() const {
2615 return mHw->getEGLDisplay();
2616}
2617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002618// ---------------------------------------------------------------------------
2619
2620}; // namespace android