blob: 7578a3db29efbd577fccb707ae04118cd67b47c0 [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;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700553 case NATIVE_WINDOW_SET_SINGLE_BUFFER_MODE:
554 res = dispatchSetSingleBufferMode(args);
555 break;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800556 default:
557 res = NAME_NOT_FOUND;
558 break;
559 }
560 return res;
561}
Mathias Agopiana138f892010-05-21 17:24:35 -0700562
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800563int Surface::dispatchConnect(va_list args) {
564 int api = va_arg(args, int);
565 return connect(api);
566}
Mathias Agopian55fa2512010-03-11 15:06:54 -0800567
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800568int Surface::dispatchDisconnect(va_list args) {
569 int api = va_arg(args, int);
570 return disconnect(api);
571}
572
573int Surface::dispatchSetUsage(va_list args) {
574 int usage = va_arg(args, int);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800575 return setUsage(static_cast<uint32_t>(usage));
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800576}
577
578int Surface::dispatchSetCrop(va_list args) {
579 android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
580 return setCrop(reinterpret_cast<Rect const*>(rect));
581}
582
583int Surface::dispatchSetBufferCount(va_list args) {
584 size_t bufferCount = va_arg(args, size_t);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800585 return setBufferCount(static_cast<int32_t>(bufferCount));
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800586}
587
588int Surface::dispatchSetBuffersGeometry(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800589 uint32_t width = va_arg(args, uint32_t);
590 uint32_t height = va_arg(args, uint32_t);
591 PixelFormat format = va_arg(args, PixelFormat);
592 int err = setBuffersDimensions(width, height);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800593 if (err != 0) {
594 return err;
595 }
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800596 return setBuffersFormat(format);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800597}
598
599int Surface::dispatchSetBuffersDimensions(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800600 uint32_t width = va_arg(args, uint32_t);
601 uint32_t height = va_arg(args, uint32_t);
602 return setBuffersDimensions(width, height);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800603}
604
605int Surface::dispatchSetBuffersUserDimensions(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800606 uint32_t width = va_arg(args, uint32_t);
607 uint32_t height = va_arg(args, uint32_t);
608 return setBuffersUserDimensions(width, height);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800609}
610
611int Surface::dispatchSetBuffersFormat(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800612 PixelFormat format = va_arg(args, PixelFormat);
613 return setBuffersFormat(format);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800614}
615
616int Surface::dispatchSetScalingMode(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800617 int mode = va_arg(args, int);
618 return setScalingMode(mode);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800619}
620
621int Surface::dispatchSetBuffersTransform(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800622 uint32_t transform = va_arg(args, uint32_t);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800623 return setBuffersTransform(transform);
624}
625
Ruben Brunk1681d952014-06-27 15:51:55 -0700626int Surface::dispatchSetBuffersStickyTransform(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800627 uint32_t transform = va_arg(args, uint32_t);
Ruben Brunk1681d952014-06-27 15:51:55 -0700628 return setBuffersStickyTransform(transform);
629}
630
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800631int Surface::dispatchSetBuffersTimestamp(va_list args) {
632 int64_t timestamp = va_arg(args, int64_t);
633 return setBuffersTimestamp(timestamp);
634}
635
636int Surface::dispatchLock(va_list args) {
637 ANativeWindow_Buffer* outBuffer = va_arg(args, ANativeWindow_Buffer*);
638 ARect* inOutDirtyBounds = va_arg(args, ARect*);
639 return lock(outBuffer, inOutDirtyBounds);
640}
641
Igor Murashkin7d2d1602013-11-12 18:02:20 -0800642int Surface::dispatchUnlockAndPost(va_list args __attribute__((unused))) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800643 return unlockAndPost();
644}
645
Rachad7cb0d392014-07-29 17:53:53 -0700646int Surface::dispatchSetSidebandStream(va_list args) {
647 native_handle_t* sH = va_arg(args, native_handle_t*);
648 sp<NativeHandle> sidebandHandle = NativeHandle::create(sH, false);
649 setSidebandStream(sidebandHandle);
650 return OK;
651}
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800652
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800653int Surface::dispatchSetBuffersDataSpace(va_list args) {
654 android_dataspace dataspace =
655 static_cast<android_dataspace>(va_arg(args, int));
656 return setBuffersDataSpace(dataspace);
657}
658
Dan Stoza5065a552015-03-17 16:23:42 -0700659int Surface::dispatchSetSurfaceDamage(va_list args) {
660 android_native_rect_t* rects = va_arg(args, android_native_rect_t*);
661 size_t numRects = va_arg(args, size_t);
662 setSurfaceDamage(rects, numRects);
663 return NO_ERROR;
664}
665
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700666int Surface::dispatchSetSingleBufferMode(va_list args) {
667 bool singleBufferMode = va_arg(args, int);
668 setSingleBufferMode(singleBufferMode);
669 return NO_ERROR;
670}
671
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800672int Surface::connect(int api) {
Dan Stoza966b98b2015-03-02 22:12:37 -0800673 static sp<IProducerListener> listener = new DummyProducerListener();
674 return connect(api, listener);
675}
676
677int Surface::connect(int api, const sp<IProducerListener>& listener) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800678 ATRACE_CALL();
679 ALOGV("Surface::connect");
680 Mutex::Autolock lock(mMutex);
681 IGraphicBufferProducer::QueueBufferOutput output;
Dan Stozaf0eaf252014-03-21 13:05:51 -0700682 int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800683 if (err == NO_ERROR) {
684 uint32_t numPendingBuffers = 0;
Ruben Brunk1681d952014-06-27 15:51:55 -0700685 uint32_t hint = 0;
686 output.deflate(&mDefaultWidth, &mDefaultHeight, &hint,
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800687 &numPendingBuffers);
Ruben Brunk1681d952014-06-27 15:51:55 -0700688
689 // Disable transform hint if sticky transform is set.
690 if (mStickyTransform == 0) {
691 mTransformHint = hint;
692 }
693
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800694 mConsumerRunningBehind = (numPendingBuffers >= 2);
695 }
696 if (!err && api == NATIVE_WINDOW_API_CPU) {
697 mConnectedToCpu = true;
Dan Stoza5065a552015-03-17 16:23:42 -0700698 // Clear the dirty region in case we're switching from a non-CPU API
699 mDirtyRegion.clear();
700 } else if (!err) {
701 // Initialize the dirty region for tracking surface damage
702 mDirtyRegion = Region::INVALID_REGION;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800703 }
Dan Stoza5065a552015-03-17 16:23:42 -0700704
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800705 return err;
706}
707
Mathias Agopian365857d2013-09-11 19:35:45 -0700708
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800709int Surface::disconnect(int api) {
710 ATRACE_CALL();
711 ALOGV("Surface::disconnect");
712 Mutex::Autolock lock(mMutex);
713 freeAllBuffers();
714 int err = mGraphicBufferProducer->disconnect(api);
715 if (!err) {
716 mReqFormat = 0;
717 mReqWidth = 0;
718 mReqHeight = 0;
719 mReqUsage = 0;
720 mCrop.clear();
721 mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
722 mTransform = 0;
Ruben Brunk1681d952014-06-27 15:51:55 -0700723 mStickyTransform = 0;
724
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800725 if (api == NATIVE_WINDOW_API_CPU) {
726 mConnectedToCpu = false;
727 }
728 }
729 return err;
730}
731
Dan Stozad9c49712015-04-27 11:06:01 -0700732int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
Dan Stoza231832e2015-03-11 11:55:01 -0700733 sp<Fence>* outFence) {
734 ATRACE_CALL();
735 ALOGV("Surface::detachNextBuffer");
736
737 if (outBuffer == NULL || outFence == NULL) {
738 return BAD_VALUE;
739 }
740
741 Mutex::Autolock lock(mMutex);
742
743 sp<GraphicBuffer> buffer(NULL);
744 sp<Fence> fence(NULL);
745 status_t result = mGraphicBufferProducer->detachNextBuffer(
746 &buffer, &fence);
747 if (result != NO_ERROR) {
748 return result;
749 }
750
Dan Stozad9c49712015-04-27 11:06:01 -0700751 *outBuffer = buffer;
Dan Stoza231832e2015-03-11 11:55:01 -0700752 if (fence != NULL && fence->isValid()) {
753 *outFence = fence;
754 } else {
755 *outFence = Fence::NO_FENCE;
756 }
757
758 return NO_ERROR;
759}
760
761int Surface::attachBuffer(ANativeWindowBuffer* buffer)
762{
763 ATRACE_CALL();
764 ALOGV("Surface::attachBuffer");
765
766 Mutex::Autolock lock(mMutex);
767
768 sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer));
Dan Stoza812ed062015-06-02 15:45:22 -0700769 uint32_t priorGeneration = graphicBuffer->mGenerationNumber;
770 graphicBuffer->mGenerationNumber = mGenerationNumber;
Dan Stoza231832e2015-03-11 11:55:01 -0700771 int32_t attachedSlot = -1;
772 status_t result = mGraphicBufferProducer->attachBuffer(
773 &attachedSlot, graphicBuffer);
774 if (result != NO_ERROR) {
775 ALOGE("attachBuffer: IGraphicBufferProducer call failed (%d)", result);
Dan Stoza812ed062015-06-02 15:45:22 -0700776 graphicBuffer->mGenerationNumber = priorGeneration;
Dan Stoza231832e2015-03-11 11:55:01 -0700777 return result;
778 }
779 mSlots[attachedSlot].buffer = graphicBuffer;
780
781 return NO_ERROR;
782}
783
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800784int Surface::setUsage(uint32_t reqUsage)
785{
786 ALOGV("Surface::setUsage");
787 Mutex::Autolock lock(mMutex);
788 mReqUsage = reqUsage;
789 return OK;
790}
791
792int Surface::setCrop(Rect const* rect)
793{
794 ATRACE_CALL();
795
Pablo Ceballos60d69222015-08-07 14:47:20 -0700796 Rect realRect(Rect::EMPTY_RECT);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800797 if (rect == NULL || rect->isEmpty()) {
798 realRect.clear();
799 } else {
800 realRect = *rect;
Mathias Agopian55fa2512010-03-11 15:06:54 -0800801 }
802
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800803 ALOGV("Surface::setCrop rect=[%d %d %d %d]",
804 realRect.left, realRect.top, realRect.right, realRect.bottom);
805
806 Mutex::Autolock lock(mMutex);
807 mCrop = realRect;
808 return NO_ERROR;
809}
810
811int Surface::setBufferCount(int bufferCount)
812{
813 ATRACE_CALL();
814 ALOGV("Surface::setBufferCount");
815 Mutex::Autolock lock(mMutex);
816
Pablo Ceballose5b755a2015-08-13 16:18:19 -0700817 status_t err = NO_ERROR;
818 if (bufferCount == 0) {
819 err = mGraphicBufferProducer->setMaxDequeuedBufferCount(1);
820 } else {
821 int minUndequeuedBuffers = 0;
822 err = mGraphicBufferProducer->query(
823 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
824 if (err == NO_ERROR) {
825 err = mGraphicBufferProducer->setMaxDequeuedBufferCount(
826 bufferCount - minUndequeuedBuffers);
827 }
828 }
Mathias Agopian90147262010-01-22 11:47:55 -0800829
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700830 if (err == NO_ERROR) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800831 freeAllBuffers();
Mathias Agopian87a96ea2011-08-23 21:09:41 -0700832 }
833
Pablo Ceballose5b755a2015-08-13 16:18:19 -0700834 ALOGE_IF(err, "IGraphicBufferProducer::setBufferCount(%d) returned %s",
835 bufferCount, strerror(-err));
836
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700837 return err;
838}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700839
Pablo Ceballosfa455352015-08-12 17:47:47 -0700840int Surface::setMaxDequeuedBufferCount(int maxDequeuedBuffers) {
841 ATRACE_CALL();
842 ALOGV("Surface::setMaxDequeuedBufferCount");
843 Mutex::Autolock lock(mMutex);
844
845 status_t err = mGraphicBufferProducer->setMaxDequeuedBufferCount(
846 maxDequeuedBuffers);
847 ALOGE_IF(err, "IGraphicBufferProducer::setMaxDequeuedBufferCount(%d) "
848 "returned %s", maxDequeuedBuffers, strerror(-err));
849
850 if (err == NO_ERROR) {
851 freeAllBuffers();
852 }
853
854 return err;
855}
856
857int Surface::setAsyncMode(bool async) {
858 ATRACE_CALL();
859 ALOGV("Surface::setAsyncMode");
860 Mutex::Autolock lock(mMutex);
861
862 status_t err = mGraphicBufferProducer->setAsyncMode(async);
863 ALOGE_IF(err, "IGraphicBufferProducer::setAsyncMode(%d) returned %s",
864 async, strerror(-err));
865
866 if (err == NO_ERROR) {
867 freeAllBuffers();
868 }
869
870 return err;
871}
872
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700873int Surface::setSingleBufferMode(bool singleBufferMode) {
874 ATRACE_CALL();
875 ALOGV("Surface::setSingleBufferMode (%d)", singleBufferMode);
876 Mutex::Autolock lock(mMutex);
877
878 status_t err = mGraphicBufferProducer->setSingleBufferMode(
879 singleBufferMode);
880 ALOGE_IF(err, "IGraphicsBufferProducer::setSingleBufferMode(%d) returned"
881 "%s", singleBufferMode, strerror(-err));
882
883 return err;
884}
885
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800886int Surface::setBuffersDimensions(uint32_t width, uint32_t height)
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800887{
888 ATRACE_CALL();
889 ALOGV("Surface::setBuffersDimensions");
890
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800891 if ((width && !height) || (!width && height))
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800892 return BAD_VALUE;
893
894 Mutex::Autolock lock(mMutex);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800895 mReqWidth = width;
896 mReqHeight = height;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800897 return NO_ERROR;
898}
899
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800900int Surface::setBuffersUserDimensions(uint32_t width, uint32_t height)
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800901{
902 ATRACE_CALL();
903 ALOGV("Surface::setBuffersUserDimensions");
904
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800905 if ((width && !height) || (!width && height))
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800906 return BAD_VALUE;
907
908 Mutex::Autolock lock(mMutex);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800909 mUserWidth = width;
910 mUserHeight = height;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800911 return NO_ERROR;
912}
913
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800914int Surface::setBuffersFormat(PixelFormat format)
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800915{
916 ALOGV("Surface::setBuffersFormat");
917
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800918 Mutex::Autolock lock(mMutex);
919 mReqFormat = format;
920 return NO_ERROR;
921}
922
923int Surface::setScalingMode(int mode)
924{
925 ATRACE_CALL();
926 ALOGV("Surface::setScalingMode(%d)", mode);
927
928 switch (mode) {
929 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
930 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
931 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
932 break;
933 default:
934 ALOGE("unknown scaling mode: %d", mode);
935 return BAD_VALUE;
936 }
937
938 Mutex::Autolock lock(mMutex);
939 mScalingMode = mode;
940 return NO_ERROR;
941}
942
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800943int Surface::setBuffersTransform(uint32_t transform)
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800944{
945 ATRACE_CALL();
946 ALOGV("Surface::setBuffersTransform");
947 Mutex::Autolock lock(mMutex);
948 mTransform = transform;
949 return NO_ERROR;
950}
951
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800952int Surface::setBuffersStickyTransform(uint32_t transform)
Ruben Brunk1681d952014-06-27 15:51:55 -0700953{
954 ATRACE_CALL();
955 ALOGV("Surface::setBuffersStickyTransform");
956 Mutex::Autolock lock(mMutex);
957 mStickyTransform = transform;
958 return NO_ERROR;
959}
960
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800961int Surface::setBuffersTimestamp(int64_t timestamp)
962{
963 ALOGV("Surface::setBuffersTimestamp");
964 Mutex::Autolock lock(mMutex);
965 mTimestamp = timestamp;
966 return NO_ERROR;
967}
968
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800969int Surface::setBuffersDataSpace(android_dataspace dataSpace)
970{
971 ALOGV("Surface::setBuffersDataSpace");
972 Mutex::Autolock lock(mMutex);
973 mDataSpace = dataSpace;
974 return NO_ERROR;
975}
976
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800977void Surface::freeAllBuffers() {
978 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
979 mSlots[i].buffer = 0;
980 }
981}
982
Dan Stoza5065a552015-03-17 16:23:42 -0700983void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) {
984 ATRACE_CALL();
985 ALOGV("Surface::setSurfaceDamage");
986 Mutex::Autolock lock(mMutex);
987
Dan Stozac62acbd2015-04-21 16:42:49 -0700988 if (mConnectedToCpu || numRects == 0) {
Dan Stoza5065a552015-03-17 16:23:42 -0700989 mDirtyRegion = Region::INVALID_REGION;
990 return;
991 }
992
993 mDirtyRegion.clear();
994 for (size_t r = 0; r < numRects; ++r) {
995 // We intentionally flip top and bottom here, since because they're
996 // specified with a bottom-left origin, top > bottom, which fails
997 // validation in the Region class. We will fix this up when we flip to a
998 // top-left origin in queueBuffer.
999 Rect rect(rects[r].left, rects[r].bottom, rects[r].right, rects[r].top);
1000 mDirtyRegion.orSelf(rect);
1001 }
1002}
1003
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001004// ----------------------------------------------------------------------
1005// the lock/unlock APIs must be used from the same thread
1006
1007static status_t copyBlt(
1008 const sp<GraphicBuffer>& dst,
1009 const sp<GraphicBuffer>& src,
1010 const Region& reg)
1011{
1012 // src and dst with, height and format must be identical. no verification
1013 // is done here.
1014 status_t err;
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001015 uint8_t* src_bits = NULL;
1016 err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(),
1017 reinterpret_cast<void**>(&src_bits));
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001018 ALOGE_IF(err, "error locking src buffer %s", strerror(-err));
1019
1020 uint8_t* dst_bits = NULL;
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001021 err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(),
1022 reinterpret_cast<void**>(&dst_bits));
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001023 ALOGE_IF(err, "error locking dst buffer %s", strerror(-err));
1024
1025 Region::const_iterator head(reg.begin());
1026 Region::const_iterator tail(reg.end());
1027 if (head != tail && src_bits && dst_bits) {
1028 const size_t bpp = bytesPerPixel(src->format);
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001029 const size_t dbpr = static_cast<uint32_t>(dst->stride) * bpp;
1030 const size_t sbpr = static_cast<uint32_t>(src->stride) * bpp;
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001031
1032 while (head != tail) {
1033 const Rect& r(*head++);
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001034 int32_t h = r.height();
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001035 if (h <= 0) continue;
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001036 size_t size = static_cast<uint32_t>(r.width()) * bpp;
1037 uint8_t const * s = src_bits +
1038 static_cast<uint32_t>(r.left + src->stride * r.top) * bpp;
1039 uint8_t * d = dst_bits +
1040 static_cast<uint32_t>(r.left + dst->stride * r.top) * bpp;
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001041 if (dbpr==sbpr && size==sbpr) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001042 size *= static_cast<size_t>(h);
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001043 h = 1;
1044 }
1045 do {
1046 memcpy(d, s, size);
1047 d += dbpr;
1048 s += sbpr;
1049 } while (--h > 0);
1050 }
1051 }
1052
1053 if (src_bits)
1054 src->unlock();
1055
1056 if (dst_bits)
1057 dst->unlock();
1058
1059 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001060}
1061
Mathias Agopiana138f892010-05-21 17:24:35 -07001062// ----------------------------------------------------------------------------
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001063
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001064status_t Surface::lock(
1065 ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
1066{
1067 if (mLockedBuffer != 0) {
1068 ALOGE("Surface::lock failed, already locked");
1069 return INVALID_OPERATION;
1070 }
1071
1072 if (!mConnectedToCpu) {
1073 int err = Surface::connect(NATIVE_WINDOW_API_CPU);
1074 if (err) {
1075 return err;
1076 }
1077 // we're intending to do software rendering from this point
1078 setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
1079 }
1080
1081 ANativeWindowBuffer* out;
1082 int fenceFd = -1;
1083 status_t err = dequeueBuffer(&out, &fenceFd);
1084 ALOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
1085 if (err == NO_ERROR) {
1086 sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001087 const Rect bounds(backBuffer->width, backBuffer->height);
1088
1089 Region newDirtyRegion;
1090 if (inOutDirtyBounds) {
1091 newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds));
1092 newDirtyRegion.andSelf(bounds);
1093 } else {
1094 newDirtyRegion.set(bounds);
1095 }
1096
1097 // figure out if we can copy the frontbuffer back
1098 const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
1099 const bool canCopyBack = (frontBuffer != 0 &&
1100 backBuffer->width == frontBuffer->width &&
1101 backBuffer->height == frontBuffer->height &&
1102 backBuffer->format == frontBuffer->format);
1103
1104 if (canCopyBack) {
1105 // copy the area that is invalid and not repainted this round
1106 const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
1107 if (!copyback.isEmpty())
1108 copyBlt(backBuffer, frontBuffer, copyback);
1109 } else {
1110 // if we can't copy-back anything, modify the user's dirty
1111 // region to make sure they redraw the whole buffer
1112 newDirtyRegion.set(bounds);
1113 mDirtyRegion.clear();
1114 Mutex::Autolock lock(mMutex);
1115 for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
1116 mSlots[i].dirtyRegion.clear();
1117 }
1118 }
1119
1120
1121 { // scope for the lock
1122 Mutex::Autolock lock(mMutex);
1123 int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
1124 if (backBufferSlot >= 0) {
1125 Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
1126 mDirtyRegion.subtract(dirtyRegion);
1127 dirtyRegion = newDirtyRegion;
1128 }
1129 }
1130
1131 mDirtyRegion.orSelf(newDirtyRegion);
1132 if (inOutDirtyBounds) {
1133 *inOutDirtyBounds = newDirtyRegion.getBounds();
1134 }
1135
1136 void* vaddr;
Francis Hart8f396012014-04-01 15:30:53 +03001137 status_t res = backBuffer->lockAsync(
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001138 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
Francis Hart8f396012014-04-01 15:30:53 +03001139 newDirtyRegion.bounds(), &vaddr, fenceFd);
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001140
1141 ALOGW_IF(res, "failed locking buffer (handle = %p)",
1142 backBuffer->handle);
1143
1144 if (res != 0) {
1145 err = INVALID_OPERATION;
1146 } else {
1147 mLockedBuffer = backBuffer;
1148 outBuffer->width = backBuffer->width;
1149 outBuffer->height = backBuffer->height;
1150 outBuffer->stride = backBuffer->stride;
1151 outBuffer->format = backBuffer->format;
1152 outBuffer->bits = vaddr;
1153 }
1154 }
1155 return err;
1156}
1157
1158status_t Surface::unlockAndPost()
1159{
1160 if (mLockedBuffer == 0) {
1161 ALOGE("Surface::unlockAndPost failed, no locked buffer");
1162 return INVALID_OPERATION;
1163 }
1164
Francis Hart8f396012014-04-01 15:30:53 +03001165 int fd = -1;
1166 status_t err = mLockedBuffer->unlockAsync(&fd);
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001167 ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
1168
Francis Hart8f396012014-04-01 15:30:53 +03001169 err = queueBuffer(mLockedBuffer.get(), fd);
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001170 ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
1171 mLockedBuffer->handle, strerror(-err));
1172
1173 mPostedBuffer = mLockedBuffer;
1174 mLockedBuffer = 0;
1175 return err;
1176}
1177
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001178}; // namespace android