blob: 9191b2a379a492217037161de59f8f8c8cfa0ba5 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
Mathias Agopiane3c697f2013-02-14 17:11:02 -08002 * Copyright (C) 2010 The Android Open Source Project
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08003 *
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
17#define LOG_TAG "Surface"
Mathias Agopiane3c697f2013-02-14 17:11:02 -080018#define ATRACE_TAG ATRACE_TAG_GRAPHICS
19//#define LOG_NDEBUG 0
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080020
Mathias Agopianb0e76f42012-03-23 14:15:44 -070021#include <android/native_window.h>
22
Mathias Agopiane3c697f2013-02-14 17:11:02 -080023#include <binder/Parcel.h>
24
Mathias Agopian9cce3252010-02-09 17:46:37 -080025#include <utils/Log.h>
Mathias Agopiane3c697f2013-02-14 17:11:02 -080026#include <utils/Trace.h>
Rachad7cb0d392014-07-29 17:53:53 -070027#include <utils/NativeHandle.h>
Mathias Agopian9cce3252010-02-09 17:46:37 -080028
Mathias Agopiane3c697f2013-02-14 17:11:02 -080029#include <ui/Fence.h>
Dan Stoza5065a552015-03-17 16:23:42 -070030#include <ui/Region.h>
Mathias Agopiana67932f2011-04-20 14:20:59 -070031
Dan Stozaf0eaf252014-03-21 13:05:51 -070032#include <gui/IProducerListener.h>
Mathias Agopian90ac7992012-02-25 18:48:35 -080033#include <gui/ISurfaceComposer.h>
Mathias Agopian90ac7992012-02-25 18:48:35 -080034#include <gui/SurfaceComposerClient.h>
Mathias Agopiane3c697f2013-02-14 17:11:02 -080035#include <gui/GLConsumer.h>
36#include <gui/Surface.h>
37
38#include <private/gui/ComposerService.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070039
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080040namespace android {
41
Mathias Agopiane3c697f2013-02-14 17:11:02 -080042Surface::Surface(
Mathias Agopian595264f2013-07-16 22:56:09 -070043 const sp<IGraphicBufferProducer>& bufferProducer,
44 bool controlledByApp)
Dan Stoza812ed062015-06-02 15:45:22 -070045 : mGraphicBufferProducer(bufferProducer),
Pablo Ceballos60d69222015-08-07 14:47:20 -070046 mCrop(Rect::EMPTY_RECT),
Dan Stoza812ed062015-06-02 15:45:22 -070047 mGenerationNumber(0)
Mathias Agopian62185b72009-04-16 16:19:50 -070048{
Mathias Agopiane3c697f2013-02-14 17:11:02 -080049 // Initialize the ANativeWindow function pointers.
50 ANativeWindow::setSwapInterval = hook_setSwapInterval;
51 ANativeWindow::dequeueBuffer = hook_dequeueBuffer;
52 ANativeWindow::cancelBuffer = hook_cancelBuffer;
53 ANativeWindow::queueBuffer = hook_queueBuffer;
54 ANativeWindow::query = hook_query;
55 ANativeWindow::perform = hook_perform;
56
57 ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
58 ANativeWindow::cancelBuffer_DEPRECATED = hook_cancelBuffer_DEPRECATED;
59 ANativeWindow::lockBuffer_DEPRECATED = hook_lockBuffer_DEPRECATED;
60 ANativeWindow::queueBuffer_DEPRECATED = hook_queueBuffer_DEPRECATED;
61
62 const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
63 const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
64
65 mReqWidth = 0;
66 mReqHeight = 0;
67 mReqFormat = 0;
68 mReqUsage = 0;
69 mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -080070 mDataSpace = HAL_DATASPACE_UNKNOWN;
Mathias Agopiane3c697f2013-02-14 17:11:02 -080071 mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
72 mTransform = 0;
Ruben Brunk1681d952014-06-27 15:51:55 -070073 mStickyTransform = 0;
Mathias Agopiane3c697f2013-02-14 17:11:02 -080074 mDefaultWidth = 0;
75 mDefaultHeight = 0;
76 mUserWidth = 0;
77 mUserHeight = 0;
78 mTransformHint = 0;
79 mConsumerRunningBehind = false;
80 mConnectedToCpu = false;
Eino-Ville Talvala7895e902013-08-21 11:53:37 -070081 mProducerControlledByApp = controlledByApp;
Mathias Agopian7cdd7862013-07-18 22:10:56 -070082 mSwapIntervalZero = false;
Mathias Agopian62185b72009-04-16 16:19:50 -070083}
84
Mathias Agopian35ffa6a2013-03-12 18:45:09 -070085Surface::~Surface() {
86 if (mConnectedToCpu) {
87 Surface::disconnect(NATIVE_WINDOW_API_CPU);
88 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -080089}
90
91sp<IGraphicBufferProducer> Surface::getIGraphicBufferProducer() const {
92 return mGraphicBufferProducer;
93}
94
Wonsik Kim0ee14ca2014-03-17 17:46:53 +090095void Surface::setSidebandStream(const sp<NativeHandle>& stream) {
96 mGraphicBufferProducer->setSidebandStream(stream);
97}
98
Dan Stoza29a3e902014-06-20 13:13:57 -070099void Surface::allocateBuffers() {
100 uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth;
101 uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight;
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700102 mGraphicBufferProducer->allocateBuffers(reqWidth, reqHeight,
103 mReqFormat, mReqUsage);
Dan Stoza29a3e902014-06-20 13:13:57 -0700104}
105
Dan Stoza812ed062015-06-02 15:45:22 -0700106status_t Surface::setGenerationNumber(uint32_t generation) {
107 status_t result = mGraphicBufferProducer->setGenerationNumber(generation);
108 if (result == NO_ERROR) {
109 mGenerationNumber = generation;
110 }
111 return result;
112}
113
Dan Stoza7dde5992015-05-22 09:51:44 -0700114uint64_t Surface::getNextFrameNumber() const {
115 return mGraphicBufferProducer->getNextFrameNumber();
116}
117
Dan Stozac6f30bd2015-06-08 09:32:50 -0700118String8 Surface::getConsumerName() const {
119 return mGraphicBufferProducer->getConsumerName();
120}
121
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800122int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
123 Surface* c = getSelf(window);
124 return c->setSwapInterval(interval);
125}
126
127int Surface::hook_dequeueBuffer(ANativeWindow* window,
128 ANativeWindowBuffer** buffer, int* fenceFd) {
129 Surface* c = getSelf(window);
130 return c->dequeueBuffer(buffer, fenceFd);
131}
132
133int Surface::hook_cancelBuffer(ANativeWindow* window,
134 ANativeWindowBuffer* buffer, int fenceFd) {
135 Surface* c = getSelf(window);
136 return c->cancelBuffer(buffer, fenceFd);
137}
138
139int Surface::hook_queueBuffer(ANativeWindow* window,
140 ANativeWindowBuffer* buffer, int fenceFd) {
141 Surface* c = getSelf(window);
142 return c->queueBuffer(buffer, fenceFd);
143}
144
145int Surface::hook_dequeueBuffer_DEPRECATED(ANativeWindow* window,
146 ANativeWindowBuffer** buffer) {
147 Surface* c = getSelf(window);
148 ANativeWindowBuffer* buf;
149 int fenceFd = -1;
150 int result = c->dequeueBuffer(&buf, &fenceFd);
151 sp<Fence> fence(new Fence(fenceFd));
Mathias Agopianea74d3b2013-05-16 18:03:22 -0700152 int waitResult = fence->waitForever("dequeueBuffer_DEPRECATED");
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800153 if (waitResult != OK) {
154 ALOGE("dequeueBuffer_DEPRECATED: Fence::wait returned an error: %d",
155 waitResult);
156 c->cancelBuffer(buf, -1);
157 return waitResult;
Mathias Agopian62185b72009-04-16 16:19:50 -0700158 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800159 *buffer = buf;
160 return result;
Mathias Agopian62185b72009-04-16 16:19:50 -0700161}
162
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800163int Surface::hook_cancelBuffer_DEPRECATED(ANativeWindow* window,
164 ANativeWindowBuffer* buffer) {
165 Surface* c = getSelf(window);
166 return c->cancelBuffer(buffer, -1);
Mathias Agopian62185b72009-04-16 16:19:50 -0700167}
168
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800169int Surface::hook_lockBuffer_DEPRECATED(ANativeWindow* window,
170 ANativeWindowBuffer* buffer) {
171 Surface* c = getSelf(window);
172 return c->lockBuffer_DEPRECATED(buffer);
Mathias Agopian62185b72009-04-16 16:19:50 -0700173}
174
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800175int Surface::hook_queueBuffer_DEPRECATED(ANativeWindow* window,
176 ANativeWindowBuffer* buffer) {
177 Surface* c = getSelf(window);
178 return c->queueBuffer(buffer, -1);
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700179}
Mathias Agopian62185b72009-04-16 16:19:50 -0700180
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800181int Surface::hook_query(const ANativeWindow* window,
182 int what, int* value) {
183 const Surface* c = getSelf(window);
184 return c->query(what, value);
185}
186
187int Surface::hook_perform(ANativeWindow* window, int operation, ...) {
188 va_list args;
189 va_start(args, operation);
190 Surface* c = getSelf(window);
Haixia Shid89c2bb2015-09-14 11:02:18 -0700191 int result = c->perform(operation, args);
192 va_end(args);
193 return result;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800194}
195
196int Surface::setSwapInterval(int interval) {
197 ATRACE_CALL();
198 // EGL specification states:
199 // interval is silently clamped to minimum and maximum implementation
200 // dependent values before being stored.
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800201
202 if (interval < minSwapInterval)
203 interval = minSwapInterval;
204
205 if (interval > maxSwapInterval)
206 interval = maxSwapInterval;
207
Mathias Agopian7cdd7862013-07-18 22:10:56 -0700208 mSwapIntervalZero = (interval == 0);
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700209 mGraphicBufferProducer->setAsyncMode(mSwapIntervalZero);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800210
Mathias Agopian7cdd7862013-07-18 22:10:56 -0700211 return NO_ERROR;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800212}
213
Mathias Agopianba93b3f2013-08-01 15:48:40 -0700214int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800215 ATRACE_CALL();
216 ALOGV("Surface::dequeueBuffer");
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800217
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800218 uint32_t reqWidth;
219 uint32_t reqHeight;
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800220 PixelFormat reqFormat;
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800221 uint32_t reqUsage;
222
223 {
224 Mutex::Autolock lock(mMutex);
225
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800226 reqWidth = mReqWidth ? mReqWidth : mUserWidth;
227 reqHeight = mReqHeight ? mReqHeight : mUserHeight;
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800228
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800229 reqFormat = mReqFormat;
230 reqUsage = mReqUsage;
231 } // Drop the lock so that we can still touch the Surface while blocking in IGBP::dequeueBuffer
232
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800233 int buf = -1;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800234 sp<Fence> fence;
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700235 status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800236 reqWidth, reqHeight, reqFormat, reqUsage);
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800237
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800238 if (result < 0) {
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700239 ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer"
240 "(%d, %d, %d, %d) failed: %d", reqWidth, reqHeight, reqFormat,
241 reqUsage, result);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800242 return result;
Mathias Agopian62185b72009-04-16 16:19:50 -0700243 }
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800244
245 Mutex::Autolock lock(mMutex);
246
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800247 sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
Mathias Agopianba93b3f2013-08-01 15:48:40 -0700248
249 // this should never happen
250 ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);
251
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800252 if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
253 freeAllBuffers();
Mathias Agopian579b3f82010-06-08 19:54:15 -0700254 }
Ted Bonkenburgbd050ab2011-07-15 15:10:10 -0700255
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800256 if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
257 result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
258 if (result != NO_ERROR) {
Mathias Agopianba93b3f2013-08-01 15:48:40 -0700259 ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result);
Jesse Hall9f5a1b62014-10-02 11:09:03 -0700260 mGraphicBufferProducer->cancelBuffer(buf, fence);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800261 return result;
262 }
263 }
Mathias Agopian579b3f82010-06-08 19:54:15 -0700264
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800265 if (fence->isValid()) {
266 *fenceFd = fence->dup();
267 if (*fenceFd == -1) {
268 ALOGE("dequeueBuffer: error duping fence: %d", errno);
269 // dup() should never fail; something is badly wrong. Soldier on
270 // and hope for the best; the worst that should happen is some
271 // visible corruption that lasts until the next frame.
272 }
Ted Bonkenburge5d6eb82011-08-09 22:38:41 -0700273 } else {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800274 *fenceFd = -1;
Mathias Agopiana0c30e92010-06-04 18:26:32 -0700275 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800276
277 *buffer = gbuf.get();
278 return OK;
Jamie Gennisaca4e222010-07-15 17:29:15 -0700279}
280
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800281int Surface::cancelBuffer(android_native_buffer_t* buffer,
282 int fenceFd) {
283 ATRACE_CALL();
284 ALOGV("Surface::cancelBuffer");
285 Mutex::Autolock lock(mMutex);
286 int i = getSlotFromBufferLocked(buffer);
287 if (i < 0) {
Taiju Tsuiki4d0cd3f2015-04-30 22:15:33 +0900288 if (fenceFd >= 0) {
289 close(fenceFd);
290 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800291 return i;
292 }
293 sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
294 mGraphicBufferProducer->cancelBuffer(i, fence);
295 return OK;
296}
297
298int Surface::getSlotFromBufferLocked(
299 android_native_buffer_t* buffer) const {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800300 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
301 if (mSlots[i].buffer != NULL &&
302 mSlots[i].buffer->handle == buffer->handle) {
303 return i;
Jamie Gennisaca4e222010-07-15 17:29:15 -0700304 }
305 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800306 ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
307 return BAD_VALUE;
Mathias Agopiana0c30e92010-06-04 18:26:32 -0700308}
309
Igor Murashkin7d2d1602013-11-12 18:02:20 -0800310int Surface::lockBuffer_DEPRECATED(android_native_buffer_t* buffer __attribute__((unused))) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800311 ALOGV("Surface::lockBuffer");
312 Mutex::Autolock lock(mMutex);
313 return OK;
314}
Mathias Agopian631f3582010-05-25 17:51:34 -0700315
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800316int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
317 ATRACE_CALL();
318 ALOGV("Surface::queueBuffer");
319 Mutex::Autolock lock(mMutex);
320 int64_t timestamp;
Andy McFadden3c256212013-08-16 14:55:39 -0700321 bool isAutoTimestamp = false;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800322 if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
Andy McFadden4b49e082013-08-02 15:31:45 -0700323 timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
Andy McFadden3c256212013-08-16 14:55:39 -0700324 isAutoTimestamp = true;
Andy McFadden4b49e082013-08-02 15:31:45 -0700325 ALOGV("Surface::queueBuffer making up timestamp: %.2f ms",
326 timestamp / 1000000.f);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800327 } else {
328 timestamp = mTimestamp;
Mathias Agopian631f3582010-05-25 17:51:34 -0700329 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800330 int i = getSlotFromBufferLocked(buffer);
331 if (i < 0) {
Taiju Tsuiki4d0cd3f2015-04-30 22:15:33 +0900332 if (fenceFd >= 0) {
333 close(fenceFd);
334 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800335 return i;
336 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800337
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800338
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800339 // Make sure the crop rectangle is entirely inside the buffer.
Pablo Ceballos60d69222015-08-07 14:47:20 -0700340 Rect crop(Rect::EMPTY_RECT);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800341 mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800342
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800343 sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
344 IGraphicBufferProducer::QueueBufferOutput output;
Andy McFadden3c256212013-08-16 14:55:39 -0700345 IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800346 mDataSpace, crop, mScalingMode, mTransform ^ mStickyTransform,
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700347 fence, mStickyTransform);
Dan Stoza5065a552015-03-17 16:23:42 -0700348
Dan Stozac62acbd2015-04-21 16:42:49 -0700349 if (mConnectedToCpu || mDirtyRegion.bounds() == Rect::INVALID_RECT) {
Dan Stoza5065a552015-03-17 16:23:42 -0700350 input.setSurfaceDamage(Region::INVALID_REGION);
351 } else {
Dan Stozadb4850c2015-06-25 16:10:18 -0700352 // Here we do two things:
353 // 1) The surface damage was specified using the OpenGL ES convention of
354 // the origin being in the bottom-left corner. Here we flip to the
355 // convention that the rest of the system uses (top-left corner) by
356 // subtracting all top/bottom coordinates from the buffer height.
357 // 2) If the buffer is coming in rotated (for example, because the EGL
358 // implementation is reacting to the transform hint coming back from
359 // SurfaceFlinger), the surface damage needs to be rotated the
360 // opposite direction, since it was generated assuming an unrotated
361 // buffer (the app doesn't know that the EGL implementation is
362 // reacting to the transform hint behind its back). The
363 // transformations in the switch statement below apply those
364 // complementary rotations (e.g., if 90 degrees, rotate 270 degrees).
365
366 int width = buffer->width;
Dan Stoza0e65e6c2015-05-26 13:22:27 -0700367 int height = buffer->height;
Dan Stozadb4850c2015-06-25 16:10:18 -0700368 bool rotated90 = (mTransform ^ mStickyTransform) &
369 NATIVE_WINDOW_TRANSFORM_ROT_90;
370 if (rotated90) {
371 std::swap(width, height);
Dan Stoza0e65e6c2015-05-26 13:22:27 -0700372 }
Dan Stozadb4850c2015-06-25 16:10:18 -0700373
Dan Stoza5065a552015-03-17 16:23:42 -0700374 Region flippedRegion;
375 for (auto rect : mDirtyRegion) {
Dan Stozadb4850c2015-06-25 16:10:18 -0700376 int left = rect.left;
377 int right = rect.right;
378 int top = height - rect.bottom; // Flip from OpenGL convention
379 int bottom = height - rect.top; // Flip from OpenGL convention
380 switch (mTransform ^ mStickyTransform) {
381 case NATIVE_WINDOW_TRANSFORM_ROT_90: {
382 // Rotate 270 degrees
383 Rect flippedRect{top, width - right, bottom, width - left};
384 flippedRegion.orSelf(flippedRect);
385 break;
386 }
387 case NATIVE_WINDOW_TRANSFORM_ROT_180: {
388 // Rotate 180 degrees
389 Rect flippedRect{width - right, height - bottom,
390 width - left, height - top};
391 flippedRegion.orSelf(flippedRect);
392 break;
393 }
394 case NATIVE_WINDOW_TRANSFORM_ROT_270: {
395 // Rotate 90 degrees
396 Rect flippedRect{height - bottom, left,
397 height - top, right};
398 flippedRegion.orSelf(flippedRect);
399 break;
400 }
401 default: {
402 Rect flippedRect{left, top, right, bottom};
403 flippedRegion.orSelf(flippedRect);
404 break;
405 }
406 }
Dan Stoza5065a552015-03-17 16:23:42 -0700407 }
408
409 input.setSurfaceDamage(flippedRegion);
410 }
411
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800412 status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
413 if (err != OK) {
414 ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
415 }
416 uint32_t numPendingBuffers = 0;
Ruben Brunk1681d952014-06-27 15:51:55 -0700417 uint32_t hint = 0;
418 output.deflate(&mDefaultWidth, &mDefaultHeight, &hint,
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800419 &numPendingBuffers);
tedbo1e7fa9e2011-06-22 15:52:53 -0700420
Ruben Brunk1681d952014-06-27 15:51:55 -0700421 // Disable transform hint if sticky transform is set.
422 if (mStickyTransform == 0) {
423 mTransformHint = hint;
424 }
425
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800426 mConsumerRunningBehind = (numPendingBuffers >= 2);
Mathias Agopian631f3582010-05-25 17:51:34 -0700427
Dan Stozac62acbd2015-04-21 16:42:49 -0700428 if (!mConnectedToCpu) {
429 // Clear surface damage back to full-buffer
430 mDirtyRegion = Region::INVALID_REGION;
431 }
Dan Stoza5065a552015-03-17 16:23:42 -0700432
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800433 return err;
434}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700435
Mathias Agopiana67932f2011-04-20 14:20:59 -0700436int Surface::query(int what, int* value) const {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800437 ATRACE_CALL();
438 ALOGV("Surface::query");
439 { // scope for the lock
440 Mutex::Autolock lock(mMutex);
441 switch (what) {
442 case NATIVE_WINDOW_FORMAT:
443 if (mReqFormat) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800444 *value = static_cast<int>(mReqFormat);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800445 return NO_ERROR;
446 }
447 break;
448 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
449 sp<ISurfaceComposer> composer(
450 ComposerService::getComposerService());
451 if (composer->authenticateSurfaceTexture(mGraphicBufferProducer)) {
452 *value = 1;
453 } else {
454 *value = 0;
455 }
456 return NO_ERROR;
457 }
458 case NATIVE_WINDOW_CONCRETE_TYPE:
459 *value = NATIVE_WINDOW_SURFACE;
460 return NO_ERROR;
461 case NATIVE_WINDOW_DEFAULT_WIDTH:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800462 *value = static_cast<int>(
463 mUserWidth ? mUserWidth : mDefaultWidth);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800464 return NO_ERROR;
465 case NATIVE_WINDOW_DEFAULT_HEIGHT:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800466 *value = static_cast<int>(
467 mUserHeight ? mUserHeight : mDefaultHeight);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800468 return NO_ERROR;
469 case NATIVE_WINDOW_TRANSFORM_HINT:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800470 *value = static_cast<int>(mTransformHint);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800471 return NO_ERROR;
472 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: {
473 status_t err = NO_ERROR;
474 if (!mConsumerRunningBehind) {
475 *value = 0;
476 } else {
477 err = mGraphicBufferProducer->query(what, value);
478 if (err == NO_ERROR) {
479 mConsumerRunningBehind = *value;
480 }
481 }
482 return err;
483 }
484 }
Jamie Gennis391bbe22011-03-14 15:00:06 -0700485 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800486 return mGraphicBufferProducer->query(what, value);
Eino-Ville Talvala1d01a122011-02-18 11:02:42 -0800487}
488
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800489int Surface::perform(int operation, va_list args)
490{
491 int res = NO_ERROR;
492 switch (operation) {
493 case NATIVE_WINDOW_CONNECT:
494 // deprecated. must return NO_ERROR.
495 break;
496 case NATIVE_WINDOW_DISCONNECT:
497 // deprecated. must return NO_ERROR.
498 break;
499 case NATIVE_WINDOW_SET_USAGE:
500 res = dispatchSetUsage(args);
501 break;
502 case NATIVE_WINDOW_SET_CROP:
503 res = dispatchSetCrop(args);
504 break;
505 case NATIVE_WINDOW_SET_BUFFER_COUNT:
506 res = dispatchSetBufferCount(args);
507 break;
508 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
509 res = dispatchSetBuffersGeometry(args);
510 break;
511 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
512 res = dispatchSetBuffersTransform(args);
513 break;
Ruben Brunk1681d952014-06-27 15:51:55 -0700514 case NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM:
515 res = dispatchSetBuffersStickyTransform(args);
516 break;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800517 case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
518 res = dispatchSetBuffersTimestamp(args);
519 break;
520 case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
521 res = dispatchSetBuffersDimensions(args);
522 break;
523 case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS:
524 res = dispatchSetBuffersUserDimensions(args);
525 break;
526 case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
527 res = dispatchSetBuffersFormat(args);
528 break;
529 case NATIVE_WINDOW_LOCK:
530 res = dispatchLock(args);
531 break;
532 case NATIVE_WINDOW_UNLOCK_AND_POST:
533 res = dispatchUnlockAndPost(args);
534 break;
535 case NATIVE_WINDOW_SET_SCALING_MODE:
536 res = dispatchSetScalingMode(args);
537 break;
538 case NATIVE_WINDOW_API_CONNECT:
539 res = dispatchConnect(args);
540 break;
541 case NATIVE_WINDOW_API_DISCONNECT:
542 res = dispatchDisconnect(args);
543 break;
Rachad7cb0d392014-07-29 17:53:53 -0700544 case NATIVE_WINDOW_SET_SIDEBAND_STREAM:
545 res = dispatchSetSidebandStream(args);
546 break;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800547 case NATIVE_WINDOW_SET_BUFFERS_DATASPACE:
548 res = dispatchSetBuffersDataSpace(args);
549 break;
Dan Stoza5065a552015-03-17 16:23:42 -0700550 case NATIVE_WINDOW_SET_SURFACE_DAMAGE:
551 res = dispatchSetSurfaceDamage(args);
552 break;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800553 default:
554 res = NAME_NOT_FOUND;
555 break;
556 }
557 return res;
558}
Mathias Agopiana138f892010-05-21 17:24:35 -0700559
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800560int Surface::dispatchConnect(va_list args) {
561 int api = va_arg(args, int);
562 return connect(api);
563}
Mathias Agopian55fa2512010-03-11 15:06:54 -0800564
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800565int Surface::dispatchDisconnect(va_list args) {
566 int api = va_arg(args, int);
567 return disconnect(api);
568}
569
570int Surface::dispatchSetUsage(va_list args) {
571 int usage = va_arg(args, int);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800572 return setUsage(static_cast<uint32_t>(usage));
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800573}
574
575int Surface::dispatchSetCrop(va_list args) {
576 android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
577 return setCrop(reinterpret_cast<Rect const*>(rect));
578}
579
580int Surface::dispatchSetBufferCount(va_list args) {
581 size_t bufferCount = va_arg(args, size_t);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800582 return setBufferCount(static_cast<int32_t>(bufferCount));
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800583}
584
585int Surface::dispatchSetBuffersGeometry(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800586 uint32_t width = va_arg(args, uint32_t);
587 uint32_t height = va_arg(args, uint32_t);
588 PixelFormat format = va_arg(args, PixelFormat);
589 int err = setBuffersDimensions(width, height);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800590 if (err != 0) {
591 return err;
592 }
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800593 return setBuffersFormat(format);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800594}
595
596int Surface::dispatchSetBuffersDimensions(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800597 uint32_t width = va_arg(args, uint32_t);
598 uint32_t height = va_arg(args, uint32_t);
599 return setBuffersDimensions(width, height);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800600}
601
602int Surface::dispatchSetBuffersUserDimensions(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800603 uint32_t width = va_arg(args, uint32_t);
604 uint32_t height = va_arg(args, uint32_t);
605 return setBuffersUserDimensions(width, height);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800606}
607
608int Surface::dispatchSetBuffersFormat(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800609 PixelFormat format = va_arg(args, PixelFormat);
610 return setBuffersFormat(format);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800611}
612
613int Surface::dispatchSetScalingMode(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800614 int mode = va_arg(args, int);
615 return setScalingMode(mode);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800616}
617
618int Surface::dispatchSetBuffersTransform(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800619 uint32_t transform = va_arg(args, uint32_t);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800620 return setBuffersTransform(transform);
621}
622
Ruben Brunk1681d952014-06-27 15:51:55 -0700623int Surface::dispatchSetBuffersStickyTransform(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800624 uint32_t transform = va_arg(args, uint32_t);
Ruben Brunk1681d952014-06-27 15:51:55 -0700625 return setBuffersStickyTransform(transform);
626}
627
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800628int Surface::dispatchSetBuffersTimestamp(va_list args) {
629 int64_t timestamp = va_arg(args, int64_t);
630 return setBuffersTimestamp(timestamp);
631}
632
633int Surface::dispatchLock(va_list args) {
634 ANativeWindow_Buffer* outBuffer = va_arg(args, ANativeWindow_Buffer*);
635 ARect* inOutDirtyBounds = va_arg(args, ARect*);
636 return lock(outBuffer, inOutDirtyBounds);
637}
638
Igor Murashkin7d2d1602013-11-12 18:02:20 -0800639int Surface::dispatchUnlockAndPost(va_list args __attribute__((unused))) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800640 return unlockAndPost();
641}
642
Rachad7cb0d392014-07-29 17:53:53 -0700643int Surface::dispatchSetSidebandStream(va_list args) {
644 native_handle_t* sH = va_arg(args, native_handle_t*);
645 sp<NativeHandle> sidebandHandle = NativeHandle::create(sH, false);
646 setSidebandStream(sidebandHandle);
647 return OK;
648}
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800649
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800650int Surface::dispatchSetBuffersDataSpace(va_list args) {
651 android_dataspace dataspace =
652 static_cast<android_dataspace>(va_arg(args, int));
653 return setBuffersDataSpace(dataspace);
654}
655
Dan Stoza5065a552015-03-17 16:23:42 -0700656int Surface::dispatchSetSurfaceDamage(va_list args) {
657 android_native_rect_t* rects = va_arg(args, android_native_rect_t*);
658 size_t numRects = va_arg(args, size_t);
659 setSurfaceDamage(rects, numRects);
660 return NO_ERROR;
661}
662
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800663int Surface::connect(int api) {
Dan Stoza966b98b2015-03-02 22:12:37 -0800664 static sp<IProducerListener> listener = new DummyProducerListener();
665 return connect(api, listener);
666}
667
668int Surface::connect(int api, const sp<IProducerListener>& listener) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800669 ATRACE_CALL();
670 ALOGV("Surface::connect");
671 Mutex::Autolock lock(mMutex);
672 IGraphicBufferProducer::QueueBufferOutput output;
Dan Stozaf0eaf252014-03-21 13:05:51 -0700673 int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800674 if (err == NO_ERROR) {
675 uint32_t numPendingBuffers = 0;
Ruben Brunk1681d952014-06-27 15:51:55 -0700676 uint32_t hint = 0;
677 output.deflate(&mDefaultWidth, &mDefaultHeight, &hint,
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800678 &numPendingBuffers);
Ruben Brunk1681d952014-06-27 15:51:55 -0700679
680 // Disable transform hint if sticky transform is set.
681 if (mStickyTransform == 0) {
682 mTransformHint = hint;
683 }
684
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800685 mConsumerRunningBehind = (numPendingBuffers >= 2);
686 }
687 if (!err && api == NATIVE_WINDOW_API_CPU) {
688 mConnectedToCpu = true;
Dan Stoza5065a552015-03-17 16:23:42 -0700689 // Clear the dirty region in case we're switching from a non-CPU API
690 mDirtyRegion.clear();
691 } else if (!err) {
692 // Initialize the dirty region for tracking surface damage
693 mDirtyRegion = Region::INVALID_REGION;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800694 }
Dan Stoza5065a552015-03-17 16:23:42 -0700695
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800696 return err;
697}
698
Mathias Agopian365857d2013-09-11 19:35:45 -0700699
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800700int Surface::disconnect(int api) {
701 ATRACE_CALL();
702 ALOGV("Surface::disconnect");
703 Mutex::Autolock lock(mMutex);
704 freeAllBuffers();
705 int err = mGraphicBufferProducer->disconnect(api);
706 if (!err) {
707 mReqFormat = 0;
708 mReqWidth = 0;
709 mReqHeight = 0;
710 mReqUsage = 0;
711 mCrop.clear();
712 mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
713 mTransform = 0;
Ruben Brunk1681d952014-06-27 15:51:55 -0700714 mStickyTransform = 0;
715
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800716 if (api == NATIVE_WINDOW_API_CPU) {
717 mConnectedToCpu = false;
718 }
719 }
720 return err;
721}
722
Dan Stozad9c49712015-04-27 11:06:01 -0700723int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
Dan Stoza231832e2015-03-11 11:55:01 -0700724 sp<Fence>* outFence) {
725 ATRACE_CALL();
726 ALOGV("Surface::detachNextBuffer");
727
728 if (outBuffer == NULL || outFence == NULL) {
729 return BAD_VALUE;
730 }
731
732 Mutex::Autolock lock(mMutex);
733
734 sp<GraphicBuffer> buffer(NULL);
735 sp<Fence> fence(NULL);
736 status_t result = mGraphicBufferProducer->detachNextBuffer(
737 &buffer, &fence);
738 if (result != NO_ERROR) {
739 return result;
740 }
741
Dan Stozad9c49712015-04-27 11:06:01 -0700742 *outBuffer = buffer;
Dan Stoza231832e2015-03-11 11:55:01 -0700743 if (fence != NULL && fence->isValid()) {
744 *outFence = fence;
745 } else {
746 *outFence = Fence::NO_FENCE;
747 }
748
749 return NO_ERROR;
750}
751
752int Surface::attachBuffer(ANativeWindowBuffer* buffer)
753{
754 ATRACE_CALL();
755 ALOGV("Surface::attachBuffer");
756
757 Mutex::Autolock lock(mMutex);
758
759 sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer));
Dan Stoza812ed062015-06-02 15:45:22 -0700760 uint32_t priorGeneration = graphicBuffer->mGenerationNumber;
761 graphicBuffer->mGenerationNumber = mGenerationNumber;
Dan Stoza231832e2015-03-11 11:55:01 -0700762 int32_t attachedSlot = -1;
763 status_t result = mGraphicBufferProducer->attachBuffer(
764 &attachedSlot, graphicBuffer);
765 if (result != NO_ERROR) {
766 ALOGE("attachBuffer: IGraphicBufferProducer call failed (%d)", result);
Dan Stoza812ed062015-06-02 15:45:22 -0700767 graphicBuffer->mGenerationNumber = priorGeneration;
Dan Stoza231832e2015-03-11 11:55:01 -0700768 return result;
769 }
770 mSlots[attachedSlot].buffer = graphicBuffer;
771
772 return NO_ERROR;
773}
774
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800775int Surface::setUsage(uint32_t reqUsage)
776{
777 ALOGV("Surface::setUsage");
778 Mutex::Autolock lock(mMutex);
779 mReqUsage = reqUsage;
780 return OK;
781}
782
783int Surface::setCrop(Rect const* rect)
784{
785 ATRACE_CALL();
786
Pablo Ceballos60d69222015-08-07 14:47:20 -0700787 Rect realRect(Rect::EMPTY_RECT);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800788 if (rect == NULL || rect->isEmpty()) {
789 realRect.clear();
790 } else {
791 realRect = *rect;
Mathias Agopian55fa2512010-03-11 15:06:54 -0800792 }
793
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800794 ALOGV("Surface::setCrop rect=[%d %d %d %d]",
795 realRect.left, realRect.top, realRect.right, realRect.bottom);
796
797 Mutex::Autolock lock(mMutex);
798 mCrop = realRect;
799 return NO_ERROR;
800}
801
802int Surface::setBufferCount(int bufferCount)
803{
804 ATRACE_CALL();
805 ALOGV("Surface::setBufferCount");
806 Mutex::Autolock lock(mMutex);
807
Pablo Ceballose5b755a2015-08-13 16:18:19 -0700808 status_t err = NO_ERROR;
809 if (bufferCount == 0) {
810 err = mGraphicBufferProducer->setMaxDequeuedBufferCount(1);
811 } else {
812 int minUndequeuedBuffers = 0;
813 err = mGraphicBufferProducer->query(
814 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
815 if (err == NO_ERROR) {
816 err = mGraphicBufferProducer->setMaxDequeuedBufferCount(
817 bufferCount - minUndequeuedBuffers);
818 }
819 }
Mathias Agopian90147262010-01-22 11:47:55 -0800820
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700821 if (err == NO_ERROR) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800822 freeAllBuffers();
Mathias Agopian87a96ea2011-08-23 21:09:41 -0700823 }
824
Pablo Ceballose5b755a2015-08-13 16:18:19 -0700825 ALOGE_IF(err, "IGraphicBufferProducer::setBufferCount(%d) returned %s",
826 bufferCount, strerror(-err));
827
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700828 return err;
829}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700830
Pablo Ceballosfa455352015-08-12 17:47:47 -0700831int Surface::setMaxDequeuedBufferCount(int maxDequeuedBuffers) {
832 ATRACE_CALL();
833 ALOGV("Surface::setMaxDequeuedBufferCount");
834 Mutex::Autolock lock(mMutex);
835
836 status_t err = mGraphicBufferProducer->setMaxDequeuedBufferCount(
837 maxDequeuedBuffers);
838 ALOGE_IF(err, "IGraphicBufferProducer::setMaxDequeuedBufferCount(%d) "
839 "returned %s", maxDequeuedBuffers, strerror(-err));
840
841 if (err == NO_ERROR) {
842 freeAllBuffers();
843 }
844
845 return err;
846}
847
848int Surface::setAsyncMode(bool async) {
849 ATRACE_CALL();
850 ALOGV("Surface::setAsyncMode");
851 Mutex::Autolock lock(mMutex);
852
853 status_t err = mGraphicBufferProducer->setAsyncMode(async);
854 ALOGE_IF(err, "IGraphicBufferProducer::setAsyncMode(%d) returned %s",
855 async, strerror(-err));
856
857 if (err == NO_ERROR) {
858 freeAllBuffers();
859 }
860
861 return err;
862}
863
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800864int Surface::setBuffersDimensions(uint32_t width, uint32_t height)
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800865{
866 ATRACE_CALL();
867 ALOGV("Surface::setBuffersDimensions");
868
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800869 if ((width && !height) || (!width && height))
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800870 return BAD_VALUE;
871
872 Mutex::Autolock lock(mMutex);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800873 mReqWidth = width;
874 mReqHeight = height;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800875 return NO_ERROR;
876}
877
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800878int Surface::setBuffersUserDimensions(uint32_t width, uint32_t height)
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800879{
880 ATRACE_CALL();
881 ALOGV("Surface::setBuffersUserDimensions");
882
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800883 if ((width && !height) || (!width && height))
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800884 return BAD_VALUE;
885
886 Mutex::Autolock lock(mMutex);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800887 mUserWidth = width;
888 mUserHeight = height;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800889 return NO_ERROR;
890}
891
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800892int Surface::setBuffersFormat(PixelFormat format)
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800893{
894 ALOGV("Surface::setBuffersFormat");
895
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800896 Mutex::Autolock lock(mMutex);
897 mReqFormat = format;
898 return NO_ERROR;
899}
900
901int Surface::setScalingMode(int mode)
902{
903 ATRACE_CALL();
904 ALOGV("Surface::setScalingMode(%d)", mode);
905
906 switch (mode) {
907 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
908 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
909 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
910 break;
911 default:
912 ALOGE("unknown scaling mode: %d", mode);
913 return BAD_VALUE;
914 }
915
916 Mutex::Autolock lock(mMutex);
917 mScalingMode = mode;
918 return NO_ERROR;
919}
920
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800921int Surface::setBuffersTransform(uint32_t transform)
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800922{
923 ATRACE_CALL();
924 ALOGV("Surface::setBuffersTransform");
925 Mutex::Autolock lock(mMutex);
926 mTransform = transform;
927 return NO_ERROR;
928}
929
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800930int Surface::setBuffersStickyTransform(uint32_t transform)
Ruben Brunk1681d952014-06-27 15:51:55 -0700931{
932 ATRACE_CALL();
933 ALOGV("Surface::setBuffersStickyTransform");
934 Mutex::Autolock lock(mMutex);
935 mStickyTransform = transform;
936 return NO_ERROR;
937}
938
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800939int Surface::setBuffersTimestamp(int64_t timestamp)
940{
941 ALOGV("Surface::setBuffersTimestamp");
942 Mutex::Autolock lock(mMutex);
943 mTimestamp = timestamp;
944 return NO_ERROR;
945}
946
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800947int Surface::setBuffersDataSpace(android_dataspace dataSpace)
948{
949 ALOGV("Surface::setBuffersDataSpace");
950 Mutex::Autolock lock(mMutex);
951 mDataSpace = dataSpace;
952 return NO_ERROR;
953}
954
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800955void Surface::freeAllBuffers() {
956 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
957 mSlots[i].buffer = 0;
958 }
959}
960
Dan Stoza5065a552015-03-17 16:23:42 -0700961void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) {
962 ATRACE_CALL();
963 ALOGV("Surface::setSurfaceDamage");
964 Mutex::Autolock lock(mMutex);
965
Dan Stozac62acbd2015-04-21 16:42:49 -0700966 if (mConnectedToCpu || numRects == 0) {
Dan Stoza5065a552015-03-17 16:23:42 -0700967 mDirtyRegion = Region::INVALID_REGION;
968 return;
969 }
970
971 mDirtyRegion.clear();
972 for (size_t r = 0; r < numRects; ++r) {
973 // We intentionally flip top and bottom here, since because they're
974 // specified with a bottom-left origin, top > bottom, which fails
975 // validation in the Region class. We will fix this up when we flip to a
976 // top-left origin in queueBuffer.
977 Rect rect(rects[r].left, rects[r].bottom, rects[r].right, rects[r].top);
978 mDirtyRegion.orSelf(rect);
979 }
980}
981
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800982// ----------------------------------------------------------------------
983// the lock/unlock APIs must be used from the same thread
984
985static status_t copyBlt(
986 const sp<GraphicBuffer>& dst,
987 const sp<GraphicBuffer>& src,
988 const Region& reg)
989{
990 // src and dst with, height and format must be identical. no verification
991 // is done here.
992 status_t err;
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800993 uint8_t* src_bits = NULL;
994 err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(),
995 reinterpret_cast<void**>(&src_bits));
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800996 ALOGE_IF(err, "error locking src buffer %s", strerror(-err));
997
998 uint8_t* dst_bits = NULL;
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800999 err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(),
1000 reinterpret_cast<void**>(&dst_bits));
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001001 ALOGE_IF(err, "error locking dst buffer %s", strerror(-err));
1002
1003 Region::const_iterator head(reg.begin());
1004 Region::const_iterator tail(reg.end());
1005 if (head != tail && src_bits && dst_bits) {
1006 const size_t bpp = bytesPerPixel(src->format);
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001007 const size_t dbpr = static_cast<uint32_t>(dst->stride) * bpp;
1008 const size_t sbpr = static_cast<uint32_t>(src->stride) * bpp;
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001009
1010 while (head != tail) {
1011 const Rect& r(*head++);
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001012 int32_t h = r.height();
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001013 if (h <= 0) continue;
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001014 size_t size = static_cast<uint32_t>(r.width()) * bpp;
1015 uint8_t const * s = src_bits +
1016 static_cast<uint32_t>(r.left + src->stride * r.top) * bpp;
1017 uint8_t * d = dst_bits +
1018 static_cast<uint32_t>(r.left + dst->stride * r.top) * bpp;
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001019 if (dbpr==sbpr && size==sbpr) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001020 size *= static_cast<size_t>(h);
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001021 h = 1;
1022 }
1023 do {
1024 memcpy(d, s, size);
1025 d += dbpr;
1026 s += sbpr;
1027 } while (--h > 0);
1028 }
1029 }
1030
1031 if (src_bits)
1032 src->unlock();
1033
1034 if (dst_bits)
1035 dst->unlock();
1036
1037 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001038}
1039
Mathias Agopiana138f892010-05-21 17:24:35 -07001040// ----------------------------------------------------------------------------
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001041
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001042status_t Surface::lock(
1043 ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
1044{
1045 if (mLockedBuffer != 0) {
1046 ALOGE("Surface::lock failed, already locked");
1047 return INVALID_OPERATION;
1048 }
1049
1050 if (!mConnectedToCpu) {
1051 int err = Surface::connect(NATIVE_WINDOW_API_CPU);
1052 if (err) {
1053 return err;
1054 }
1055 // we're intending to do software rendering from this point
1056 setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
1057 }
1058
1059 ANativeWindowBuffer* out;
1060 int fenceFd = -1;
1061 status_t err = dequeueBuffer(&out, &fenceFd);
1062 ALOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
1063 if (err == NO_ERROR) {
1064 sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001065 const Rect bounds(backBuffer->width, backBuffer->height);
1066
1067 Region newDirtyRegion;
1068 if (inOutDirtyBounds) {
1069 newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds));
1070 newDirtyRegion.andSelf(bounds);
1071 } else {
1072 newDirtyRegion.set(bounds);
1073 }
1074
1075 // figure out if we can copy the frontbuffer back
1076 const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
1077 const bool canCopyBack = (frontBuffer != 0 &&
1078 backBuffer->width == frontBuffer->width &&
1079 backBuffer->height == frontBuffer->height &&
1080 backBuffer->format == frontBuffer->format);
1081
1082 if (canCopyBack) {
1083 // copy the area that is invalid and not repainted this round
1084 const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
1085 if (!copyback.isEmpty())
1086 copyBlt(backBuffer, frontBuffer, copyback);
1087 } else {
1088 // if we can't copy-back anything, modify the user's dirty
1089 // region to make sure they redraw the whole buffer
1090 newDirtyRegion.set(bounds);
1091 mDirtyRegion.clear();
1092 Mutex::Autolock lock(mMutex);
1093 for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
1094 mSlots[i].dirtyRegion.clear();
1095 }
1096 }
1097
1098
1099 { // scope for the lock
1100 Mutex::Autolock lock(mMutex);
1101 int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
1102 if (backBufferSlot >= 0) {
1103 Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
1104 mDirtyRegion.subtract(dirtyRegion);
1105 dirtyRegion = newDirtyRegion;
1106 }
1107 }
1108
1109 mDirtyRegion.orSelf(newDirtyRegion);
1110 if (inOutDirtyBounds) {
1111 *inOutDirtyBounds = newDirtyRegion.getBounds();
1112 }
1113
1114 void* vaddr;
Francis Hart8f396012014-04-01 15:30:53 +03001115 status_t res = backBuffer->lockAsync(
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001116 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
Francis Hart8f396012014-04-01 15:30:53 +03001117 newDirtyRegion.bounds(), &vaddr, fenceFd);
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001118
1119 ALOGW_IF(res, "failed locking buffer (handle = %p)",
1120 backBuffer->handle);
1121
1122 if (res != 0) {
1123 err = INVALID_OPERATION;
1124 } else {
1125 mLockedBuffer = backBuffer;
1126 outBuffer->width = backBuffer->width;
1127 outBuffer->height = backBuffer->height;
1128 outBuffer->stride = backBuffer->stride;
1129 outBuffer->format = backBuffer->format;
1130 outBuffer->bits = vaddr;
1131 }
1132 }
1133 return err;
1134}
1135
1136status_t Surface::unlockAndPost()
1137{
1138 if (mLockedBuffer == 0) {
1139 ALOGE("Surface::unlockAndPost failed, no locked buffer");
1140 return INVALID_OPERATION;
1141 }
1142
Francis Hart8f396012014-04-01 15:30:53 +03001143 int fd = -1;
1144 status_t err = mLockedBuffer->unlockAsync(&fd);
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001145 ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
1146
Francis Hart8f396012014-04-01 15:30:53 +03001147 err = queueBuffer(mLockedBuffer.get(), fd);
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001148 ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
1149 mLockedBuffer->handle, strerror(-err));
1150
1151 mPostedBuffer = mLockedBuffer;
1152 mLockedBuffer = 0;
1153 return err;
1154}
1155
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001156}; // namespace android