blob: 6f9ad4ce0f4445cd01c9de199b8f2f4533f7e1d7 [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
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080017#include <stdlib.h>
18#include <stdint.h>
19#include <sys/types.h>
Mathias Agopiana8bca8d2013-02-27 22:03:19 -080020#include <math.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080021
22#include <utils/Errors.h>
23#include <utils/Log.h>
Mathias Agopian310f8da2009-05-22 01:27:01 -070024#include <binder/IPCThreadState.h>
25#include <binder/IServiceManager.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080026
27#include <GLES/gl.h>
28#include <GLES/glext.h>
29
30#include <hardware/hardware.h>
31
32#include "clz.h"
Mathias Agopiandb403e82012-06-18 16:47:56 -070033#include "Client.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080034#include "LayerBase.h"
Mathias Agopian921e6ac2012-07-23 23:11:29 -070035#include "Layer.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080036#include "SurfaceFlinger.h"
Mathias Agopian0f2f5ff2012-07-31 23:09:07 -070037#include "DisplayDevice.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080038
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080039namespace android {
40
41// ---------------------------------------------------------------------------
42
Mathias Agopianf6679fc2010-08-10 18:09:09 -070043int32_t LayerBase::sSequence = 1;
44
Mathias Agopianb79f61d2013-03-05 15:14:58 -080045LayerBase::LayerBase(SurfaceFlinger* flinger, const sp<Client>& client)
Mathias Agopian3ee454a2012-08-27 16:28:24 -070046 : contentDirty(false),
Mathias Agopianf6679fc2010-08-10 18:09:09 -070047 sequence(uint32_t(android_atomic_inc(&sSequence))),
Mathias Agopiana67932f2011-04-20 14:20:59 -070048 mFlinger(flinger), mFiltering(false),
Mathias Agopiana2f4e562012-04-15 23:34:59 -070049 mNeedsFiltering(false),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080050 mTransactionFlags(0),
Mathias Agopianb79f61d2013-03-05 15:14:58 -080051 mPremultipliedAlpha(true), mName("unnamed"), mDebug(false),
52 mHasSurface(false),
53 mClientRef(client)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080054{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080055}
56
57LayerBase::~LayerBase()
58{
Mathias Agopianb79f61d2013-03-05 15:14:58 -080059 sp<Client> c(mClientRef.promote());
60 if (c != 0) {
61 c->detachLayer(this);
62 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080063}
64
Mathias Agopiand1296592010-03-09 19:17:47 -080065void LayerBase::setName(const String8& name) {
66 mName = name;
67}
68
69String8 LayerBase::getName() const {
70 return mName;
71}
72
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080073void LayerBase::initStates(uint32_t w, uint32_t h, uint32_t flags)
74{
75 uint32_t layerFlags = 0;
Mathias Agopian3165cc22012-08-08 19:42:09 -070076 if (flags & ISurfaceComposerClient::eHidden)
77 layerFlags = layer_state_t::eLayerHidden;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080078
Mathias Agopian3165cc22012-08-08 19:42:09 -070079 if (flags & ISurfaceComposerClient::eNonPremultiplied)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080080 mPremultipliedAlpha = false;
81
Mathias Agopian93ffb862012-05-16 17:07:49 -070082 mCurrentState.active.w = w;
83 mCurrentState.active.h = h;
84 mCurrentState.active.crop.makeInvalid();
85 mCurrentState.z = 0;
86 mCurrentState.alpha = 0xFF;
Mathias Agopian87855782012-07-24 21:41:09 -070087 mCurrentState.layerStack = 0;
Mathias Agopian93ffb862012-05-16 17:07:49 -070088 mCurrentState.flags = layerFlags;
89 mCurrentState.sequence = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080090 mCurrentState.transform.set(0, 0);
Mathias Agopian93ffb862012-05-16 17:07:49 -070091 mCurrentState.requested = mCurrentState.active;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080092
93 // drawing state & current state are identical
94 mDrawingState = mCurrentState;
95}
96
Mathias Agopianeba8c682012-09-19 23:14:45 -070097bool LayerBase::needsFiltering(const sp<const DisplayDevice>& hw) const {
98 return mNeedsFiltering || hw->needsFiltering();
99}
100
Mathias Agopianba6be542009-09-29 22:32:36 -0700101void LayerBase::commitTransaction() {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800102 mDrawingState = mCurrentState;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800103}
104void LayerBase::forceVisibilityTransaction() {
105 // this can be called without SurfaceFlinger.mStateLock, but if we
106 // can atomically increment the sequence number, it doesn't matter.
107 android_atomic_inc(&mCurrentState.sequence);
108 requestTransaction();
109}
110bool LayerBase::requestTransaction() {
111 int32_t old = setTransactionFlags(eTransactionNeeded);
112 return ((old & eTransactionNeeded) == 0);
113}
114uint32_t LayerBase::getTransactionFlags(uint32_t flags) {
115 return android_atomic_and(~flags, &mTransactionFlags) & flags;
116}
117uint32_t LayerBase::setTransactionFlags(uint32_t flags) {
118 return android_atomic_or(flags, &mTransactionFlags);
119}
120
Mathias Agopian41b6aab2011-08-30 18:51:54 -0700121bool LayerBase::setPosition(float x, float y) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800122 if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
123 return false;
124 mCurrentState.sequence++;
125 mCurrentState.transform.set(x, y);
126 requestTransaction();
127 return true;
128}
129bool LayerBase::setLayer(uint32_t z) {
130 if (mCurrentState.z == z)
131 return false;
132 mCurrentState.sequence++;
133 mCurrentState.z = z;
134 requestTransaction();
135 return true;
136}
137bool LayerBase::setSize(uint32_t w, uint32_t h) {
Mathias Agopian93ffb862012-05-16 17:07:49 -0700138 if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800139 return false;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700140 mCurrentState.requested.w = w;
141 mCurrentState.requested.h = h;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800142 requestTransaction();
143 return true;
144}
145bool LayerBase::setAlpha(uint8_t alpha) {
146 if (mCurrentState.alpha == alpha)
147 return false;
148 mCurrentState.sequence++;
149 mCurrentState.alpha = alpha;
150 requestTransaction();
151 return true;
152}
153bool LayerBase::setMatrix(const layer_state_t::matrix22_t& matrix) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800154 mCurrentState.sequence++;
155 mCurrentState.transform.set(
156 matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy);
157 requestTransaction();
158 return true;
159}
160bool LayerBase::setTransparentRegionHint(const Region& transparent) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800161 mCurrentState.sequence++;
162 mCurrentState.transparentRegion = transparent;
163 requestTransaction();
164 return true;
165}
166bool LayerBase::setFlags(uint8_t flags, uint8_t mask) {
167 const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
168 if (mCurrentState.flags == newFlags)
169 return false;
170 mCurrentState.sequence++;
171 mCurrentState.flags = newFlags;
172 requestTransaction();
173 return true;
174}
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700175bool LayerBase::setCrop(const Rect& crop) {
Mathias Agopianb30c4152012-05-16 18:21:32 -0700176 if (mCurrentState.requested.crop == crop)
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700177 return false;
178 mCurrentState.sequence++;
Mathias Agopianb30c4152012-05-16 18:21:32 -0700179 mCurrentState.requested.crop = crop;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700180 requestTransaction();
181 return true;
182}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800183
Mathias Agopian87855782012-07-24 21:41:09 -0700184bool LayerBase::setLayerStack(uint32_t layerStack) {
185 if (mCurrentState.layerStack == layerStack)
186 return false;
187 mCurrentState.sequence++;
188 mCurrentState.layerStack = layerStack;
189 requestTransaction();
190 return true;
191}
192
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800193void LayerBase::setVisibleRegion(const Region& visibleRegion) {
194 // always called from main thread
Mathias Agopian4fec8732012-06-29 14:12:52 -0700195 this->visibleRegion = visibleRegion;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800196}
197
198void LayerBase::setCoveredRegion(const Region& coveredRegion) {
199 // always called from main thread
Mathias Agopian4fec8732012-06-29 14:12:52 -0700200 this->coveredRegion = coveredRegion;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800201}
202
Jesse Halla8026d22012-09-25 13:25:04 -0700203void LayerBase::setVisibleNonTransparentRegion(const Region&
204 setVisibleNonTransparentRegion) {
205 // always called from main thread
206 this->visibleNonTransparentRegion = setVisibleNonTransparentRegion;
207}
208
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800209uint32_t LayerBase::doTransaction(uint32_t flags)
210{
211 const Layer::State& front(drawingState());
212 const Layer::State& temp(currentState());
213
Mathias Agopian05cec9d2012-05-23 14:35:49 -0700214 // always set active to requested, unless we're asked not to
215 // this is used by Layer, which special cases resizes.
216 if (flags & eDontUpdateGeometryState) {
217 } else {
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700218 Layer::State& editTemp(currentState());
Mathias Agopianb30c4152012-05-16 18:21:32 -0700219 editTemp.active = temp.requested;
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700220 }
Mathias Agopian05cec9d2012-05-23 14:35:49 -0700221
Mathias Agopianb30c4152012-05-16 18:21:32 -0700222 if (front.active != temp.active) {
Mathias Agopian6656dbc2009-09-30 12:48:47 -0700223 // invalidate and recompute the visible regions if needed
224 flags |= Layer::eVisibleRegion;
Mathias Agopian6656dbc2009-09-30 12:48:47 -0700225 }
226
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800227 if (temp.sequence != front.sequence) {
228 // invalidate and recompute the visible regions if needed
229 flags |= eVisibleRegion;
230 this->contentDirty = true;
Mathias Agopiana2fe0a22009-09-23 18:34:53 -0700231
Mathias Agopian733189d2010-12-02 21:32:29 -0800232 // we may use linear filtering, if the matrix scales us
233 const uint8_t type = temp.transform.getType();
234 mNeedsFiltering = (!temp.transform.preserveRects() ||
235 (type >= Transform::SCALE));
Mathias Agopiana2fe0a22009-09-23 18:34:53 -0700236 }
237
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800238 // Commit the transaction
Mathias Agopianba6be542009-09-29 22:32:36 -0700239 commitTransaction();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800240 return flags;
241}
242
Mathias Agopian42977342012-08-05 00:40:46 -0700243void LayerBase::computeGeometry(const sp<const DisplayDevice>& hw, LayerMesh* mesh) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800244{
245 const Layer::State& s(drawingState());
Mathias Agopian42977342012-08-05 00:40:46 -0700246 const Transform tr(hw->getTransform() * s.transform);
247 const uint32_t hw_h = hw->getHeight();
Mathias Agopian93ffb862012-05-16 17:07:49 -0700248 Rect win(s.active.w, s.active.h);
Mathias Agopiana046dd92012-09-24 22:01:01 -0700249 if (!s.active.crop.isEmpty()) {
250 win.intersect(s.active.crop, &win);
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700251 }
Mathias Agopian4fec8732012-06-29 14:12:52 -0700252 if (mesh) {
253 tr.transform(mesh->mVertices[0], win.left, win.top);
254 tr.transform(mesh->mVertices[1], win.left, win.bottom);
255 tr.transform(mesh->mVertices[2], win.right, win.bottom);
256 tr.transform(mesh->mVertices[3], win.right, win.top);
257 for (size_t i=0 ; i<4 ; i++) {
258 mesh->mVertices[i][1] = hw_h - mesh->mVertices[i][1];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800259 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800260 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800261}
262
Mathias Agopian4fec8732012-06-29 14:12:52 -0700263Rect LayerBase::computeBounds() const {
264 const Layer::State& s(drawingState());
Mathias Agopian4fec8732012-06-29 14:12:52 -0700265 Rect win(s.active.w, s.active.h);
Mathias Agopiana046dd92012-09-24 22:01:01 -0700266 if (!s.active.crop.isEmpty()) {
267 win.intersect(s.active.crop, &win);
Mathias Agopian4fec8732012-06-29 14:12:52 -0700268 }
Mathias Agopian5219a062013-02-26 16:37:53 -0800269 return win;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800270}
271
Mathias Agopian4fec8732012-06-29 14:12:52 -0700272Region LayerBase::latchBuffer(bool& recomputeVisibleRegions) {
273 Region result;
274 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800275}
276
Mathias Agopiana8bca8d2013-02-27 22:03:19 -0800277
278Rect LayerBase::getContentCrop() const {
279 // regular layers just use their active area as the content crop
280 const State& s(drawingState());
281 return Rect(s.active.w, s.active.h);
282}
283
284uint32_t LayerBase::getContentTransform() const {
285 // regular layers don't have a content transform
286 return 0;
287}
288
289Rect LayerBase::computeCrop(const sp<const DisplayDevice>& hw) const {
Mathias Agopian3da16722013-02-28 17:12:07 -0800290 /*
291 * The way we compute the crop (aka. texture coordinates when we have a
292 * Layer) produces a different output from the GL code in
293 * drawWithOpenGL() due to HWC being limited to integers. The difference
294 * can be large if getContentTransform() contains a large scale factor.
295 * See comments in drawWithOpenGL() for more details.
296 */
297
Mathias Agopiana8bca8d2013-02-27 22:03:19 -0800298 // the content crop is the area of the content that gets scaled to the
299 // layer's size.
300 Rect crop(getContentCrop());
301
302 // the active.crop is the area of the window that gets cropped, but not
303 // scaled in any ways.
304 const State& s(drawingState());
Mathias Agopian3da16722013-02-28 17:12:07 -0800305
306 // apply the projection's clipping to the window crop in
307 // layerstack space, and convert-back to layer space.
308 // if there are no window scaling (or content scaling) involved,
309 // this operation will map to full pixels in the buffer.
310 // NOTE: should we revert to GL composition if a scaling is involved
311 // since it cannot be represented in the HWC API?
312 Rect activeCrop(s.transform.transform(s.active.crop));
313 activeCrop.intersect(hw->getViewport(), &activeCrop);
314 activeCrop = s.transform.inverse().transform(activeCrop);
315
316 // paranoia: make sure the window-crop is constrained in the
317 // window's bounds
318 activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop);
319
Mathias Agopiana8bca8d2013-02-27 22:03:19 -0800320 if (!activeCrop.isEmpty()) {
321 // Transform the window crop to match the buffer coordinate system,
322 // which means using the inverse of the current transform set on the
323 // SurfaceFlingerConsumer.
324 uint32_t invTransform = getContentTransform();
325 int winWidth = s.active.w;
326 int winHeight = s.active.h;
327 if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
328 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
329 NATIVE_WINDOW_TRANSFORM_FLIP_H;
330 winWidth = s.active.h;
331 winHeight = s.active.w;
332 }
333 const Rect winCrop = activeCrop.transform(
334 invTransform, s.active.w, s.active.h);
335
336 // the code below essentially performs a scaled intersection
337 // of crop and winCrop
338 float xScale = float(crop.width()) / float(winWidth);
339 float yScale = float(crop.height()) / float(winHeight);
340
341 int insetL = int(ceilf( winCrop.left * xScale));
342 int insetT = int(ceilf( winCrop.top * yScale));
343 int insetR = int(ceilf((winWidth - winCrop.right ) * xScale));
344 int insetB = int(ceilf((winHeight - winCrop.bottom) * yScale));
345
346 crop.left += insetL;
347 crop.top += insetT;
348 crop.right -= insetR;
349 crop.bottom -= insetB;
350 }
351 return crop;
352}
353
Mathias Agopian4fec8732012-06-29 14:12:52 -0700354void LayerBase::setGeometry(
Mathias Agopian42977342012-08-05 00:40:46 -0700355 const sp<const DisplayDevice>& hw,
Mathias Agopian4fec8732012-06-29 14:12:52 -0700356 HWComposer::HWCLayerInterface& layer)
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700357{
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700358 layer.setDefaultState();
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700359
360 // this gives us only the "orientation" component of the transform
361 const State& s(drawingState());
362 const uint32_t finalTransform = s.transform.getOrientation();
363 // we can only handle simple transformation
364 if (finalTransform & Transform::ROT_INVALID) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700365 layer.setTransform(0);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700366 } else {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700367 layer.setTransform(finalTransform);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700368 }
369
Mathias Agopian9f8386e2013-01-29 18:56:42 -0800370 if (!isOpaque() || s.alpha != 0xFF) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700371 layer.setBlending(mPremultipliedAlpha ?
372 HWC_BLENDING_PREMULT :
373 HWC_BLENDING_COVERAGE);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700374 }
375
Mathias Agopian4fec8732012-06-29 14:12:52 -0700376
Mathias Agopian5219a062013-02-26 16:37:53 -0800377 // apply the layer's transform, followed by the display's global transform
378 // here we're guaranteed that the layer's transform preserves rects
379
Mathias Agopiana8bca8d2013-02-27 22:03:19 -0800380 Rect frame(s.transform.transform(computeBounds()));
Mathias Agopian3da16722013-02-28 17:12:07 -0800381 frame.intersect(hw->getViewport(), &frame);
Mathias Agopiana8bca8d2013-02-27 22:03:19 -0800382 const Transform& tr(hw->getTransform());
383 layer.setFrame(tr.transform(frame));
384 layer.setCrop(computeCrop(hw));
Mathias Agopiana350ff92010-08-10 17:14:02 -0700385}
386
Mathias Agopian42977342012-08-05 00:40:46 -0700387void LayerBase::setPerFrameData(const sp<const DisplayDevice>& hw,
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700388 HWComposer::HWCLayerInterface& layer) {
Mathias Agopianc3973602012-08-31 17:51:25 -0700389 // we have to set the visible region on every frame because
390 // we currently free it during onLayerDisplayed(), which is called
391 // after HWComposer::commit() -- every frame.
Mathias Agopianf5f714a2013-02-26 16:54:05 -0800392 // Apply this display's projection's viewport to the visible region
393 // before giving it to the HWC HAL.
Mathias Agopianc3973602012-08-31 17:51:25 -0700394 const Transform& tr = hw->getTransform();
Mathias Agopianf5f714a2013-02-26 16:54:05 -0800395 Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
396 layer.setVisibleRegionScreen(visible);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700397}
398
Mathias Agopian42977342012-08-05 00:40:46 -0700399void LayerBase::setAcquireFence(const sp<const DisplayDevice>& hw,
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700400 HWComposer::HWCLayerInterface& layer) {
Jesse Hallc5c5a142012-07-02 16:49:28 -0700401 layer.setAcquireFenceFd(-1);
402}
403
Mathias Agopianc3973602012-08-31 17:51:25 -0700404void LayerBase::onLayerDisplayed(const sp<const DisplayDevice>& hw,
405 HWComposer::HWCLayerInterface* layer) {
406 if (layer) {
407 layer->onDisplayed();
408 }
409}
410
Mathias Agopiana67932f2011-04-20 14:20:59 -0700411void LayerBase::setFiltering(bool filtering)
412{
413 mFiltering = filtering;
414}
415
416bool LayerBase::getFiltering() const
417{
418 return mFiltering;
419}
420
Mathias Agopianda27af92012-09-13 18:17:13 -0700421bool LayerBase::isVisible() const {
422 const Layer::State& s(mDrawingState);
423 return !(s.flags & layer_state_t::eLayerHidden) && s.alpha;
424}
425
Mathias Agopian42977342012-08-05 00:40:46 -0700426void LayerBase::draw(const sp<const DisplayDevice>& hw, const Region& clip) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800427{
Mathias Agopian1b031492012-06-20 17:51:20 -0700428 onDraw(hw, clip);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800429}
430
Mathias Agopian42977342012-08-05 00:40:46 -0700431void LayerBase::draw(const sp<const DisplayDevice>& hw)
Mathias Agopian74c40c02010-09-29 13:02:36 -0700432{
Mathias Agopian42977342012-08-05 00:40:46 -0700433 onDraw( hw, Region(hw->bounds()) );
Mathias Agopian74c40c02010-09-29 13:02:36 -0700434}
435
Mathias Agopian42977342012-08-05 00:40:46 -0700436void LayerBase::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
Mathias Agopian1b031492012-06-20 17:51:20 -0700437 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800438{
Mathias Agopian42977342012-08-05 00:40:46 -0700439 const uint32_t fbHeight = hw->getHeight();
Mathias Agopian010fccb2010-05-26 22:26:12 -0700440 glColor4f(red,green,blue,alpha);
Mathias Agopian0a917752010-06-14 21:20:00 -0700441
Mathias Agopianc492e672011-10-18 14:49:27 -0700442 glDisable(GL_TEXTURE_EXTERNAL_OES);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700443 glDisable(GL_TEXTURE_2D);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800444 glDisable(GL_BLEND);
Mathias Agopian20f68782009-05-11 00:03:41 -0700445
Mathias Agopian4fec8732012-06-29 14:12:52 -0700446 LayerMesh mesh;
447 computeGeometry(hw, &mesh);
448
449 glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
450 glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800451}
452
Mathias Agopian42977342012-08-05 00:40:46 -0700453void LayerBase::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const
Rebecca Schultz Zavin29aa74c2009-09-01 23:06:45 -0700454{
Mathias Agopian1b031492012-06-20 17:51:20 -0700455 clearWithOpenGL(hw, clip, 0,0,0,0);
Rebecca Schultz Zavin29aa74c2009-09-01 23:06:45 -0700456}
457
Mathias Agopian42977342012-08-05 00:40:46 -0700458void LayerBase::drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800459{
Mathias Agopian42977342012-08-05 00:40:46 -0700460 const uint32_t fbHeight = hw->getHeight();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800461 const State& s(drawingState());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800462
Mathias Agopian49753262010-04-12 15:34:55 -0700463 GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
Glenn Kasten99ed2242011-12-15 09:51:17 -0800464 if (CC_UNLIKELY(s.alpha < 0xFF)) {
Mathias Agopian78fd5012010-04-20 14:51:04 -0700465 const GLfloat alpha = s.alpha * (1.0f/255.0f);
Mathias Agopian49753262010-04-12 15:34:55 -0700466 if (mPremultipliedAlpha) {
467 glColor4f(alpha, alpha, alpha, alpha);
468 } else {
469 glColor4f(1, 1, 1, alpha);
470 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800471 glEnable(GL_BLEND);
472 glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
Mathias Agopian49753262010-04-12 15:34:55 -0700473 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800474 } else {
Mathias Agopian78fd5012010-04-20 14:51:04 -0700475 glColor4f(1, 1, 1, 1);
Mathias Agopian49753262010-04-12 15:34:55 -0700476 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700477 if (!isOpaque()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800478 glEnable(GL_BLEND);
479 glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
480 } else {
481 glDisable(GL_BLEND);
482 }
483 }
484
Mathias Agopian4fec8732012-06-29 14:12:52 -0700485 LayerMesh mesh;
486 computeGeometry(hw, &mesh);
487
488 // TODO: we probably want to generate the texture coords with the mesh
489 // here we assume that we only have 4 vertices
490
Mathias Agopianb661d662010-08-19 17:01:19 -0700491 struct TexCoords {
492 GLfloat u;
493 GLfloat v;
Mathias Agopian78fd5012010-04-20 14:51:04 -0700494 };
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800495
Mathias Agopian3da16722013-02-28 17:12:07 -0800496
497 /*
498 * NOTE: the way we compute the texture coordinates here produces
499 * different results than when we take the HWC path -- in the later case
500 * the "source crop" is rounded to texel boundaries.
501 * This can produce significantly different results when the texture
502 * is scaled by a large amount.
503 *
504 * The GL code below is more logical (imho), and the difference with
505 * HWC is due to a limitation of the HWC API to integers -- a question
506 * is suspend is wether we should ignore this problem or revert to
507 * GL composition when a buffer scaling is applied (maybe with some
508 * minimal value)? Or, we could make GL behave like HWC -- but this feel
509 * like more of a hack.
510 */
511 const Rect win(computeBounds());
Mathias Agopiana046dd92012-09-24 22:01:01 -0700512
513 GLfloat left = GLfloat(win.left) / GLfloat(s.active.w);
514 GLfloat top = GLfloat(win.top) / GLfloat(s.active.h);
515 GLfloat right = GLfloat(win.right) / GLfloat(s.active.w);
516 GLfloat bottom = GLfloat(win.bottom) / GLfloat(s.active.h);
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700517
Mathias Agopianb661d662010-08-19 17:01:19 -0700518 TexCoords texCoords[4];
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700519 texCoords[0].u = left;
520 texCoords[0].v = top;
521 texCoords[1].u = left;
522 texCoords[1].v = bottom;
523 texCoords[2].u = right;
524 texCoords[2].v = bottom;
525 texCoords[3].u = right;
526 texCoords[3].v = top;
527 for (int i = 0; i < 4; i++) {
528 texCoords[i].v = 1.0f - texCoords[i].v;
529 }
Mathias Agopian78fd5012010-04-20 14:51:04 -0700530
531 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
Mathias Agopian78fd5012010-04-20 14:51:04 -0700532 glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
Mathias Agopian4fec8732012-06-29 14:12:52 -0700533 glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
534 glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
Mathias Agopian78fd5012010-04-20 14:51:04 -0700535
Mathias Agopian78fd5012010-04-20 14:51:04 -0700536 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
Mathias Agopianc492e672011-10-18 14:49:27 -0700537 glDisable(GL_BLEND);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800538}
539
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700540void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
541{
542 const Layer::State& s(drawingState());
Mathias Agopianc95dbdc2012-02-05 00:19:27 -0800543
544 snprintf(buffer, SIZE,
545 "+ %s %p (%s)\n",
546 getTypeId(), this, getName().string());
547 result.append(buffer);
548
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800549 s.transparentRegion.dump(result, "transparentRegion");
Mathias Agopian4fec8732012-06-29 14:12:52 -0700550 visibleRegion.dump(result, "visibleRegion");
Mathias Agopianb79f61d2013-03-05 15:14:58 -0800551 sp<Client> client(mClientRef.promote());
Mathias Agopianc95dbdc2012-02-05 00:19:27 -0800552
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700553 snprintf(buffer, SIZE,
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700554 " "
Mathias Agopian5f20e2d2012-08-10 18:50:38 -0700555 "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
Mathias Agopiana67932f2011-04-20 14:20:59 -0700556 "isOpaque=%1d, needsDithering=%1d, invalidate=%1d, "
Mathias Agopianb79f61d2013-03-05 15:14:58 -0800557 "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
558 " client=%p\n",
Mathias Agopian791da602012-09-11 20:52:46 -0700559 s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
Mathias Agopian93ffb862012-05-16 17:07:49 -0700560 s.active.crop.left, s.active.crop.top,
561 s.active.crop.right, s.active.crop.bottom,
Mathias Agopiana67932f2011-04-20 14:20:59 -0700562 isOpaque(), needsDithering(), contentDirty,
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700563 s.alpha, s.flags,
564 s.transform[0][0], s.transform[0][1],
Mathias Agopianb79f61d2013-03-05 15:14:58 -0800565 s.transform[1][0], s.transform[1][1],
566 client.get());
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700567 result.append(buffer);
568}
Mathias Agopian54ba51d2009-10-26 20:12:37 -0700569
Mathias Agopian25e66fc2012-01-28 22:31:55 -0800570void LayerBase::shortDump(String8& result, char* scratch, size_t size) const {
Mathias Agopian48b888a2011-01-19 16:15:53 -0800571 LayerBase::dump(result, scratch, size);
572}
573
Mathias Agopian25e66fc2012-01-28 22:31:55 -0800574void LayerBase::dumpStats(String8& result, char* scratch, size_t SIZE) const {
575}
576
577void LayerBase::clearStats() {
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800578}
Mathias Agopian48b888a2011-01-19 16:15:53 -0800579
Mathias Agopian921e6ac2012-07-23 23:11:29 -0700580sp<Layer> LayerBase::getLayer() const {
581 return 0;
582}
583
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800584// ---------------------------------------------------------------------------
585
Mathias Agopianb79f61d2013-03-05 15:14:58 -0800586sp<ISurface> LayerBase::createSurface()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800587{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700588 class BSurface : public BnSurface, public LayerCleaner {
Andy McFadden2adaf042012-12-18 09:49:45 -0800589 virtual sp<IGraphicBufferProducer> getSurfaceTexture() const { return 0; }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700590 public:
591 BSurface(const sp<SurfaceFlinger>& flinger,
Mathias Agopianb79f61d2013-03-05 15:14:58 -0800592 const sp<LayerBase>& layer)
Mathias Agopiana67932f2011-04-20 14:20:59 -0700593 : LayerCleaner(flinger, layer) { }
594 };
595 sp<ISurface> sur(new BSurface(mFlinger, this));
596 return sur;
597}
598
Mathias Agopianb79f61d2013-03-05 15:14:58 -0800599sp<ISurface> LayerBase::getSurface()
Mathias Agopiana67932f2011-04-20 14:20:59 -0700600{
601 sp<ISurface> s;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700602 Mutex::Autolock _l(mLock);
Mathias Agopiana1f47b92011-02-15 19:01:06 -0800603
604 LOG_ALWAYS_FATAL_IF(mHasSurface,
Mathias Agopianb79f61d2013-03-05 15:14:58 -0800605 "LayerBase::getSurface() has already been called");
Mathias Agopiana1f47b92011-02-15 19:01:06 -0800606
607 mHasSurface = true;
608 s = createSurface();
609 mClientSurfaceBinder = s->asBinder();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700610 return s;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800611}
612
Mathias Agopianb79f61d2013-03-05 15:14:58 -0800613wp<IBinder> LayerBase::getSurfaceBinder() const {
Mathias Agopian0d156122011-01-25 20:17:45 -0800614 return mClientSurfaceBinder;
615}
616
Mathias Agopianb79f61d2013-03-05 15:14:58 -0800617wp<IBinder> LayerBase::getSurfaceTextureBinder() const {
Jamie Gennis582270d2011-08-17 18:19:00 -0700618 return 0;
619}
620
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700621// ---------------------------------------------------------------------------
622
Mathias Agopianb79f61d2013-03-05 15:14:58 -0800623LayerBase::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
624 const sp<LayerBase>& layer)
Mathias Agopiana67932f2011-04-20 14:20:59 -0700625 : mFlinger(flinger), mLayer(layer) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700626}
627
Mathias Agopianb79f61d2013-03-05 15:14:58 -0800628LayerBase::LayerCleaner::~LayerCleaner() {
Mathias Agopian9a112062009-04-17 19:36:26 -0700629 // destroy client resources
Mathias Agopian921e6ac2012-07-23 23:11:29 -0700630 mFlinger->onLayerDestroyed(mLayer);
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700631}
632
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800633// ---------------------------------------------------------------------------
634
635}; // namespace android