blob: 7150fa1d014a599200580a346e13272c4889ad15 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-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
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080017#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080019#include <stdlib.h>
20#include <stdint.h>
21#include <sys/types.h>
Mathias Agopian13127d82013-03-05 17:47:11 -080022#include <math.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080023
Mathias Agopiana67932f2011-04-20 14:20:59 -070024#include <cutils/compiler.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070025#include <cutils/native_handle.h>
Mathias Agopiana67932f2011-04-20 14:20:59 -070026#include <cutils/properties.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080027
28#include <utils/Errors.h>
29#include <utils/Log.h>
30#include <utils/StopWatch.h>
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080031#include <utils/Trace.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080032
Mathias Agopian3330b202009-10-05 17:07:12 -070033#include <ui/GraphicBuffer.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080034#include <ui/PixelFormat.h>
Mathias Agopian9cce3252010-02-09 17:46:37 -080035
Mathias Agopian90ac7992012-02-25 18:48:35 -080036#include <gui/Surface.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080037
38#include "clz.h"
Mathias Agopian3e25fd82013-04-22 17:52:16 +020039#include "Colorizer.h"
Mathias Agopian0f2f5ff2012-07-31 23:09:07 -070040#include "DisplayDevice.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080041#include "Layer.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080042#include "SurfaceFlinger.h"
Mathias Agopiana67932f2011-04-20 14:20:59 -070043#include "SurfaceTextureLayer.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080044
Mathias Agopian1b031492012-06-20 17:51:20 -070045#include "DisplayHardware/HWComposer.h"
46
Mathias Agopian875d8e12013-06-07 15:35:48 -070047#include "RenderEngine/RenderEngine.h"
48
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080049#define DEBUG_RESIZE 0
50
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080051namespace android {
52
53// ---------------------------------------------------------------------------
54
Mathias Agopian13127d82013-03-05 17:47:11 -080055int32_t Layer::sSequence = 1;
56
Mathias Agopian4d9b8222013-03-12 17:11:48 -070057Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
58 const String8& name, uint32_t w, uint32_t h, uint32_t flags)
Mathias Agopian13127d82013-03-05 17:47:11 -080059 : contentDirty(false),
60 sequence(uint32_t(android_atomic_inc(&sSequence))),
61 mFlinger(flinger),
Mathias Agopiana67932f2011-04-20 14:20:59 -070062 mTextureName(-1U),
Mathias Agopian13127d82013-03-05 17:47:11 -080063 mPremultipliedAlpha(true),
64 mName("unnamed"),
65 mDebug(false),
66 mFormat(PIXEL_FORMAT_NONE),
Mathias Agopian13127d82013-03-05 17:47:11 -080067 mOpaqueLayer(true),
68 mTransactionFlags(0),
Mathias Agopiana67932f2011-04-20 14:20:59 -070069 mQueuedFrames(0),
70 mCurrentTransform(0),
Mathias Agopian933389f2011-07-18 16:15:08 -070071 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
Mathias Agopiana67932f2011-04-20 14:20:59 -070072 mCurrentOpacity(true),
Mathias Agopian4d143ee2012-02-23 20:05:39 -080073 mRefreshPending(false),
Mathias Agopian82d7ab62012-01-19 18:34:40 -080074 mFrameLatencyNeeded(false),
Mathias Agopian13127d82013-03-05 17:47:11 -080075 mFiltering(false),
76 mNeedsFiltering(false),
Mathias Agopian5cdc8992013-08-13 20:51:23 -070077 mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2),
Mathias Agopianb7e930d2010-06-01 15:12:58 -070078 mSecure(false),
Mathias Agopian13127d82013-03-05 17:47:11 -080079 mProtectedByApp(false),
80 mHasSurface(false),
81 mClientRef(client)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080082{
Mathias Agopiana67932f2011-04-20 14:20:59 -070083 mCurrentCrop.makeInvalid();
Mathias Agopian3f844832013-08-07 21:24:32 -070084 mFlinger->getRenderEngine().genTextures(1, &mTextureName);
Mathias Agopian49457ac2013-08-14 18:20:17 -070085 mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);
Mathias Agopian4d9b8222013-03-12 17:11:48 -070086
87 uint32_t layerFlags = 0;
88 if (flags & ISurfaceComposerClient::eHidden)
89 layerFlags = layer_state_t::eLayerHidden;
90
91 if (flags & ISurfaceComposerClient::eNonPremultiplied)
92 mPremultipliedAlpha = false;
93
94 mName = name;
95
96 mCurrentState.active.w = w;
97 mCurrentState.active.h = h;
98 mCurrentState.active.crop.makeInvalid();
99 mCurrentState.z = 0;
100 mCurrentState.alpha = 0xFF;
101 mCurrentState.layerStack = 0;
102 mCurrentState.flags = layerFlags;
103 mCurrentState.sequence = 0;
104 mCurrentState.transform.set(0, 0);
105 mCurrentState.requested = mCurrentState.active;
106
107 // drawing state & current state are identical
108 mDrawingState = mCurrentState;
Jamie Gennis6547ff42013-07-16 20:12:42 -0700109
110 nsecs_t displayPeriod =
111 flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
112 mFrameTracker.setDisplayRefreshPeriod(displayPeriod);
Jamie Gennise8696a42012-01-15 18:54:57 -0800113}
114
Mathias Agopian3f844832013-08-07 21:24:32 -0700115void Layer::onFirstRef() {
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800116 // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
Mathias Agopiandb89edc2013-08-02 01:40:18 -0700117 mBufferQueue = new SurfaceTextureLayer(mFlinger);
Mathias Agopian3f844832013-08-07 21:24:32 -0700118 mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mBufferQueue, mTextureName);
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800119 mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
120 mSurfaceFlingerConsumer->setFrameAvailableListener(this);
Mathias Agopian4d9b8222013-03-12 17:11:48 -0700121 mSurfaceFlingerConsumer->setName(mName);
Daniel Lamb2675792012-02-23 14:35:13 -0800122
Mathias Agopian7f42a9c2012-04-23 20:00:16 -0700123#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
124#warning "disabling triple buffering"
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800125 mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
Mathias Agopian7f42a9c2012-04-23 20:00:16 -0700126#else
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800127 mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3);
Mathias Agopian303d5382012-02-05 01:49:16 -0800128#endif
Andy McFadden69052052012-09-14 16:10:11 -0700129
Mathias Agopian84300952012-11-21 16:02:13 -0800130 const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
131 updateTransformHint(hw);
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700132}
133
Mathias Agopian4d9b8222013-03-12 17:11:48 -0700134Layer::~Layer() {
Mathias Agopian13127d82013-03-05 17:47:11 -0800135 sp<Client> c(mClientRef.promote());
136 if (c != 0) {
137 c->detachLayer(this);
138 }
Mathias Agopian921e6ac2012-07-23 23:11:29 -0700139 mFlinger->deleteTextureAsync(mTextureName);
Jamie Gennis6547ff42013-07-16 20:12:42 -0700140 mFrameTracker.logAndResetStats(mName);
Mathias Agopian96f08192010-06-02 23:28:45 -0700141}
142
Mathias Agopian13127d82013-03-05 17:47:11 -0800143// ---------------------------------------------------------------------------
144// callbacks
145// ---------------------------------------------------------------------------
146
147void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw,
148 HWComposer::HWCLayerInterface* layer) {
149 if (layer) {
150 layer->onDisplayed();
Jesse Hall13f01cb2013-03-20 11:37:21 -0700151 mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence());
Mathias Agopian13127d82013-03-05 17:47:11 -0800152 }
153}
154
Igor Murashkina4a31492012-10-29 13:36:11 -0700155void Layer::onFrameAvailable() {
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700156 android_atomic_inc(&mQueuedFrames);
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800157 mFlinger->signalLayerUpdate();
Mathias Agopian579b3f82010-06-08 19:54:15 -0700158}
159
Mathias Agopian67106042013-03-14 19:18:13 -0700160// called with SurfaceFlinger::mStateLock from the drawing thread after
161// the layer has been remove from the current state list (and just before
162// it's removed from the drawing state list)
Mathias Agopian13127d82013-03-05 17:47:11 -0800163void Layer::onRemoved() {
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800164 mSurfaceFlingerConsumer->abandon();
Mathias Agopian48d819a2009-09-10 19:41:18 -0700165}
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700166
Mathias Agopian13127d82013-03-05 17:47:11 -0800167// ---------------------------------------------------------------------------
168// set-up
169// ---------------------------------------------------------------------------
170
Mathias Agopian1eae0ee2013-06-05 16:59:15 -0700171const String8& Layer::getName() const {
Mathias Agopian13127d82013-03-05 17:47:11 -0800172 return mName;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800173}
174
Mathias Agopianf9d93272009-06-19 17:00:27 -0700175status_t Layer::setBuffers( uint32_t w, uint32_t h,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800176 PixelFormat format, uint32_t flags)
177{
Mathias Agopianca99fb82010-04-14 16:43:44 -0700178 uint32_t const maxSurfaceDims = min(
Mathias Agopiana4912602012-07-12 14:25:33 -0700179 mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
Mathias Agopianca99fb82010-04-14 16:43:44 -0700180
181 // never allow a surface larger than what our underlying GL implementation
182 // can handle.
183 if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
Mathias Agopianff615cc2012-02-24 14:58:36 -0800184 ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700185 return BAD_VALUE;
186 }
187
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700188 mFormat = format;
Mathias Agopianeff062c2010-08-25 14:59:15 -0700189
Mathias Agopian3165cc22012-08-08 19:42:09 -0700190 mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false;
191 mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
192 mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700193 mCurrentOpacity = getOpacityForFormat(format);
194
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800195 mSurfaceFlingerConsumer->setDefaultBufferSize(w, h);
196 mSurfaceFlingerConsumer->setDefaultBufferFormat(format);
197 mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700198
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800199 return NO_ERROR;
200}
201
Mathias Agopian4d9b8222013-03-12 17:11:48 -0700202sp<IBinder> Layer::getHandle() {
Mathias Agopian13127d82013-03-05 17:47:11 -0800203 Mutex::Autolock _l(mLock);
204
205 LOG_ALWAYS_FATAL_IF(mHasSurface,
Mathias Agopian4d9b8222013-03-12 17:11:48 -0700206 "Layer::getHandle() has already been called");
Mathias Agopian13127d82013-03-05 17:47:11 -0800207
208 mHasSurface = true;
Mathias Agopian4d9b8222013-03-12 17:11:48 -0700209
210 /*
211 * The layer handle is just a BBinder object passed to the client
212 * (remote process) -- we don't keep any reference on our side such that
213 * the dtor is called when the remote side let go of its reference.
214 *
215 * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
216 * this layer when the handle is destroyed.
217 */
218
219 class Handle : public BBinder, public LayerCleaner {
220 wp<const Layer> mOwner;
221 public:
222 Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
223 : LayerCleaner(flinger, layer), mOwner(layer) {
224 }
225 };
226
227 return new Handle(mFlinger, this);
Mathias Agopian13127d82013-03-05 17:47:11 -0800228}
229
Mathias Agopiandb89edc2013-08-02 01:40:18 -0700230sp<IGraphicBufferProducer> Layer::getBufferQueue() const {
231 return mBufferQueue;
Mathias Agopian4d9b8222013-03-12 17:11:48 -0700232}
233
Mathias Agopian13127d82013-03-05 17:47:11 -0800234// ---------------------------------------------------------------------------
235// h/w composer set-up
236// ---------------------------------------------------------------------------
237
Mathias Agopiana8bca8d2013-02-27 22:03:19 -0800238Rect Layer::getContentCrop() const {
239 // this is the crop rectangle that applies to the buffer
240 // itself (as opposed to the window)
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700241 Rect crop;
242 if (!mCurrentCrop.isEmpty()) {
Mathias Agopiana8bca8d2013-02-27 22:03:19 -0800243 // if the buffer crop is defined, we use that
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700244 crop = mCurrentCrop;
Mathias Agopiana8bca8d2013-02-27 22:03:19 -0800245 } else if (mActiveBuffer != NULL) {
246 // otherwise we use the whole buffer
247 crop = mActiveBuffer->getBounds();
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700248 } else {
Mathias Agopiana8bca8d2013-02-27 22:03:19 -0800249 // if we don't have a buffer yet, we use an empty/invalid crop
Mathias Agopian4fec8732012-06-29 14:12:52 -0700250 crop.makeInvalid();
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700251 }
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700252 return crop;
253}
254
Mathias Agopianf3e85d42013-05-10 18:01:12 -0700255static Rect reduce(const Rect& win, const Region& exclude) {
256 if (CC_LIKELY(exclude.isEmpty())) {
257 return win;
258 }
259 if (exclude.isRect()) {
260 return win.reduce(exclude.getBounds());
261 }
262 return Region(win).subtract(exclude).getBounds();
263}
264
Mathias Agopian13127d82013-03-05 17:47:11 -0800265Rect Layer::computeBounds() const {
Mathias Agopian1eae0ee2013-06-05 16:59:15 -0700266 const Layer::State& s(getDrawingState());
Mathias Agopian13127d82013-03-05 17:47:11 -0800267 Rect win(s.active.w, s.active.h);
268 if (!s.active.crop.isEmpty()) {
269 win.intersect(s.active.crop, &win);
270 }
Mathias Agopian6c7f25a2013-05-09 20:37:10 -0700271 // subtract the transparent region and snap to the bounds
Mathias Agopianf3e85d42013-05-10 18:01:12 -0700272 return reduce(win, s.activeTransparentRegion);
Mathias Agopian13127d82013-03-05 17:47:11 -0800273}
274
Mathias Agopian6b442672013-07-09 21:24:52 -0700275FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
Mathias Agopian13127d82013-03-05 17:47:11 -0800276 // the content crop is the area of the content that gets scaled to the
277 // layer's size.
Mathias Agopian6b442672013-07-09 21:24:52 -0700278 FloatRect crop(getContentCrop());
Mathias Agopian13127d82013-03-05 17:47:11 -0800279
280 // the active.crop is the area of the window that gets cropped, but not
281 // scaled in any ways.
Mathias Agopian1eae0ee2013-06-05 16:59:15 -0700282 const State& s(getDrawingState());
Mathias Agopian13127d82013-03-05 17:47:11 -0800283
284 // apply the projection's clipping to the window crop in
285 // layerstack space, and convert-back to layer space.
Mathias Agopian6b442672013-07-09 21:24:52 -0700286 // if there are no window scaling involved, this operation will map to full
287 // pixels in the buffer.
288 // FIXME: the 3 lines below can produce slightly incorrect clipping when we have
289 // a viewport clipping and a window transform. we should use floating point to fix this.
Mathias Agopian13127d82013-03-05 17:47:11 -0800290 Rect activeCrop(s.transform.transform(s.active.crop));
291 activeCrop.intersect(hw->getViewport(), &activeCrop);
292 activeCrop = s.transform.inverse().transform(activeCrop);
293
294 // paranoia: make sure the window-crop is constrained in the
295 // window's bounds
296 activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop);
297
Mathias Agopianf3e85d42013-05-10 18:01:12 -0700298 // subtract the transparent region and snap to the bounds
299 activeCrop = reduce(activeCrop, s.activeTransparentRegion);
300
Mathias Agopian13127d82013-03-05 17:47:11 -0800301 if (!activeCrop.isEmpty()) {
302 // Transform the window crop to match the buffer coordinate system,
303 // which means using the inverse of the current transform set on the
304 // SurfaceFlingerConsumer.
Mathias Agopian6b442672013-07-09 21:24:52 -0700305 uint32_t invTransform = mCurrentTransform;
Mathias Agopian13127d82013-03-05 17:47:11 -0800306 int winWidth = s.active.w;
307 int winHeight = s.active.h;
308 if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
309 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
310 NATIVE_WINDOW_TRANSFORM_FLIP_H;
311 winWidth = s.active.h;
312 winHeight = s.active.w;
313 }
314 const Rect winCrop = activeCrop.transform(
315 invTransform, s.active.w, s.active.h);
316
Mathias Agopian6b442672013-07-09 21:24:52 -0700317 // below, crop is intersected with winCrop expressed in crop's coordinate space
318 float xScale = crop.getWidth() / float(winWidth);
319 float yScale = crop.getHeight() / float(winHeight);
Mathias Agopian13127d82013-03-05 17:47:11 -0800320
Mathias Agopian6b442672013-07-09 21:24:52 -0700321 float insetL = winCrop.left * xScale;
322 float insetT = winCrop.top * yScale;
323 float insetR = (winWidth - winCrop.right ) * xScale;
324 float insetB = (winHeight - winCrop.bottom) * yScale;
Mathias Agopian13127d82013-03-05 17:47:11 -0800325
326 crop.left += insetL;
327 crop.top += insetT;
328 crop.right -= insetR;
329 crop.bottom -= insetB;
330 }
331 return crop;
332}
333
Mathias Agopian4fec8732012-06-29 14:12:52 -0700334void Layer::setGeometry(
Mathias Agopian42977342012-08-05 00:40:46 -0700335 const sp<const DisplayDevice>& hw,
Mathias Agopian4fec8732012-06-29 14:12:52 -0700336 HWComposer::HWCLayerInterface& layer)
Mathias Agopiana350ff92010-08-10 17:14:02 -0700337{
Mathias Agopian13127d82013-03-05 17:47:11 -0800338 layer.setDefaultState();
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700339
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700340 // enable this layer
341 layer.setSkip(false);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700342
Jamie Gennisdd3cb842012-10-19 18:19:11 -0700343 if (isSecure() && !hw->isSecure()) {
344 layer.setSkip(true);
345 }
346
Mathias Agopian13127d82013-03-05 17:47:11 -0800347 // this gives us only the "orientation" component of the transform
Mathias Agopian1eae0ee2013-06-05 16:59:15 -0700348 const State& s(getDrawingState());
Mathias Agopian13127d82013-03-05 17:47:11 -0800349 if (!isOpaque() || s.alpha != 0xFF) {
350 layer.setBlending(mPremultipliedAlpha ?
351 HWC_BLENDING_PREMULT :
352 HWC_BLENDING_COVERAGE);
353 }
354
355 // apply the layer's transform, followed by the display's global transform
356 // here we're guaranteed that the layer's transform preserves rects
357 Rect frame(s.transform.transform(computeBounds()));
358 frame.intersect(hw->getViewport(), &frame);
359 const Transform& tr(hw->getTransform());
360 layer.setFrame(tr.transform(frame));
361 layer.setCrop(computeCrop(hw));
Mathias Agopian9f8386e2013-01-29 18:56:42 -0800362 layer.setPlaneAlpha(s.alpha);
363
Mathias Agopian29a367b2011-07-12 14:51:45 -0700364 /*
365 * Transformations are applied in this order:
366 * 1) buffer orientation/flip/mirror
367 * 2) state transformation (window manager)
368 * 3) layer orientation (screen orientation)
369 * (NOTE: the matrices are multiplied in reverse order)
370 */
371
372 const Transform bufferOrientation(mCurrentTransform);
Mathias Agopian13127d82013-03-05 17:47:11 -0800373 const Transform transform(tr * s.transform * bufferOrientation);
Mathias Agopian29a367b2011-07-12 14:51:45 -0700374
375 // this gives us only the "orientation" component of the transform
Mathias Agopian13127d82013-03-05 17:47:11 -0800376 const uint32_t orientation = transform.getOrientation();
377 if (orientation & Transform::ROT_INVALID) {
378 // we can only handle simple transformation
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700379 layer.setSkip(true);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700380 } else {
Mathias Agopian13127d82013-03-05 17:47:11 -0800381 layer.setTransform(orientation);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700382 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700383}
384
Mathias Agopian42977342012-08-05 00:40:46 -0700385void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700386 HWComposer::HWCLayerInterface& layer) {
Mathias Agopian13127d82013-03-05 17:47:11 -0800387 // we have to set the visible region on every frame because
388 // we currently free it during onLayerDisplayed(), which is called
389 // after HWComposer::commit() -- every frame.
390 // Apply this display's projection's viewport to the visible region
391 // before giving it to the HWC HAL.
392 const Transform& tr = hw->getTransform();
393 Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
394 layer.setVisibleRegionScreen(visible);
395
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700396 // NOTE: buffer can be NULL if the client never drew into this
397 // layer yet, or if we ran out of memory
Mathias Agopian71e83e12012-09-04 20:25:39 -0700398 layer.setBuffer(mActiveBuffer);
Jesse Hallc5c5a142012-07-02 16:49:28 -0700399}
Jesse Halldc5b4852012-06-29 15:21:18 -0700400
Mathias Agopian42977342012-08-05 00:40:46 -0700401void Layer::setAcquireFence(const sp<const DisplayDevice>& hw,
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700402 HWComposer::HWCLayerInterface& layer) {
Jesse Hallc5c5a142012-07-02 16:49:28 -0700403 int fenceFd = -1;
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700404
405 // TODO: there is a possible optimization here: we only need to set the
406 // acquire fence the first time a new buffer is acquired on EACH display.
407
408 if (layer.getCompositionType() == HWC_OVERLAY) {
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800409 sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence();
Jamie Gennis1df8c342012-12-20 14:05:45 -0800410 if (fence->isValid()) {
Jesse Hallc5c5a142012-07-02 16:49:28 -0700411 fenceFd = fence->dup();
Jesse Halldc5b4852012-06-29 15:21:18 -0700412 if (fenceFd == -1) {
413 ALOGW("failed to dup layer fence, skipping sync: %d", errno);
414 }
Jesse Halldc5b4852012-06-29 15:21:18 -0700415 }
Jesse Halldc5b4852012-06-29 15:21:18 -0700416 }
Jesse Hallc5c5a142012-07-02 16:49:28 -0700417 layer.setAcquireFenceFd(fenceFd);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700418}
419
Mathias Agopian13127d82013-03-05 17:47:11 -0800420// ---------------------------------------------------------------------------
421// drawing...
422// ---------------------------------------------------------------------------
423
424void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) const {
425 onDraw(hw, clip);
426}
427
428void Layer::draw(const sp<const DisplayDevice>& hw) {
429 onDraw( hw, Region(hw->bounds()) );
430}
431
Mathias Agopian42977342012-08-05 00:40:46 -0700432void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800433{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800434 ATRACE_CALL();
435
Mathias Agopiana67932f2011-04-20 14:20:59 -0700436 if (CC_UNLIKELY(mActiveBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800437 // the texture has not been created yet, this Layer has
Mathias Agopian179169e2010-05-06 20:21:45 -0700438 // in fact never been drawn into. This happens frequently with
439 // SurfaceView because the WindowManager can't know when the client
440 // has drawn the first time.
441
442 // If there is nothing under us, we paint the screen in black, otherwise
443 // we just skip this update.
444
445 // figure out if there is something below us
446 Region under;
Mathias Agopianf7ae69d2011-08-23 12:34:29 -0700447 const SurfaceFlinger::LayerVector& drawingLayers(
448 mFlinger->mDrawingState.layersSortedByZ);
Mathias Agopian179169e2010-05-06 20:21:45 -0700449 const size_t count = drawingLayers.size();
450 for (size_t i=0 ; i<count ; ++i) {
Mathias Agopian13127d82013-03-05 17:47:11 -0800451 const sp<Layer>& layer(drawingLayers[i]);
452 if (layer.get() == static_cast<Layer const*>(this))
Mathias Agopian179169e2010-05-06 20:21:45 -0700453 break;
Mathias Agopian42977342012-08-05 00:40:46 -0700454 under.orSelf( hw->getTransform().transform(layer->visibleRegion) );
Mathias Agopian179169e2010-05-06 20:21:45 -0700455 }
456 // if not everything below us is covered, we plug the holes!
457 Region holes(clip.subtract(under));
458 if (!holes.isEmpty()) {
Mathias Agopian1b031492012-06-20 17:51:20 -0700459 clearWithOpenGL(hw, holes, 0, 0, 0, 1);
Mathias Agopian179169e2010-05-06 20:21:45 -0700460 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800461 return;
462 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700463
Andy McFadden97eba892012-12-11 15:21:45 -0800464 // Bind the current buffer to the GL texture, and wait for it to be
465 // ready for us to draw into.
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800466 status_t err = mSurfaceFlingerConsumer->bindTextureImage();
467 if (err != NO_ERROR) {
Andy McFadden97eba892012-12-11 15:21:45 -0800468 ALOGW("onDraw: bindTextureImage failed (err=%d)", err);
Jesse Halldc5b4852012-06-29 15:21:18 -0700469 // Go ahead and draw the buffer anyway; no matter what we do the screen
470 // is probably going to have something visibly wrong.
471 }
472
Jamie Gennisdd3cb842012-10-19 18:19:11 -0700473 bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure());
474
Mathias Agopian875d8e12013-06-07 15:35:48 -0700475 RenderEngine& engine(mFlinger->getRenderEngine());
476
Jamie Gennisdd3cb842012-10-19 18:19:11 -0700477 if (!blackOutLayer) {
Jamie Genniscbb1a952012-05-08 17:05:52 -0700478 // TODO: we could be more subtle with isFixedSize()
Mathias Agopianeba8c682012-09-19 23:14:45 -0700479 const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize();
Jamie Genniscbb1a952012-05-08 17:05:52 -0700480
481 // Query the texture matrix given our current filtering mode.
482 float textureMatrix[16];
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800483 mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering);
484 mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix);
Jamie Genniscbb1a952012-05-08 17:05:52 -0700485
486 // Set things up for texturing.
Mathias Agopian49457ac2013-08-14 18:20:17 -0700487 mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
488 mTexture.setFiltering(useFiltering);
489 mTexture.setMatrix(textureMatrix);
490
491 engine.setupLayerTexturing(mTexture);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700492 } else {
Mathias Agopian875d8e12013-06-07 15:35:48 -0700493 engine.setupLayerBlackedOut();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700494 }
Mathias Agopian1b031492012-06-20 17:51:20 -0700495 drawWithOpenGL(hw, clip);
Mathias Agopian875d8e12013-06-07 15:35:48 -0700496 engine.disableTexturing();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800497}
498
Mathias Agopian13127d82013-03-05 17:47:11 -0800499
500void Layer::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
Mathias Agopian3f844832013-08-07 21:24:32 -0700501 float red, float green, float blue, float alpha) const
Mathias Agopian13127d82013-03-05 17:47:11 -0800502{
Mathias Agopian5cdc8992013-08-13 20:51:23 -0700503 computeGeometry(hw, mMesh);
504 mFlinger->getRenderEngine().fillWithColor(mMesh, red, green, blue, alpha);
Mathias Agopian13127d82013-03-05 17:47:11 -0800505}
506
507void Layer::clearWithOpenGL(
508 const sp<const DisplayDevice>& hw, const Region& clip) const {
509 clearWithOpenGL(hw, clip, 0,0,0,0);
510}
511
512void Layer::drawWithOpenGL(
513 const sp<const DisplayDevice>& hw, const Region& clip) const {
514 const uint32_t fbHeight = hw->getHeight();
Mathias Agopian1eae0ee2013-06-05 16:59:15 -0700515 const State& s(getDrawingState());
Mathias Agopian13127d82013-03-05 17:47:11 -0800516
Mathias Agopian5cdc8992013-08-13 20:51:23 -0700517 computeGeometry(hw, mMesh);
Mathias Agopian13127d82013-03-05 17:47:11 -0800518
Mathias Agopian13127d82013-03-05 17:47:11 -0800519 /*
520 * NOTE: the way we compute the texture coordinates here produces
521 * different results than when we take the HWC path -- in the later case
522 * the "source crop" is rounded to texel boundaries.
523 * This can produce significantly different results when the texture
524 * is scaled by a large amount.
525 *
526 * The GL code below is more logical (imho), and the difference with
527 * HWC is due to a limitation of the HWC API to integers -- a question
528 * is suspend is wether we should ignore this problem or revert to
529 * GL composition when a buffer scaling is applied (maybe with some
530 * minimal value)? Or, we could make GL behave like HWC -- but this feel
531 * like more of a hack.
532 */
533 const Rect win(computeBounds());
534
Mathias Agopian3f844832013-08-07 21:24:32 -0700535 float left = float(win.left) / float(s.active.w);
536 float top = float(win.top) / float(s.active.h);
537 float right = float(win.right) / float(s.active.w);
538 float bottom = float(win.bottom) / float(s.active.h);
Mathias Agopian13127d82013-03-05 17:47:11 -0800539
Mathias Agopian875d8e12013-06-07 15:35:48 -0700540 // TODO: we probably want to generate the texture coords with the mesh
541 // here we assume that we only have 4 vertices
Mathias Agopian5cdc8992013-08-13 20:51:23 -0700542 Mesh::VertexArray texCoords(mMesh.getTexCoordArray());
543 texCoords[0].s = left;
544 texCoords[0].t = 1.0f - top;
545 texCoords[1].s = left;
546 texCoords[1].t = 1.0f - bottom;
547 texCoords[2].s = right;
548 texCoords[2].t = 1.0f - bottom;
549 texCoords[3].s = right;
550 texCoords[3].t = 1.0f - top;
Mathias Agopian13127d82013-03-05 17:47:11 -0800551
Mathias Agopian875d8e12013-06-07 15:35:48 -0700552 RenderEngine& engine(mFlinger->getRenderEngine());
553 engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(), s.alpha);
Mathias Agopian5cdc8992013-08-13 20:51:23 -0700554 engine.drawMesh(mMesh);
Mathias Agopian875d8e12013-06-07 15:35:48 -0700555 engine.disableBlending();
Mathias Agopian13127d82013-03-05 17:47:11 -0800556}
557
558void Layer::setFiltering(bool filtering) {
559 mFiltering = filtering;
560}
561
562bool Layer::getFiltering() const {
563 return mFiltering;
564}
565
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800566// As documented in libhardware header, formats in the range
567// 0x100 - 0x1FF are specific to the HAL implementation, and
568// are known to have no alpha channel
569// TODO: move definition for device-specific range into
570// hardware.h, instead of using hard-coded values here.
571#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
572
Mathias Agopian5773d3f2013-07-25 19:24:31 -0700573bool Layer::getOpacityForFormat(uint32_t format) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700574 if (HARDWARE_IS_DEVICE_FORMAT(format)) {
575 return true;
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800576 }
Mathias Agopian5773d3f2013-07-25 19:24:31 -0700577 switch (format) {
578 case HAL_PIXEL_FORMAT_RGBA_8888:
579 case HAL_PIXEL_FORMAT_BGRA_8888:
Jesse Hallc2e41222013-08-08 13:40:22 -0700580 case HAL_PIXEL_FORMAT_sRGB_A_8888:
Mathias Agopiandd533712013-07-26 15:31:39 -0700581 return false;
Mathias Agopian5773d3f2013-07-25 19:24:31 -0700582 }
583 // in all other case, we have no blending (also for unknown formats)
Mathias Agopiandd533712013-07-26 15:31:39 -0700584 return true;
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800585}
586
Mathias Agopian13127d82013-03-05 17:47:11 -0800587// ----------------------------------------------------------------------------
588// local state
589// ----------------------------------------------------------------------------
590
Mathias Agopian3f844832013-08-07 21:24:32 -0700591void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh) const
Mathias Agopian13127d82013-03-05 17:47:11 -0800592{
Mathias Agopian1eae0ee2013-06-05 16:59:15 -0700593 const Layer::State& s(getDrawingState());
Mathias Agopian13127d82013-03-05 17:47:11 -0800594 const Transform tr(hw->getTransform() * s.transform);
595 const uint32_t hw_h = hw->getHeight();
596 Rect win(s.active.w, s.active.h);
597 if (!s.active.crop.isEmpty()) {
598 win.intersect(s.active.crop, &win);
599 }
Mathias Agopian6c7f25a2013-05-09 20:37:10 -0700600 // subtract the transparent region and snap to the bounds
Mathias Agopianf3e85d42013-05-10 18:01:12 -0700601 win = reduce(win, s.activeTransparentRegion);
Mathias Agopian3f844832013-08-07 21:24:32 -0700602
Mathias Agopian5cdc8992013-08-13 20:51:23 -0700603 Mesh::VertexArray position(mesh.getPositionArray());
604 tr.transform(position[0], win.left, win.top);
605 tr.transform(position[1], win.left, win.bottom);
606 tr.transform(position[2], win.right, win.bottom);
607 tr.transform(position[3], win.right, win.top);
Mathias Agopian3f844832013-08-07 21:24:32 -0700608 for (size_t i=0 ; i<4 ; i++) {
Mathias Agopian5cdc8992013-08-13 20:51:23 -0700609 position[i].y = hw_h - position[i].y;
Mathias Agopian13127d82013-03-05 17:47:11 -0800610 }
611}
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800612
Mathias Agopiana67932f2011-04-20 14:20:59 -0700613bool Layer::isOpaque() const
Mathias Agopiana7f66922010-05-26 22:08:52 -0700614{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700615 // if we don't have a buffer yet, we're translucent regardless of the
616 // layer's opaque flag.
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700617 if (mActiveBuffer == 0) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700618 return false;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700619 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700620
621 // if the layer has the opaque flag, then we're always opaque,
622 // otherwise we use the current buffer's format.
623 return mOpaqueLayer || mCurrentOpacity;
Mathias Agopiana7f66922010-05-26 22:08:52 -0700624}
625
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800626bool Layer::isProtected() const
627{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700628 const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800629 return (activeBuffer != 0) &&
630 (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
631}
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700632
Mathias Agopian13127d82013-03-05 17:47:11 -0800633bool Layer::isFixedSize() const {
634 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
635}
636
637bool Layer::isCropped() const {
638 return !mCurrentCrop.isEmpty();
639}
640
641bool Layer::needsFiltering(const sp<const DisplayDevice>& hw) const {
642 return mNeedsFiltering || hw->needsFiltering();
643}
644
645void Layer::setVisibleRegion(const Region& visibleRegion) {
646 // always called from main thread
647 this->visibleRegion = visibleRegion;
648}
649
650void Layer::setCoveredRegion(const Region& coveredRegion) {
651 // always called from main thread
652 this->coveredRegion = coveredRegion;
653}
654
655void Layer::setVisibleNonTransparentRegion(const Region&
656 setVisibleNonTransparentRegion) {
657 // always called from main thread
658 this->visibleNonTransparentRegion = setVisibleNonTransparentRegion;
659}
660
661// ----------------------------------------------------------------------------
662// transaction
663// ----------------------------------------------------------------------------
664
665uint32_t Layer::doTransaction(uint32_t flags) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800666 ATRACE_CALL();
667
Mathias Agopian1eae0ee2013-06-05 16:59:15 -0700668 const Layer::State& s(getDrawingState());
669 const Layer::State& c(getCurrentState());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800670
Mathias Agopian1eae0ee2013-06-05 16:59:15 -0700671 const bool sizeChanged = (c.requested.w != s.requested.w) ||
672 (c.requested.h != s.requested.h);
Mathias Agopiana138f892010-05-21 17:24:35 -0700673
674 if (sizeChanged) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700675 // the size changed, we need to ask our client to request a new buffer
Steve Block9d453682011-12-20 16:23:08 +0000676 ALOGD_IF(DEBUG_RESIZE,
Andy McFadden69052052012-09-14 16:10:11 -0700677 "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
Mathias Agopian419e1962012-05-23 14:34:07 -0700678 " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
679 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
680 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
681 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
Mathias Agopian1eae0ee2013-06-05 16:59:15 -0700682 this, getName().string(), mCurrentTransform, mCurrentScalingMode,
683 c.active.w, c.active.h,
684 c.active.crop.left,
685 c.active.crop.top,
686 c.active.crop.right,
687 c.active.crop.bottom,
688 c.active.crop.getWidth(),
689 c.active.crop.getHeight(),
690 c.requested.w, c.requested.h,
691 c.requested.crop.left,
692 c.requested.crop.top,
693 c.requested.crop.right,
694 c.requested.crop.bottom,
695 c.requested.crop.getWidth(),
696 c.requested.crop.getHeight(),
697 s.active.w, s.active.h,
698 s.active.crop.left,
699 s.active.crop.top,
700 s.active.crop.right,
701 s.active.crop.bottom,
702 s.active.crop.getWidth(),
703 s.active.crop.getHeight(),
704 s.requested.w, s.requested.h,
705 s.requested.crop.left,
706 s.requested.crop.top,
707 s.requested.crop.right,
708 s.requested.crop.bottom,
709 s.requested.crop.getWidth(),
710 s.requested.crop.getHeight());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800711
Jamie Gennis2a0d5b62011-09-26 16:54:44 -0700712 // record the new size, form this point on, when the client request
713 // a buffer, it'll get the new size.
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800714 mSurfaceFlingerConsumer->setDefaultBufferSize(
Mathias Agopian1eae0ee2013-06-05 16:59:15 -0700715 c.requested.w, c.requested.h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800716 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700717
Mathias Agopian0cd545f2012-06-07 14:18:55 -0700718 if (!isFixedSize()) {
719
Mathias Agopian1eae0ee2013-06-05 16:59:15 -0700720 const bool resizePending = (c.requested.w != c.active.w) ||
721 (c.requested.h != c.active.h);
Mathias Agopian0cd545f2012-06-07 14:18:55 -0700722
723 if (resizePending) {
Mathias Agopian13127d82013-03-05 17:47:11 -0800724 // don't let Layer::doTransaction update the drawing state
Mathias Agopian0cd545f2012-06-07 14:18:55 -0700725 // if we have a pending resize, unless we are in fixed-size mode.
726 // the drawing state will be updated only once we receive a buffer
727 // with the correct size.
728 //
729 // in particular, we want to make sure the clip (which is part
730 // of the geometry state) is latched together with the size but is
731 // latched immediately when no resizing is involved.
732
733 flags |= eDontUpdateGeometryState;
734 }
735 }
736
Mathias Agopian13127d82013-03-05 17:47:11 -0800737 // always set active to requested, unless we're asked not to
738 // this is used by Layer, which special cases resizes.
739 if (flags & eDontUpdateGeometryState) {
740 } else {
Mathias Agopian1eae0ee2013-06-05 16:59:15 -0700741 Layer::State& editCurrentState(getCurrentState());
742 editCurrentState.active = c.requested;
Mathias Agopian13127d82013-03-05 17:47:11 -0800743 }
744
Mathias Agopian1eae0ee2013-06-05 16:59:15 -0700745 if (s.active != c.active) {
Mathias Agopian13127d82013-03-05 17:47:11 -0800746 // invalidate and recompute the visible regions if needed
747 flags |= Layer::eVisibleRegion;
748 }
749
Mathias Agopian1eae0ee2013-06-05 16:59:15 -0700750 if (c.sequence != s.sequence) {
Mathias Agopian13127d82013-03-05 17:47:11 -0800751 // invalidate and recompute the visible regions if needed
752 flags |= eVisibleRegion;
753 this->contentDirty = true;
754
755 // we may use linear filtering, if the matrix scales us
Mathias Agopian1eae0ee2013-06-05 16:59:15 -0700756 const uint8_t type = c.transform.getType();
757 mNeedsFiltering = (!c.transform.preserveRects() ||
Mathias Agopian13127d82013-03-05 17:47:11 -0800758 (type >= Transform::SCALE));
759 }
760
761 // Commit the transaction
762 commitTransaction();
763 return flags;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800764}
765
Mathias Agopian13127d82013-03-05 17:47:11 -0800766void Layer::commitTransaction() {
767 mDrawingState = mCurrentState;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700768}
769
Mathias Agopian13127d82013-03-05 17:47:11 -0800770uint32_t Layer::getTransactionFlags(uint32_t flags) {
771 return android_atomic_and(~flags, &mTransactionFlags) & flags;
772}
773
774uint32_t Layer::setTransactionFlags(uint32_t flags) {
775 return android_atomic_or(flags, &mTransactionFlags);
776}
777
778bool Layer::setPosition(float x, float y) {
779 if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
780 return false;
781 mCurrentState.sequence++;
782 mCurrentState.transform.set(x, y);
783 setTransactionFlags(eTransactionNeeded);
784 return true;
785}
786bool Layer::setLayer(uint32_t z) {
787 if (mCurrentState.z == z)
788 return false;
789 mCurrentState.sequence++;
790 mCurrentState.z = z;
791 setTransactionFlags(eTransactionNeeded);
792 return true;
793}
794bool Layer::setSize(uint32_t w, uint32_t h) {
795 if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
796 return false;
797 mCurrentState.requested.w = w;
798 mCurrentState.requested.h = h;
799 setTransactionFlags(eTransactionNeeded);
800 return true;
801}
802bool Layer::setAlpha(uint8_t alpha) {
803 if (mCurrentState.alpha == alpha)
804 return false;
805 mCurrentState.sequence++;
806 mCurrentState.alpha = alpha;
807 setTransactionFlags(eTransactionNeeded);
808 return true;
809}
810bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) {
811 mCurrentState.sequence++;
812 mCurrentState.transform.set(
813 matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy);
814 setTransactionFlags(eTransactionNeeded);
815 return true;
816}
817bool Layer::setTransparentRegionHint(const Region& transparent) {
Mathias Agopian2ca79392013-04-02 18:30:32 -0700818 mCurrentState.requestedTransparentRegion = transparent;
Mathias Agopian13127d82013-03-05 17:47:11 -0800819 setTransactionFlags(eTransactionNeeded);
820 return true;
821}
822bool Layer::setFlags(uint8_t flags, uint8_t mask) {
823 const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
824 if (mCurrentState.flags == newFlags)
825 return false;
826 mCurrentState.sequence++;
827 mCurrentState.flags = newFlags;
828 setTransactionFlags(eTransactionNeeded);
829 return true;
830}
831bool Layer::setCrop(const Rect& crop) {
832 if (mCurrentState.requested.crop == crop)
833 return false;
834 mCurrentState.sequence++;
835 mCurrentState.requested.crop = crop;
836 setTransactionFlags(eTransactionNeeded);
837 return true;
838}
839
840bool Layer::setLayerStack(uint32_t layerStack) {
841 if (mCurrentState.layerStack == layerStack)
842 return false;
843 mCurrentState.sequence++;
844 mCurrentState.layerStack = layerStack;
845 setTransactionFlags(eTransactionNeeded);
846 return true;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700847}
848
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800849// ----------------------------------------------------------------------------
850// pageflip handling...
851// ----------------------------------------------------------------------------
852
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800853bool Layer::onPreComposition() {
854 mRefreshPending = false;
855 return mQueuedFrames > 0;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800856}
857
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700858void Layer::onPostComposition() {
859 if (mFrameLatencyNeeded) {
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800860 nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp();
Jamie Gennis82dbc742012-11-08 19:23:28 -0800861 mFrameTracker.setDesiredPresentTime(desiredPresentTime);
862
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800863 sp<Fence> frameReadyFence = mSurfaceFlingerConsumer->getCurrentFence();
Jamie Gennis789a6c32013-02-25 13:37:54 -0800864 if (frameReadyFence->isValid()) {
Jamie Gennis82dbc742012-11-08 19:23:28 -0800865 mFrameTracker.setFrameReadyFence(frameReadyFence);
866 } else {
867 // There was no fence for this frame, so assume that it was ready
868 // to be presented at the desired present time.
869 mFrameTracker.setFrameReadyTime(desiredPresentTime);
870 }
871
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700872 const HWComposer& hwc = mFlinger->getHwComposer();
Jamie Gennis82dbc742012-11-08 19:23:28 -0800873 sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
Jamie Gennis789a6c32013-02-25 13:37:54 -0800874 if (presentFence->isValid()) {
Jamie Gennis82dbc742012-11-08 19:23:28 -0800875 mFrameTracker.setActualPresentFence(presentFence);
876 } else {
877 // The HWC doesn't support present fences, so use the refresh
878 // timestamp instead.
879 nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
880 mFrameTracker.setActualPresentTime(presentTime);
881 }
882
883 mFrameTracker.advanceFrame();
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700884 mFrameLatencyNeeded = false;
885 }
886}
887
Mathias Agopianda27af92012-09-13 18:17:13 -0700888bool Layer::isVisible() const {
Mathias Agopian13127d82013-03-05 17:47:11 -0800889 const Layer::State& s(mDrawingState);
890 return !(s.flags & layer_state_t::eLayerHidden) && s.alpha
891 && (mActiveBuffer != NULL);
Mathias Agopianda27af92012-09-13 18:17:13 -0700892}
893
Mathias Agopian4fec8732012-06-29 14:12:52 -0700894Region Layer::latchBuffer(bool& recomputeVisibleRegions)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800895{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800896 ATRACE_CALL();
897
Mathias Agopian4fec8732012-06-29 14:12:52 -0700898 Region outDirtyRegion;
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700899 if (mQueuedFrames > 0) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800900
901 // if we've already called updateTexImage() without going through
902 // a composition step, we have to skip this layer at this point
903 // because we cannot call updateTeximage() without a corresponding
904 // compositionComplete() call.
905 // we'll trigger an update in onPreComposition().
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800906 if (mRefreshPending) {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700907 return outDirtyRegion;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800908 }
909
Jamie Gennis351a5132011-09-14 18:23:37 -0700910 // Capture the old state of the layer for comparisons later
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700911 const bool oldOpacity = isOpaque();
Jamie Gennis351a5132011-09-14 18:23:37 -0700912 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700913
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800914 struct Reject : public SurfaceFlingerConsumer::BufferRejecter {
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700915 Layer::State& front;
916 Layer::State& current;
917 bool& recomputeVisibleRegions;
918 Reject(Layer::State& front, Layer::State& current,
919 bool& recomputeVisibleRegions)
920 : front(front), current(current),
921 recomputeVisibleRegions(recomputeVisibleRegions) {
922 }
923
924 virtual bool reject(const sp<GraphicBuffer>& buf,
Mathias Agopiandb89edc2013-08-02 01:40:18 -0700925 const IGraphicBufferConsumer::BufferItem& item) {
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700926 if (buf == NULL) {
927 return false;
928 }
929
930 uint32_t bufWidth = buf->getWidth();
931 uint32_t bufHeight = buf->getHeight();
932
933 // check that we received a buffer of the right size
934 // (Take the buffer's orientation into account)
935 if (item.mTransform & Transform::ROT_90) {
936 swap(bufWidth, bufHeight);
937 }
938
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700939 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
940 if (front.active != front.requested) {
941
942 if (isFixedSize ||
943 (bufWidth == front.requested.w &&
944 bufHeight == front.requested.h))
945 {
946 // Here we pretend the transaction happened by updating the
947 // current and drawing states. Drawing state is only accessed
948 // in this thread, no need to have it locked
949 front.active = front.requested;
950
951 // We also need to update the current state so that
952 // we don't end-up overwriting the drawing state with
953 // this stale current state during the next transaction
954 //
955 // NOTE: We don't need to hold the transaction lock here
956 // because State::active is only accessed from this thread.
957 current.active = front.active;
958
959 // recompute visible region
960 recomputeVisibleRegions = true;
961 }
962
963 ALOGD_IF(DEBUG_RESIZE,
Andy McFadden69052052012-09-14 16:10:11 -0700964 "latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700965 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
966 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
Andy McFadden69052052012-09-14 16:10:11 -0700967 bufWidth, bufHeight, item.mTransform, item.mScalingMode,
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700968 front.active.w, front.active.h,
969 front.active.crop.left,
970 front.active.crop.top,
971 front.active.crop.right,
972 front.active.crop.bottom,
973 front.active.crop.getWidth(),
974 front.active.crop.getHeight(),
975 front.requested.w, front.requested.h,
976 front.requested.crop.left,
977 front.requested.crop.top,
978 front.requested.crop.right,
979 front.requested.crop.bottom,
980 front.requested.crop.getWidth(),
981 front.requested.crop.getHeight());
982 }
983
984 if (!isFixedSize) {
985 if (front.active.w != bufWidth ||
986 front.active.h != bufHeight) {
Mathias Agopian4824d402012-06-04 18:16:30 -0700987 // reject this buffer
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700988 return true;
989 }
990 }
Mathias Agopian2ca79392013-04-02 18:30:32 -0700991
992 // if the transparent region has changed (this test is
993 // conservative, but that's fine, worst case we're doing
994 // a bit of extra work), we latch the new one and we
995 // trigger a visible-region recompute.
996 if (!front.activeTransparentRegion.isTriviallyEqual(
997 front.requestedTransparentRegion)) {
998 front.activeTransparentRegion = front.requestedTransparentRegion;
Mathias Agopian6c67f0f2013-04-12 16:58:11 -0700999
1000 // We also need to update the current state so that
1001 // we don't end-up overwriting the drawing state with
1002 // this stale current state during the next transaction
1003 //
1004 // NOTE: We don't need to hold the transaction lock here
1005 // because State::active is only accessed from this thread.
1006 current.activeTransparentRegion = front.activeTransparentRegion;
1007
1008 // recompute visible region
Mathias Agopian2ca79392013-04-02 18:30:32 -07001009 recomputeVisibleRegions = true;
1010 }
1011
Mathias Agopian2c8207e2012-05-23 17:56:42 -07001012 return false;
1013 }
1014 };
1015
1016
Mathias Agopian1eae0ee2013-06-05 16:59:15 -07001017 Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions);
Mathias Agopian2c8207e2012-05-23 17:56:42 -07001018
Andy McFadden1585c4d2013-06-28 13:52:40 -07001019 status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r);
1020 if (updateResult == BufferQueue::PRESENT_LATER) {
1021 // Producer doesn't want buffer to be displayed yet. Signal a
1022 // layer update so we check again at the next opportunity.
1023 mFlinger->signalLayerUpdate();
1024 return outDirtyRegion;
1025 }
1026
1027 // Decrement the queued-frames count. Signal another event if we
1028 // have more frames pending.
1029 if (android_atomic_dec(&mQueuedFrames) > 1) {
1030 mFlinger->signalLayerUpdate();
1031 }
1032
1033 if (updateResult != NO_ERROR) {
Mathias Agopiana67932f2011-04-20 14:20:59 -07001034 // something happened!
1035 recomputeVisibleRegions = true;
Mathias Agopian4fec8732012-06-29 14:12:52 -07001036 return outDirtyRegion;
Mathias Agopiana67932f2011-04-20 14:20:59 -07001037 }
Mathias Agopian96f08192010-06-02 23:28:45 -07001038
Jamie Gennis351a5132011-09-14 18:23:37 -07001039 // update the active buffer
Andy McFaddenbf974ab2012-12-04 16:51:15 -08001040 mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer();
Mathias Agopiane31564d2012-05-29 20:41:03 -07001041 if (mActiveBuffer == NULL) {
1042 // this can only happen if the very first buffer was rejected.
Mathias Agopian4fec8732012-06-29 14:12:52 -07001043 return outDirtyRegion;
Mathias Agopiane31564d2012-05-29 20:41:03 -07001044 }
Mathias Agopianda9584d2010-12-13 18:51:59 -08001045
Mathias Agopian4824d402012-06-04 18:16:30 -07001046 mRefreshPending = true;
Mathias Agopian2c8207e2012-05-23 17:56:42 -07001047 mFrameLatencyNeeded = true;
Mathias Agopiane31564d2012-05-29 20:41:03 -07001048 if (oldActiveBuffer == NULL) {
Mathias Agopian2c8207e2012-05-23 17:56:42 -07001049 // the first time we receive a buffer, we need to trigger a
1050 // geometry invalidation.
Andy McFaddenab10c582012-09-26 16:19:12 -07001051 recomputeVisibleRegions = true;
Mathias Agopian2c8207e2012-05-23 17:56:42 -07001052 }
1053
Andy McFaddenbf974ab2012-12-04 16:51:15 -08001054 Rect crop(mSurfaceFlingerConsumer->getCurrentCrop());
1055 const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform());
1056 const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode());
Mathias Agopian702634a2012-05-23 17:50:31 -07001057 if ((crop != mCurrentCrop) ||
1058 (transform != mCurrentTransform) ||
1059 (scalingMode != mCurrentScalingMode))
1060 {
1061 mCurrentCrop = crop;
1062 mCurrentTransform = transform;
1063 mCurrentScalingMode = scalingMode;
Andy McFaddenab10c582012-09-26 16:19:12 -07001064 recomputeVisibleRegions = true;
Mathias Agopian702634a2012-05-23 17:50:31 -07001065 }
1066
1067 if (oldActiveBuffer != NULL) {
Mathias Agopiane31564d2012-05-29 20:41:03 -07001068 uint32_t bufWidth = mActiveBuffer->getWidth();
1069 uint32_t bufHeight = mActiveBuffer->getHeight();
Mathias Agopian702634a2012-05-23 17:50:31 -07001070 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
1071 bufHeight != uint32_t(oldActiveBuffer->height)) {
Andy McFaddenab10c582012-09-26 16:19:12 -07001072 recomputeVisibleRegions = true;
Mathias Agopian702634a2012-05-23 17:50:31 -07001073 }
1074 }
1075
1076 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
1077 if (oldOpacity != isOpaque()) {
1078 recomputeVisibleRegions = true;
1079 }
1080
Mathias Agopian4fec8732012-06-29 14:12:52 -07001081 // FIXME: postedRegion should be dirty & bounds
Mathias Agopian1eae0ee2013-06-05 16:59:15 -07001082 const Layer::State& s(getDrawingState());
1083 Region dirtyRegion(Rect(s.active.w, s.active.h));
Mathias Agopian4fec8732012-06-29 14:12:52 -07001084
1085 // transform the dirty region to window-manager space
Mathias Agopian1eae0ee2013-06-05 16:59:15 -07001086 outDirtyRegion = (s.transform.transform(dirtyRegion));
Mathias Agopiancaa600c2009-09-16 18:27:24 -07001087 }
Mathias Agopian4fec8732012-06-29 14:12:52 -07001088 return outDirtyRegion;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001089}
1090
Mathias Agopiana67932f2011-04-20 14:20:59 -07001091uint32_t Layer::getEffectiveUsage(uint32_t usage) const
Mathias Agopianb7e930d2010-06-01 15:12:58 -07001092{
Mathias Agopiana67932f2011-04-20 14:20:59 -07001093 // TODO: should we do something special if mSecure is set?
1094 if (mProtectedByApp) {
1095 // need a hardware-protected path to external video sink
1096 usage |= GraphicBuffer::USAGE_PROTECTED;
Jamie Gennis54cc83e2010-11-02 11:51:32 -07001097 }
Jamie Gennis3599bf22011-08-10 11:48:07 -07001098 usage |= GraphicBuffer::USAGE_HW_COMPOSER;
Mathias Agopiana67932f2011-04-20 14:20:59 -07001099 return usage;
Mathias Agopianb5b7f262010-05-07 15:58:44 -07001100}
1101
Mathias Agopian84300952012-11-21 16:02:13 -08001102void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const {
Mathias Agopiana4583642011-08-23 18:03:18 -07001103 uint32_t orientation = 0;
1104 if (!mFlinger->mDebugDisableTransformHint) {
Mathias Agopian84300952012-11-21 16:02:13 -08001105 // The transform hint is used to improve performance, but we can
1106 // only have a single transform hint, it cannot
Mathias Agopian4fec8732012-06-29 14:12:52 -07001107 // apply to all displays.
Mathias Agopian42977342012-08-05 00:40:46 -07001108 const Transform& planeTransform(hw->getTransform());
Mathias Agopian4fec8732012-06-29 14:12:52 -07001109 orientation = planeTransform.getOrientation();
Mathias Agopiana4583642011-08-23 18:03:18 -07001110 if (orientation & Transform::ROT_INVALID) {
1111 orientation = 0;
1112 }
1113 }
Andy McFaddenbf974ab2012-12-04 16:51:15 -08001114 mSurfaceFlingerConsumer->setTransformHint(orientation);
Mathias Agopiana4583642011-08-23 18:03:18 -07001115}
1116
Mathias Agopian13127d82013-03-05 17:47:11 -08001117// ----------------------------------------------------------------------------
1118// debugging
1119// ----------------------------------------------------------------------------
1120
Mathias Agopian3e25fd82013-04-22 17:52:16 +02001121void Layer::dump(String8& result, Colorizer& colorizer) const
Mathias Agopian13127d82013-03-05 17:47:11 -08001122{
Mathias Agopian1eae0ee2013-06-05 16:59:15 -07001123 const Layer::State& s(getDrawingState());
Mathias Agopian13127d82013-03-05 17:47:11 -08001124
Mathias Agopian3e25fd82013-04-22 17:52:16 +02001125 colorizer.colorize(result, Colorizer::GREEN);
Mathias Agopian74d211a2013-04-22 16:55:35 +02001126 result.appendFormat(
Mathias Agopian13127d82013-03-05 17:47:11 -08001127 "+ %s %p (%s)\n",
1128 getTypeId(), this, getName().string());
Mathias Agopian3e25fd82013-04-22 17:52:16 +02001129 colorizer.reset(result);
Mathias Agopian13127d82013-03-05 17:47:11 -08001130
Mathias Agopian2ca79392013-04-02 18:30:32 -07001131 s.activeTransparentRegion.dump(result, "transparentRegion");
Mathias Agopian13127d82013-03-05 17:47:11 -08001132 visibleRegion.dump(result, "visibleRegion");
1133 sp<Client> client(mClientRef.promote());
1134
Mathias Agopian74d211a2013-04-22 16:55:35 +02001135 result.appendFormat( " "
Mathias Agopian13127d82013-03-05 17:47:11 -08001136 "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
1137 "isOpaque=%1d, invalidate=%1d, "
1138 "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
1139 " client=%p\n",
1140 s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
1141 s.active.crop.left, s.active.crop.top,
1142 s.active.crop.right, s.active.crop.bottom,
1143 isOpaque(), contentDirty,
1144 s.alpha, s.flags,
1145 s.transform[0][0], s.transform[0][1],
1146 s.transform[1][0], s.transform[1][1],
1147 client.get());
Mathias Agopian13127d82013-03-05 17:47:11 -08001148
1149 sp<const GraphicBuffer> buf0(mActiveBuffer);
1150 uint32_t w0=0, h0=0, s0=0, f0=0;
1151 if (buf0 != 0) {
1152 w0 = buf0->getWidth();
1153 h0 = buf0->getHeight();
1154 s0 = buf0->getStride();
1155 f0 = buf0->format;
1156 }
Mathias Agopian74d211a2013-04-22 16:55:35 +02001157 result.appendFormat(
Mathias Agopian13127d82013-03-05 17:47:11 -08001158 " "
1159 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
1160 " queued-frames=%d, mRefreshPending=%d\n",
1161 mFormat, w0, h0, s0,f0,
1162 mQueuedFrames, mRefreshPending);
1163
Mathias Agopian13127d82013-03-05 17:47:11 -08001164 if (mSurfaceFlingerConsumer != 0) {
Mathias Agopian74d211a2013-04-22 16:55:35 +02001165 mSurfaceFlingerConsumer->dump(result, " ");
Mathias Agopian13127d82013-03-05 17:47:11 -08001166 }
1167}
1168
Mathias Agopian74d211a2013-04-22 16:55:35 +02001169void Layer::dumpStats(String8& result) const {
Mathias Agopian13127d82013-03-05 17:47:11 -08001170 mFrameTracker.dump(result);
1171}
1172
1173void Layer::clearStats() {
1174 mFrameTracker.clear();
1175}
1176
Jamie Gennis6547ff42013-07-16 20:12:42 -07001177void Layer::logFrameStats() {
1178 mFrameTracker.logAndResetStats(mName);
1179}
1180
Mathias Agopian13127d82013-03-05 17:47:11 -08001181// ---------------------------------------------------------------------------
1182
1183Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
1184 const sp<Layer>& layer)
1185 : mFlinger(flinger), mLayer(layer) {
1186}
1187
1188Layer::LayerCleaner::~LayerCleaner() {
1189 // destroy client resources
1190 mFlinger->onLayerDestroyed(mLayer);
1191}
1192
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001193// ---------------------------------------------------------------------------
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001194}; // namespace android
Mathias Agopian3f844832013-08-07 21:24:32 -07001195
1196#if defined(__gl_h_)
1197#error "don't include gl/gl.h in this file"
1198#endif
1199
1200#if defined(__gl2_h_)
1201#error "don't include gl2/gl2.h in this file"
1202#endif