blob: de5c2750e0d9712b06e5f5842390fe8f3107f1df [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;
Andreas Gampe7398a5a2014-12-08 20:42:40 -0800102 mGraphicBufferProducer->allocateBuffers(mSwapIntervalZero, reqWidth,
103 reqHeight, 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 Stozac6f30bd2015-06-08 09:32:50 -0700114String8 Surface::getConsumerName() const {
115 return mGraphicBufferProducer->getConsumerName();
116}
117
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800118int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
119 Surface* c = getSelf(window);
120 return c->setSwapInterval(interval);
121}
122
123int Surface::hook_dequeueBuffer(ANativeWindow* window,
124 ANativeWindowBuffer** buffer, int* fenceFd) {
125 Surface* c = getSelf(window);
126 return c->dequeueBuffer(buffer, fenceFd);
127}
128
129int Surface::hook_cancelBuffer(ANativeWindow* window,
130 ANativeWindowBuffer* buffer, int fenceFd) {
131 Surface* c = getSelf(window);
132 return c->cancelBuffer(buffer, fenceFd);
133}
134
135int Surface::hook_queueBuffer(ANativeWindow* window,
136 ANativeWindowBuffer* buffer, int fenceFd) {
137 Surface* c = getSelf(window);
138 return c->queueBuffer(buffer, fenceFd);
139}
140
141int Surface::hook_dequeueBuffer_DEPRECATED(ANativeWindow* window,
142 ANativeWindowBuffer** buffer) {
143 Surface* c = getSelf(window);
144 ANativeWindowBuffer* buf;
145 int fenceFd = -1;
146 int result = c->dequeueBuffer(&buf, &fenceFd);
147 sp<Fence> fence(new Fence(fenceFd));
Mathias Agopianea74d3b2013-05-16 18:03:22 -0700148 int waitResult = fence->waitForever("dequeueBuffer_DEPRECATED");
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800149 if (waitResult != OK) {
150 ALOGE("dequeueBuffer_DEPRECATED: Fence::wait returned an error: %d",
151 waitResult);
152 c->cancelBuffer(buf, -1);
153 return waitResult;
Mathias Agopian62185b72009-04-16 16:19:50 -0700154 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800155 *buffer = buf;
156 return result;
Mathias Agopian62185b72009-04-16 16:19:50 -0700157}
158
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800159int Surface::hook_cancelBuffer_DEPRECATED(ANativeWindow* window,
160 ANativeWindowBuffer* buffer) {
161 Surface* c = getSelf(window);
162 return c->cancelBuffer(buffer, -1);
Mathias Agopian62185b72009-04-16 16:19:50 -0700163}
164
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800165int Surface::hook_lockBuffer_DEPRECATED(ANativeWindow* window,
166 ANativeWindowBuffer* buffer) {
167 Surface* c = getSelf(window);
168 return c->lockBuffer_DEPRECATED(buffer);
Mathias Agopian62185b72009-04-16 16:19:50 -0700169}
170
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800171int Surface::hook_queueBuffer_DEPRECATED(ANativeWindow* window,
172 ANativeWindowBuffer* buffer) {
173 Surface* c = getSelf(window);
174 return c->queueBuffer(buffer, -1);
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700175}
Mathias Agopian62185b72009-04-16 16:19:50 -0700176
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800177int Surface::hook_query(const ANativeWindow* window,
178 int what, int* value) {
179 const Surface* c = getSelf(window);
180 return c->query(what, value);
181}
182
183int Surface::hook_perform(ANativeWindow* window, int operation, ...) {
184 va_list args;
185 va_start(args, operation);
186 Surface* c = getSelf(window);
Haixia Shid89c2bb2015-09-14 11:02:18 -0700187 int result = c->perform(operation, args);
188 va_end(args);
189 return result;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800190}
191
192int Surface::setSwapInterval(int interval) {
193 ATRACE_CALL();
194 // EGL specification states:
195 // interval is silently clamped to minimum and maximum implementation
196 // dependent values before being stored.
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800197
198 if (interval < minSwapInterval)
199 interval = minSwapInterval;
200
201 if (interval > maxSwapInterval)
202 interval = maxSwapInterval;
203
Mathias Agopian7cdd7862013-07-18 22:10:56 -0700204 mSwapIntervalZero = (interval == 0);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800205
Mathias Agopian7cdd7862013-07-18 22:10:56 -0700206 return NO_ERROR;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800207}
208
Mathias Agopianba93b3f2013-08-01 15:48:40 -0700209int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800210 ATRACE_CALL();
211 ALOGV("Surface::dequeueBuffer");
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800212
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800213 uint32_t reqWidth;
214 uint32_t reqHeight;
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800215 bool swapIntervalZero;
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800216 PixelFormat reqFormat;
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800217 uint32_t reqUsage;
218
219 {
220 Mutex::Autolock lock(mMutex);
221
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800222 reqWidth = mReqWidth ? mReqWidth : mUserWidth;
223 reqHeight = mReqHeight ? mReqHeight : mUserHeight;
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800224
225 swapIntervalZero = mSwapIntervalZero;
226 reqFormat = mReqFormat;
227 reqUsage = mReqUsage;
228 } // Drop the lock so that we can still touch the Surface while blocking in IGBP::dequeueBuffer
229
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800230 int buf = -1;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800231 sp<Fence> fence;
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800232 status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, swapIntervalZero,
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800233 reqWidth, reqHeight, reqFormat, reqUsage);
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800234
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800235 if (result < 0) {
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800236 ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d, %d)"
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800237 "failed: %d", swapIntervalZero, reqWidth, reqHeight, reqFormat,
238 reqUsage, result);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800239 return result;
Mathias Agopian62185b72009-04-16 16:19:50 -0700240 }
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800241
242 Mutex::Autolock lock(mMutex);
243
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800244 sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
Mathias Agopianba93b3f2013-08-01 15:48:40 -0700245
246 // this should never happen
247 ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);
248
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800249 if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
250 freeAllBuffers();
Mathias Agopian579b3f82010-06-08 19:54:15 -0700251 }
Ted Bonkenburgbd050ab2011-07-15 15:10:10 -0700252
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800253 if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
254 result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
255 if (result != NO_ERROR) {
Mathias Agopianba93b3f2013-08-01 15:48:40 -0700256 ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result);
Jesse Hall9f5a1b62014-10-02 11:09:03 -0700257 mGraphicBufferProducer->cancelBuffer(buf, fence);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800258 return result;
259 }
260 }
Mathias Agopian579b3f82010-06-08 19:54:15 -0700261
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800262 if (fence->isValid()) {
263 *fenceFd = fence->dup();
264 if (*fenceFd == -1) {
265 ALOGE("dequeueBuffer: error duping fence: %d", errno);
266 // dup() should never fail; something is badly wrong. Soldier on
267 // and hope for the best; the worst that should happen is some
268 // visible corruption that lasts until the next frame.
269 }
Ted Bonkenburge5d6eb82011-08-09 22:38:41 -0700270 } else {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800271 *fenceFd = -1;
Mathias Agopiana0c30e92010-06-04 18:26:32 -0700272 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800273
274 *buffer = gbuf.get();
275 return OK;
Jamie Gennisaca4e222010-07-15 17:29:15 -0700276}
277
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800278int Surface::cancelBuffer(android_native_buffer_t* buffer,
279 int fenceFd) {
280 ATRACE_CALL();
281 ALOGV("Surface::cancelBuffer");
282 Mutex::Autolock lock(mMutex);
283 int i = getSlotFromBufferLocked(buffer);
284 if (i < 0) {
Taiju Tsuiki4d0cd3f2015-04-30 22:15:33 +0900285 if (fenceFd >= 0) {
286 close(fenceFd);
287 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800288 return i;
289 }
290 sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
291 mGraphicBufferProducer->cancelBuffer(i, fence);
292 return OK;
293}
294
295int Surface::getSlotFromBufferLocked(
296 android_native_buffer_t* buffer) const {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800297 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
298 if (mSlots[i].buffer != NULL &&
299 mSlots[i].buffer->handle == buffer->handle) {
300 return i;
Jamie Gennisaca4e222010-07-15 17:29:15 -0700301 }
302 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800303 ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
304 return BAD_VALUE;
Mathias Agopiana0c30e92010-06-04 18:26:32 -0700305}
306
Igor Murashkin7d2d1602013-11-12 18:02:20 -0800307int Surface::lockBuffer_DEPRECATED(android_native_buffer_t* buffer __attribute__((unused))) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800308 ALOGV("Surface::lockBuffer");
309 Mutex::Autolock lock(mMutex);
310 return OK;
311}
Mathias Agopian631f3582010-05-25 17:51:34 -0700312
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800313int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
314 ATRACE_CALL();
315 ALOGV("Surface::queueBuffer");
316 Mutex::Autolock lock(mMutex);
317 int64_t timestamp;
Andy McFadden3c256212013-08-16 14:55:39 -0700318 bool isAutoTimestamp = false;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800319 if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
Andy McFadden4b49e082013-08-02 15:31:45 -0700320 timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
Andy McFadden3c256212013-08-16 14:55:39 -0700321 isAutoTimestamp = true;
Andy McFadden4b49e082013-08-02 15:31:45 -0700322 ALOGV("Surface::queueBuffer making up timestamp: %.2f ms",
323 timestamp / 1000000.f);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800324 } else {
325 timestamp = mTimestamp;
Mathias Agopian631f3582010-05-25 17:51:34 -0700326 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800327 int i = getSlotFromBufferLocked(buffer);
328 if (i < 0) {
Taiju Tsuiki4d0cd3f2015-04-30 22:15:33 +0900329 if (fenceFd >= 0) {
330 close(fenceFd);
331 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800332 return i;
333 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800334
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800335
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800336 // Make sure the crop rectangle is entirely inside the buffer.
Pablo Ceballos60d69222015-08-07 14:47:20 -0700337 Rect crop(Rect::EMPTY_RECT);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800338 mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800339
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800340 sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
341 IGraphicBufferProducer::QueueBufferOutput output;
Andy McFadden3c256212013-08-16 14:55:39 -0700342 IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800343 mDataSpace, crop, mScalingMode, mTransform ^ mStickyTransform,
344 mSwapIntervalZero, fence, mStickyTransform);
Dan Stoza5065a552015-03-17 16:23:42 -0700345
Dan Stozac62acbd2015-04-21 16:42:49 -0700346 if (mConnectedToCpu || mDirtyRegion.bounds() == Rect::INVALID_RECT) {
Dan Stoza5065a552015-03-17 16:23:42 -0700347 input.setSurfaceDamage(Region::INVALID_REGION);
348 } else {
Dan Stozadb4850c2015-06-25 16:10:18 -0700349 // Here we do two things:
350 // 1) The surface damage was specified using the OpenGL ES convention of
351 // the origin being in the bottom-left corner. Here we flip to the
352 // convention that the rest of the system uses (top-left corner) by
353 // subtracting all top/bottom coordinates from the buffer height.
354 // 2) If the buffer is coming in rotated (for example, because the EGL
355 // implementation is reacting to the transform hint coming back from
356 // SurfaceFlinger), the surface damage needs to be rotated the
357 // opposite direction, since it was generated assuming an unrotated
358 // buffer (the app doesn't know that the EGL implementation is
359 // reacting to the transform hint behind its back). The
360 // transformations in the switch statement below apply those
361 // complementary rotations (e.g., if 90 degrees, rotate 270 degrees).
362
363 int width = buffer->width;
Dan Stoza0e65e6c2015-05-26 13:22:27 -0700364 int height = buffer->height;
Dan Stozadb4850c2015-06-25 16:10:18 -0700365 bool rotated90 = (mTransform ^ mStickyTransform) &
366 NATIVE_WINDOW_TRANSFORM_ROT_90;
367 if (rotated90) {
368 std::swap(width, height);
Dan Stoza0e65e6c2015-05-26 13:22:27 -0700369 }
Dan Stozadb4850c2015-06-25 16:10:18 -0700370
Dan Stoza5065a552015-03-17 16:23:42 -0700371 Region flippedRegion;
372 for (auto rect : mDirtyRegion) {
Dan Stozadb4850c2015-06-25 16:10:18 -0700373 int left = rect.left;
374 int right = rect.right;
375 int top = height - rect.bottom; // Flip from OpenGL convention
376 int bottom = height - rect.top; // Flip from OpenGL convention
377 switch (mTransform ^ mStickyTransform) {
378 case NATIVE_WINDOW_TRANSFORM_ROT_90: {
379 // Rotate 270 degrees
380 Rect flippedRect{top, width - right, bottom, width - left};
381 flippedRegion.orSelf(flippedRect);
382 break;
383 }
384 case NATIVE_WINDOW_TRANSFORM_ROT_180: {
385 // Rotate 180 degrees
386 Rect flippedRect{width - right, height - bottom,
387 width - left, height - top};
388 flippedRegion.orSelf(flippedRect);
389 break;
390 }
391 case NATIVE_WINDOW_TRANSFORM_ROT_270: {
392 // Rotate 90 degrees
393 Rect flippedRect{height - bottom, left,
394 height - top, right};
395 flippedRegion.orSelf(flippedRect);
396 break;
397 }
398 default: {
399 Rect flippedRect{left, top, right, bottom};
400 flippedRegion.orSelf(flippedRect);
401 break;
402 }
403 }
Dan Stoza5065a552015-03-17 16:23:42 -0700404 }
405
406 input.setSurfaceDamage(flippedRegion);
407 }
408
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800409 status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
410 if (err != OK) {
411 ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
412 }
413 uint32_t numPendingBuffers = 0;
Ruben Brunk1681d952014-06-27 15:51:55 -0700414 uint32_t hint = 0;
415 output.deflate(&mDefaultWidth, &mDefaultHeight, &hint,
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800416 &numPendingBuffers);
tedbo1e7fa9e2011-06-22 15:52:53 -0700417
Ruben Brunk1681d952014-06-27 15:51:55 -0700418 // Disable transform hint if sticky transform is set.
419 if (mStickyTransform == 0) {
420 mTransformHint = hint;
421 }
422
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800423 mConsumerRunningBehind = (numPendingBuffers >= 2);
Mathias Agopian631f3582010-05-25 17:51:34 -0700424
Dan Stozac62acbd2015-04-21 16:42:49 -0700425 if (!mConnectedToCpu) {
426 // Clear surface damage back to full-buffer
427 mDirtyRegion = Region::INVALID_REGION;
428 }
Dan Stoza5065a552015-03-17 16:23:42 -0700429
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800430 return err;
431}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700432
Mathias Agopiana67932f2011-04-20 14:20:59 -0700433int Surface::query(int what, int* value) const {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800434 ATRACE_CALL();
435 ALOGV("Surface::query");
436 { // scope for the lock
437 Mutex::Autolock lock(mMutex);
438 switch (what) {
439 case NATIVE_WINDOW_FORMAT:
440 if (mReqFormat) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800441 *value = static_cast<int>(mReqFormat);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800442 return NO_ERROR;
443 }
444 break;
445 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
446 sp<ISurfaceComposer> composer(
447 ComposerService::getComposerService());
448 if (composer->authenticateSurfaceTexture(mGraphicBufferProducer)) {
449 *value = 1;
450 } else {
451 *value = 0;
452 }
453 return NO_ERROR;
454 }
455 case NATIVE_WINDOW_CONCRETE_TYPE:
456 *value = NATIVE_WINDOW_SURFACE;
457 return NO_ERROR;
458 case NATIVE_WINDOW_DEFAULT_WIDTH:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800459 *value = static_cast<int>(
460 mUserWidth ? mUserWidth : mDefaultWidth);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800461 return NO_ERROR;
462 case NATIVE_WINDOW_DEFAULT_HEIGHT:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800463 *value = static_cast<int>(
464 mUserHeight ? mUserHeight : mDefaultHeight);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800465 return NO_ERROR;
466 case NATIVE_WINDOW_TRANSFORM_HINT:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800467 *value = static_cast<int>(mTransformHint);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800468 return NO_ERROR;
469 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: {
470 status_t err = NO_ERROR;
471 if (!mConsumerRunningBehind) {
472 *value = 0;
473 } else {
474 err = mGraphicBufferProducer->query(what, value);
475 if (err == NO_ERROR) {
476 mConsumerRunningBehind = *value;
477 }
478 }
479 return err;
480 }
481 }
Jamie Gennis391bbe22011-03-14 15:00:06 -0700482 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800483 return mGraphicBufferProducer->query(what, value);
Eino-Ville Talvala1d01a122011-02-18 11:02:42 -0800484}
485
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800486int Surface::perform(int operation, va_list args)
487{
488 int res = NO_ERROR;
489 switch (operation) {
490 case NATIVE_WINDOW_CONNECT:
491 // deprecated. must return NO_ERROR.
492 break;
493 case NATIVE_WINDOW_DISCONNECT:
494 // deprecated. must return NO_ERROR.
495 break;
496 case NATIVE_WINDOW_SET_USAGE:
497 res = dispatchSetUsage(args);
498 break;
499 case NATIVE_WINDOW_SET_CROP:
500 res = dispatchSetCrop(args);
501 break;
502 case NATIVE_WINDOW_SET_BUFFER_COUNT:
503 res = dispatchSetBufferCount(args);
504 break;
505 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
506 res = dispatchSetBuffersGeometry(args);
507 break;
508 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
509 res = dispatchSetBuffersTransform(args);
510 break;
Ruben Brunk1681d952014-06-27 15:51:55 -0700511 case NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM:
512 res = dispatchSetBuffersStickyTransform(args);
513 break;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800514 case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
515 res = dispatchSetBuffersTimestamp(args);
516 break;
517 case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
518 res = dispatchSetBuffersDimensions(args);
519 break;
520 case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS:
521 res = dispatchSetBuffersUserDimensions(args);
522 break;
523 case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
524 res = dispatchSetBuffersFormat(args);
525 break;
526 case NATIVE_WINDOW_LOCK:
527 res = dispatchLock(args);
528 break;
529 case NATIVE_WINDOW_UNLOCK_AND_POST:
530 res = dispatchUnlockAndPost(args);
531 break;
532 case NATIVE_WINDOW_SET_SCALING_MODE:
533 res = dispatchSetScalingMode(args);
534 break;
535 case NATIVE_WINDOW_API_CONNECT:
536 res = dispatchConnect(args);
537 break;
538 case NATIVE_WINDOW_API_DISCONNECT:
539 res = dispatchDisconnect(args);
540 break;
Rachad7cb0d392014-07-29 17:53:53 -0700541 case NATIVE_WINDOW_SET_SIDEBAND_STREAM:
542 res = dispatchSetSidebandStream(args);
543 break;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800544 case NATIVE_WINDOW_SET_BUFFERS_DATASPACE:
545 res = dispatchSetBuffersDataSpace(args);
546 break;
Dan Stoza5065a552015-03-17 16:23:42 -0700547 case NATIVE_WINDOW_SET_SURFACE_DAMAGE:
548 res = dispatchSetSurfaceDamage(args);
549 break;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800550 default:
551 res = NAME_NOT_FOUND;
552 break;
553 }
554 return res;
555}
Mathias Agopiana138f892010-05-21 17:24:35 -0700556
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800557int Surface::dispatchConnect(va_list args) {
558 int api = va_arg(args, int);
559 return connect(api);
560}
Mathias Agopian55fa2512010-03-11 15:06:54 -0800561
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800562int Surface::dispatchDisconnect(va_list args) {
563 int api = va_arg(args, int);
564 return disconnect(api);
565}
566
567int Surface::dispatchSetUsage(va_list args) {
568 int usage = va_arg(args, int);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800569 return setUsage(static_cast<uint32_t>(usage));
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800570}
571
572int Surface::dispatchSetCrop(va_list args) {
573 android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
574 return setCrop(reinterpret_cast<Rect const*>(rect));
575}
576
577int Surface::dispatchSetBufferCount(va_list args) {
578 size_t bufferCount = va_arg(args, size_t);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800579 return setBufferCount(static_cast<int32_t>(bufferCount));
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800580}
581
582int Surface::dispatchSetBuffersGeometry(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800583 uint32_t width = va_arg(args, uint32_t);
584 uint32_t height = va_arg(args, uint32_t);
585 PixelFormat format = va_arg(args, PixelFormat);
586 int err = setBuffersDimensions(width, height);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800587 if (err != 0) {
588 return err;
589 }
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800590 return setBuffersFormat(format);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800591}
592
593int Surface::dispatchSetBuffersDimensions(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800594 uint32_t width = va_arg(args, uint32_t);
595 uint32_t height = va_arg(args, uint32_t);
596 return setBuffersDimensions(width, height);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800597}
598
599int Surface::dispatchSetBuffersUserDimensions(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 setBuffersUserDimensions(width, height);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800603}
604
605int Surface::dispatchSetBuffersFormat(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800606 PixelFormat format = va_arg(args, PixelFormat);
607 return setBuffersFormat(format);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800608}
609
610int Surface::dispatchSetScalingMode(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800611 int mode = va_arg(args, int);
612 return setScalingMode(mode);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800613}
614
615int Surface::dispatchSetBuffersTransform(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800616 uint32_t transform = va_arg(args, uint32_t);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800617 return setBuffersTransform(transform);
618}
619
Ruben Brunk1681d952014-06-27 15:51:55 -0700620int Surface::dispatchSetBuffersStickyTransform(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800621 uint32_t transform = va_arg(args, uint32_t);
Ruben Brunk1681d952014-06-27 15:51:55 -0700622 return setBuffersStickyTransform(transform);
623}
624
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800625int Surface::dispatchSetBuffersTimestamp(va_list args) {
626 int64_t timestamp = va_arg(args, int64_t);
627 return setBuffersTimestamp(timestamp);
628}
629
630int Surface::dispatchLock(va_list args) {
631 ANativeWindow_Buffer* outBuffer = va_arg(args, ANativeWindow_Buffer*);
632 ARect* inOutDirtyBounds = va_arg(args, ARect*);
633 return lock(outBuffer, inOutDirtyBounds);
634}
635
Igor Murashkin7d2d1602013-11-12 18:02:20 -0800636int Surface::dispatchUnlockAndPost(va_list args __attribute__((unused))) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800637 return unlockAndPost();
638}
639
Rachad7cb0d392014-07-29 17:53:53 -0700640int Surface::dispatchSetSidebandStream(va_list args) {
641 native_handle_t* sH = va_arg(args, native_handle_t*);
642 sp<NativeHandle> sidebandHandle = NativeHandle::create(sH, false);
643 setSidebandStream(sidebandHandle);
644 return OK;
645}
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800646
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800647int Surface::dispatchSetBuffersDataSpace(va_list args) {
648 android_dataspace dataspace =
649 static_cast<android_dataspace>(va_arg(args, int));
650 return setBuffersDataSpace(dataspace);
651}
652
Dan Stoza5065a552015-03-17 16:23:42 -0700653int Surface::dispatchSetSurfaceDamage(va_list args) {
654 android_native_rect_t* rects = va_arg(args, android_native_rect_t*);
655 size_t numRects = va_arg(args, size_t);
656 setSurfaceDamage(rects, numRects);
657 return NO_ERROR;
658}
659
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800660int Surface::connect(int api) {
Dan Stoza966b98b2015-03-02 22:12:37 -0800661 static sp<IProducerListener> listener = new DummyProducerListener();
662 return connect(api, listener);
663}
664
665int Surface::connect(int api, const sp<IProducerListener>& listener) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800666 ATRACE_CALL();
667 ALOGV("Surface::connect");
668 Mutex::Autolock lock(mMutex);
669 IGraphicBufferProducer::QueueBufferOutput output;
Dan Stozaf0eaf252014-03-21 13:05:51 -0700670 int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800671 if (err == NO_ERROR) {
672 uint32_t numPendingBuffers = 0;
Ruben Brunk1681d952014-06-27 15:51:55 -0700673 uint32_t hint = 0;
674 output.deflate(&mDefaultWidth, &mDefaultHeight, &hint,
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800675 &numPendingBuffers);
Ruben Brunk1681d952014-06-27 15:51:55 -0700676
677 // Disable transform hint if sticky transform is set.
678 if (mStickyTransform == 0) {
679 mTransformHint = hint;
680 }
681
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800682 mConsumerRunningBehind = (numPendingBuffers >= 2);
683 }
684 if (!err && api == NATIVE_WINDOW_API_CPU) {
685 mConnectedToCpu = true;
Dan Stoza5065a552015-03-17 16:23:42 -0700686 // Clear the dirty region in case we're switching from a non-CPU API
687 mDirtyRegion.clear();
688 } else if (!err) {
689 // Initialize the dirty region for tracking surface damage
690 mDirtyRegion = Region::INVALID_REGION;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800691 }
Dan Stoza5065a552015-03-17 16:23:42 -0700692
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800693 return err;
694}
695
Mathias Agopian365857d2013-09-11 19:35:45 -0700696
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800697int Surface::disconnect(int api) {
698 ATRACE_CALL();
699 ALOGV("Surface::disconnect");
700 Mutex::Autolock lock(mMutex);
701 freeAllBuffers();
702 int err = mGraphicBufferProducer->disconnect(api);
703 if (!err) {
704 mReqFormat = 0;
705 mReqWidth = 0;
706 mReqHeight = 0;
707 mReqUsage = 0;
708 mCrop.clear();
709 mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
710 mTransform = 0;
Ruben Brunk1681d952014-06-27 15:51:55 -0700711 mStickyTransform = 0;
712
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800713 if (api == NATIVE_WINDOW_API_CPU) {
714 mConnectedToCpu = false;
715 }
716 }
717 return err;
718}
719
Dan Stozad9c49712015-04-27 11:06:01 -0700720int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
Dan Stoza231832e2015-03-11 11:55:01 -0700721 sp<Fence>* outFence) {
722 ATRACE_CALL();
723 ALOGV("Surface::detachNextBuffer");
724
725 if (outBuffer == NULL || outFence == NULL) {
726 return BAD_VALUE;
727 }
728
729 Mutex::Autolock lock(mMutex);
730
731 sp<GraphicBuffer> buffer(NULL);
732 sp<Fence> fence(NULL);
733 status_t result = mGraphicBufferProducer->detachNextBuffer(
734 &buffer, &fence);
735 if (result != NO_ERROR) {
736 return result;
737 }
738
Dan Stozad9c49712015-04-27 11:06:01 -0700739 *outBuffer = buffer;
Dan Stoza231832e2015-03-11 11:55:01 -0700740 if (fence != NULL && fence->isValid()) {
741 *outFence = fence;
742 } else {
743 *outFence = Fence::NO_FENCE;
744 }
745
746 return NO_ERROR;
747}
748
749int Surface::attachBuffer(ANativeWindowBuffer* buffer)
750{
751 ATRACE_CALL();
752 ALOGV("Surface::attachBuffer");
753
754 Mutex::Autolock lock(mMutex);
755
756 sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer));
Dan Stoza812ed062015-06-02 15:45:22 -0700757 uint32_t priorGeneration = graphicBuffer->mGenerationNumber;
758 graphicBuffer->mGenerationNumber = mGenerationNumber;
Dan Stoza231832e2015-03-11 11:55:01 -0700759 int32_t attachedSlot = -1;
760 status_t result = mGraphicBufferProducer->attachBuffer(
761 &attachedSlot, graphicBuffer);
762 if (result != NO_ERROR) {
763 ALOGE("attachBuffer: IGraphicBufferProducer call failed (%d)", result);
Dan Stoza812ed062015-06-02 15:45:22 -0700764 graphicBuffer->mGenerationNumber = priorGeneration;
Dan Stoza231832e2015-03-11 11:55:01 -0700765 return result;
766 }
767 mSlots[attachedSlot].buffer = graphicBuffer;
768
769 return NO_ERROR;
770}
771
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800772int Surface::setUsage(uint32_t reqUsage)
773{
774 ALOGV("Surface::setUsage");
775 Mutex::Autolock lock(mMutex);
776 mReqUsage = reqUsage;
777 return OK;
778}
779
780int Surface::setCrop(Rect const* rect)
781{
782 ATRACE_CALL();
783
Pablo Ceballos60d69222015-08-07 14:47:20 -0700784 Rect realRect(Rect::EMPTY_RECT);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800785 if (rect == NULL || rect->isEmpty()) {
786 realRect.clear();
787 } else {
788 realRect = *rect;
Mathias Agopian55fa2512010-03-11 15:06:54 -0800789 }
790
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800791 ALOGV("Surface::setCrop rect=[%d %d %d %d]",
792 realRect.left, realRect.top, realRect.right, realRect.bottom);
793
794 Mutex::Autolock lock(mMutex);
795 mCrop = realRect;
796 return NO_ERROR;
797}
798
799int Surface::setBufferCount(int bufferCount)
800{
801 ATRACE_CALL();
802 ALOGV("Surface::setBufferCount");
803 Mutex::Autolock lock(mMutex);
804
Pablo Ceballose5b755a2015-08-13 16:18:19 -0700805 status_t err = NO_ERROR;
806 if (bufferCount == 0) {
807 err = mGraphicBufferProducer->setMaxDequeuedBufferCount(1);
808 } else {
809 int minUndequeuedBuffers = 0;
810 err = mGraphicBufferProducer->query(
811 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
812 if (err == NO_ERROR) {
813 err = mGraphicBufferProducer->setMaxDequeuedBufferCount(
814 bufferCount - minUndequeuedBuffers);
815 }
816 }
Mathias Agopian90147262010-01-22 11:47:55 -0800817
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700818 if (err == NO_ERROR) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800819 freeAllBuffers();
Mathias Agopian87a96ea2011-08-23 21:09:41 -0700820 }
821
Pablo Ceballose5b755a2015-08-13 16:18:19 -0700822 ALOGE_IF(err, "IGraphicBufferProducer::setBufferCount(%d) returned %s",
823 bufferCount, strerror(-err));
824
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700825 return err;
826}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700827
Pablo Ceballosfa455352015-08-12 17:47:47 -0700828int Surface::setMaxDequeuedBufferCount(int maxDequeuedBuffers) {
829 ATRACE_CALL();
830 ALOGV("Surface::setMaxDequeuedBufferCount");
831 Mutex::Autolock lock(mMutex);
832
833 status_t err = mGraphicBufferProducer->setMaxDequeuedBufferCount(
834 maxDequeuedBuffers);
835 ALOGE_IF(err, "IGraphicBufferProducer::setMaxDequeuedBufferCount(%d) "
836 "returned %s", maxDequeuedBuffers, strerror(-err));
837
838 if (err == NO_ERROR) {
839 freeAllBuffers();
840 }
841
842 return err;
843}
844
845int Surface::setAsyncMode(bool async) {
846 ATRACE_CALL();
847 ALOGV("Surface::setAsyncMode");
848 Mutex::Autolock lock(mMutex);
849
850 status_t err = mGraphicBufferProducer->setAsyncMode(async);
851 ALOGE_IF(err, "IGraphicBufferProducer::setAsyncMode(%d) returned %s",
852 async, strerror(-err));
853
854 if (err == NO_ERROR) {
855 freeAllBuffers();
856 }
857
858 return err;
859}
860
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800861int Surface::setBuffersDimensions(uint32_t width, uint32_t height)
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800862{
863 ATRACE_CALL();
864 ALOGV("Surface::setBuffersDimensions");
865
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800866 if ((width && !height) || (!width && height))
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800867 return BAD_VALUE;
868
869 Mutex::Autolock lock(mMutex);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800870 mReqWidth = width;
871 mReqHeight = height;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800872 return NO_ERROR;
873}
874
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800875int Surface::setBuffersUserDimensions(uint32_t width, uint32_t height)
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800876{
877 ATRACE_CALL();
878 ALOGV("Surface::setBuffersUserDimensions");
879
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800880 if ((width && !height) || (!width && height))
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800881 return BAD_VALUE;
882
883 Mutex::Autolock lock(mMutex);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800884 mUserWidth = width;
885 mUserHeight = height;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800886 return NO_ERROR;
887}
888
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800889int Surface::setBuffersFormat(PixelFormat format)
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800890{
891 ALOGV("Surface::setBuffersFormat");
892
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800893 Mutex::Autolock lock(mMutex);
894 mReqFormat = format;
895 return NO_ERROR;
896}
897
898int Surface::setScalingMode(int mode)
899{
900 ATRACE_CALL();
901 ALOGV("Surface::setScalingMode(%d)", mode);
902
903 switch (mode) {
904 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
905 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
906 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
907 break;
908 default:
909 ALOGE("unknown scaling mode: %d", mode);
910 return BAD_VALUE;
911 }
912
913 Mutex::Autolock lock(mMutex);
914 mScalingMode = mode;
915 return NO_ERROR;
916}
917
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800918int Surface::setBuffersTransform(uint32_t transform)
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800919{
920 ATRACE_CALL();
921 ALOGV("Surface::setBuffersTransform");
922 Mutex::Autolock lock(mMutex);
923 mTransform = transform;
924 return NO_ERROR;
925}
926
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800927int Surface::setBuffersStickyTransform(uint32_t transform)
Ruben Brunk1681d952014-06-27 15:51:55 -0700928{
929 ATRACE_CALL();
930 ALOGV("Surface::setBuffersStickyTransform");
931 Mutex::Autolock lock(mMutex);
932 mStickyTransform = transform;
933 return NO_ERROR;
934}
935
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800936int Surface::setBuffersTimestamp(int64_t timestamp)
937{
938 ALOGV("Surface::setBuffersTimestamp");
939 Mutex::Autolock lock(mMutex);
940 mTimestamp = timestamp;
941 return NO_ERROR;
942}
943
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800944int Surface::setBuffersDataSpace(android_dataspace dataSpace)
945{
946 ALOGV("Surface::setBuffersDataSpace");
947 Mutex::Autolock lock(mMutex);
948 mDataSpace = dataSpace;
949 return NO_ERROR;
950}
951
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800952void Surface::freeAllBuffers() {
953 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
954 mSlots[i].buffer = 0;
955 }
956}
957
Dan Stoza5065a552015-03-17 16:23:42 -0700958void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) {
959 ATRACE_CALL();
960 ALOGV("Surface::setSurfaceDamage");
961 Mutex::Autolock lock(mMutex);
962
Dan Stozac62acbd2015-04-21 16:42:49 -0700963 if (mConnectedToCpu || numRects == 0) {
Dan Stoza5065a552015-03-17 16:23:42 -0700964 mDirtyRegion = Region::INVALID_REGION;
965 return;
966 }
967
968 mDirtyRegion.clear();
969 for (size_t r = 0; r < numRects; ++r) {
970 // We intentionally flip top and bottom here, since because they're
971 // specified with a bottom-left origin, top > bottom, which fails
972 // validation in the Region class. We will fix this up when we flip to a
973 // top-left origin in queueBuffer.
974 Rect rect(rects[r].left, rects[r].bottom, rects[r].right, rects[r].top);
975 mDirtyRegion.orSelf(rect);
976 }
977}
978
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800979// ----------------------------------------------------------------------
980// the lock/unlock APIs must be used from the same thread
981
982static status_t copyBlt(
983 const sp<GraphicBuffer>& dst,
984 const sp<GraphicBuffer>& src,
985 const Region& reg)
986{
987 // src and dst with, height and format must be identical. no verification
988 // is done here.
989 status_t err;
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800990 uint8_t* src_bits = NULL;
991 err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(),
992 reinterpret_cast<void**>(&src_bits));
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800993 ALOGE_IF(err, "error locking src buffer %s", strerror(-err));
994
995 uint8_t* dst_bits = NULL;
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800996 err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(),
997 reinterpret_cast<void**>(&dst_bits));
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800998 ALOGE_IF(err, "error locking dst buffer %s", strerror(-err));
999
1000 Region::const_iterator head(reg.begin());
1001 Region::const_iterator tail(reg.end());
1002 if (head != tail && src_bits && dst_bits) {
1003 const size_t bpp = bytesPerPixel(src->format);
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001004 const size_t dbpr = static_cast<uint32_t>(dst->stride) * bpp;
1005 const size_t sbpr = static_cast<uint32_t>(src->stride) * bpp;
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001006
1007 while (head != tail) {
1008 const Rect& r(*head++);
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001009 int32_t h = r.height();
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001010 if (h <= 0) continue;
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001011 size_t size = static_cast<uint32_t>(r.width()) * bpp;
1012 uint8_t const * s = src_bits +
1013 static_cast<uint32_t>(r.left + src->stride * r.top) * bpp;
1014 uint8_t * d = dst_bits +
1015 static_cast<uint32_t>(r.left + dst->stride * r.top) * bpp;
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001016 if (dbpr==sbpr && size==sbpr) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001017 size *= static_cast<size_t>(h);
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001018 h = 1;
1019 }
1020 do {
1021 memcpy(d, s, size);
1022 d += dbpr;
1023 s += sbpr;
1024 } while (--h > 0);
1025 }
1026 }
1027
1028 if (src_bits)
1029 src->unlock();
1030
1031 if (dst_bits)
1032 dst->unlock();
1033
1034 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001035}
1036
Mathias Agopiana138f892010-05-21 17:24:35 -07001037// ----------------------------------------------------------------------------
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001038
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001039status_t Surface::lock(
1040 ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
1041{
1042 if (mLockedBuffer != 0) {
1043 ALOGE("Surface::lock failed, already locked");
1044 return INVALID_OPERATION;
1045 }
1046
1047 if (!mConnectedToCpu) {
1048 int err = Surface::connect(NATIVE_WINDOW_API_CPU);
1049 if (err) {
1050 return err;
1051 }
1052 // we're intending to do software rendering from this point
1053 setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
1054 }
1055
1056 ANativeWindowBuffer* out;
1057 int fenceFd = -1;
1058 status_t err = dequeueBuffer(&out, &fenceFd);
1059 ALOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
1060 if (err == NO_ERROR) {
1061 sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001062 const Rect bounds(backBuffer->width, backBuffer->height);
1063
1064 Region newDirtyRegion;
1065 if (inOutDirtyBounds) {
1066 newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds));
1067 newDirtyRegion.andSelf(bounds);
1068 } else {
1069 newDirtyRegion.set(bounds);
1070 }
1071
1072 // figure out if we can copy the frontbuffer back
1073 const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
1074 const bool canCopyBack = (frontBuffer != 0 &&
1075 backBuffer->width == frontBuffer->width &&
1076 backBuffer->height == frontBuffer->height &&
1077 backBuffer->format == frontBuffer->format);
1078
1079 if (canCopyBack) {
1080 // copy the area that is invalid and not repainted this round
1081 const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
1082 if (!copyback.isEmpty())
1083 copyBlt(backBuffer, frontBuffer, copyback);
1084 } else {
1085 // if we can't copy-back anything, modify the user's dirty
1086 // region to make sure they redraw the whole buffer
1087 newDirtyRegion.set(bounds);
1088 mDirtyRegion.clear();
1089 Mutex::Autolock lock(mMutex);
1090 for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
1091 mSlots[i].dirtyRegion.clear();
1092 }
1093 }
1094
1095
1096 { // scope for the lock
1097 Mutex::Autolock lock(mMutex);
1098 int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
1099 if (backBufferSlot >= 0) {
1100 Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
1101 mDirtyRegion.subtract(dirtyRegion);
1102 dirtyRegion = newDirtyRegion;
1103 }
1104 }
1105
1106 mDirtyRegion.orSelf(newDirtyRegion);
1107 if (inOutDirtyBounds) {
1108 *inOutDirtyBounds = newDirtyRegion.getBounds();
1109 }
1110
1111 void* vaddr;
Francis Hart8f396012014-04-01 15:30:53 +03001112 status_t res = backBuffer->lockAsync(
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001113 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
Francis Hart8f396012014-04-01 15:30:53 +03001114 newDirtyRegion.bounds(), &vaddr, fenceFd);
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001115
1116 ALOGW_IF(res, "failed locking buffer (handle = %p)",
1117 backBuffer->handle);
1118
1119 if (res != 0) {
1120 err = INVALID_OPERATION;
1121 } else {
1122 mLockedBuffer = backBuffer;
1123 outBuffer->width = backBuffer->width;
1124 outBuffer->height = backBuffer->height;
1125 outBuffer->stride = backBuffer->stride;
1126 outBuffer->format = backBuffer->format;
1127 outBuffer->bits = vaddr;
1128 }
1129 }
1130 return err;
1131}
1132
1133status_t Surface::unlockAndPost()
1134{
1135 if (mLockedBuffer == 0) {
1136 ALOGE("Surface::unlockAndPost failed, no locked buffer");
1137 return INVALID_OPERATION;
1138 }
1139
Francis Hart8f396012014-04-01 15:30:53 +03001140 int fd = -1;
1141 status_t err = mLockedBuffer->unlockAsync(&fd);
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001142 ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
1143
Francis Hart8f396012014-04-01 15:30:53 +03001144 err = queueBuffer(mLockedBuffer.get(), fd);
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001145 ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
1146 mLockedBuffer->handle, strerror(-err));
1147
1148 mPostedBuffer = mLockedBuffer;
1149 mLockedBuffer = 0;
1150 return err;
1151}
1152
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001153}; // namespace android