blob: 35aa7c76ba87cff0d99e19ffdebf32feb786beaa [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)
Mathias Agopian35ffa6a2013-03-12 18:45:09 -070045 : mGraphicBufferProducer(bufferProducer)
Mathias Agopian62185b72009-04-16 16:19:50 -070046{
Mathias Agopiane3c697f2013-02-14 17:11:02 -080047 // Initialize the ANativeWindow function pointers.
48 ANativeWindow::setSwapInterval = hook_setSwapInterval;
49 ANativeWindow::dequeueBuffer = hook_dequeueBuffer;
50 ANativeWindow::cancelBuffer = hook_cancelBuffer;
51 ANativeWindow::queueBuffer = hook_queueBuffer;
52 ANativeWindow::query = hook_query;
53 ANativeWindow::perform = hook_perform;
54
55 ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
56 ANativeWindow::cancelBuffer_DEPRECATED = hook_cancelBuffer_DEPRECATED;
57 ANativeWindow::lockBuffer_DEPRECATED = hook_lockBuffer_DEPRECATED;
58 ANativeWindow::queueBuffer_DEPRECATED = hook_queueBuffer_DEPRECATED;
59
60 const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
61 const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
62
63 mReqWidth = 0;
64 mReqHeight = 0;
65 mReqFormat = 0;
66 mReqUsage = 0;
67 mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -080068 mDataSpace = HAL_DATASPACE_UNKNOWN;
Mathias Agopiane3c697f2013-02-14 17:11:02 -080069 mCrop.clear();
70 mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
71 mTransform = 0;
Ruben Brunk1681d952014-06-27 15:51:55 -070072 mStickyTransform = 0;
Mathias Agopiane3c697f2013-02-14 17:11:02 -080073 mDefaultWidth = 0;
74 mDefaultHeight = 0;
75 mUserWidth = 0;
76 mUserHeight = 0;
77 mTransformHint = 0;
78 mConsumerRunningBehind = false;
79 mConnectedToCpu = false;
Eino-Ville Talvala7895e902013-08-21 11:53:37 -070080 mProducerControlledByApp = controlledByApp;
Mathias Agopian7cdd7862013-07-18 22:10:56 -070081 mSwapIntervalZero = false;
Mathias Agopian62185b72009-04-16 16:19:50 -070082}
83
Mathias Agopian35ffa6a2013-03-12 18:45:09 -070084Surface::~Surface() {
85 if (mConnectedToCpu) {
86 Surface::disconnect(NATIVE_WINDOW_API_CPU);
87 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -080088}
89
90sp<IGraphicBufferProducer> Surface::getIGraphicBufferProducer() const {
91 return mGraphicBufferProducer;
92}
93
Wonsik Kim0ee14ca2014-03-17 17:46:53 +090094void Surface::setSidebandStream(const sp<NativeHandle>& stream) {
95 mGraphicBufferProducer->setSidebandStream(stream);
96}
97
Dan Stoza29a3e902014-06-20 13:13:57 -070098void Surface::allocateBuffers() {
99 uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth;
100 uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight;
Andreas Gampe7398a5a2014-12-08 20:42:40 -0800101 mGraphicBufferProducer->allocateBuffers(mSwapIntervalZero, reqWidth,
102 reqHeight, mReqFormat, mReqUsage);
Dan Stoza29a3e902014-06-20 13:13:57 -0700103}
104
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800105int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
106 Surface* c = getSelf(window);
107 return c->setSwapInterval(interval);
108}
109
110int Surface::hook_dequeueBuffer(ANativeWindow* window,
111 ANativeWindowBuffer** buffer, int* fenceFd) {
112 Surface* c = getSelf(window);
113 return c->dequeueBuffer(buffer, fenceFd);
114}
115
116int Surface::hook_cancelBuffer(ANativeWindow* window,
117 ANativeWindowBuffer* buffer, int fenceFd) {
118 Surface* c = getSelf(window);
119 return c->cancelBuffer(buffer, fenceFd);
120}
121
122int Surface::hook_queueBuffer(ANativeWindow* window,
123 ANativeWindowBuffer* buffer, int fenceFd) {
124 Surface* c = getSelf(window);
125 return c->queueBuffer(buffer, fenceFd);
126}
127
128int Surface::hook_dequeueBuffer_DEPRECATED(ANativeWindow* window,
129 ANativeWindowBuffer** buffer) {
130 Surface* c = getSelf(window);
131 ANativeWindowBuffer* buf;
132 int fenceFd = -1;
133 int result = c->dequeueBuffer(&buf, &fenceFd);
134 sp<Fence> fence(new Fence(fenceFd));
Mathias Agopianea74d3b2013-05-16 18:03:22 -0700135 int waitResult = fence->waitForever("dequeueBuffer_DEPRECATED");
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800136 if (waitResult != OK) {
137 ALOGE("dequeueBuffer_DEPRECATED: Fence::wait returned an error: %d",
138 waitResult);
139 c->cancelBuffer(buf, -1);
140 return waitResult;
Mathias Agopian62185b72009-04-16 16:19:50 -0700141 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800142 *buffer = buf;
143 return result;
Mathias Agopian62185b72009-04-16 16:19:50 -0700144}
145
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800146int Surface::hook_cancelBuffer_DEPRECATED(ANativeWindow* window,
147 ANativeWindowBuffer* buffer) {
148 Surface* c = getSelf(window);
149 return c->cancelBuffer(buffer, -1);
Mathias Agopian62185b72009-04-16 16:19:50 -0700150}
151
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800152int Surface::hook_lockBuffer_DEPRECATED(ANativeWindow* window,
153 ANativeWindowBuffer* buffer) {
154 Surface* c = getSelf(window);
155 return c->lockBuffer_DEPRECATED(buffer);
Mathias Agopian62185b72009-04-16 16:19:50 -0700156}
157
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800158int Surface::hook_queueBuffer_DEPRECATED(ANativeWindow* window,
159 ANativeWindowBuffer* buffer) {
160 Surface* c = getSelf(window);
161 return c->queueBuffer(buffer, -1);
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700162}
Mathias Agopian62185b72009-04-16 16:19:50 -0700163
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800164int Surface::hook_query(const ANativeWindow* window,
165 int what, int* value) {
166 const Surface* c = getSelf(window);
167 return c->query(what, value);
168}
169
170int Surface::hook_perform(ANativeWindow* window, int operation, ...) {
171 va_list args;
172 va_start(args, operation);
173 Surface* c = getSelf(window);
174 return c->perform(operation, args);
175}
176
177int Surface::setSwapInterval(int interval) {
178 ATRACE_CALL();
179 // EGL specification states:
180 // interval is silently clamped to minimum and maximum implementation
181 // dependent values before being stored.
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800182
183 if (interval < minSwapInterval)
184 interval = minSwapInterval;
185
186 if (interval > maxSwapInterval)
187 interval = maxSwapInterval;
188
Mathias Agopian7cdd7862013-07-18 22:10:56 -0700189 mSwapIntervalZero = (interval == 0);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800190
Mathias Agopian7cdd7862013-07-18 22:10:56 -0700191 return NO_ERROR;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800192}
193
Mathias Agopianba93b3f2013-08-01 15:48:40 -0700194int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800195 ATRACE_CALL();
196 ALOGV("Surface::dequeueBuffer");
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800197
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800198 uint32_t reqWidth;
199 uint32_t reqHeight;
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800200 bool swapIntervalZero;
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800201 PixelFormat reqFormat;
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800202 uint32_t reqUsage;
203
204 {
205 Mutex::Autolock lock(mMutex);
206
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800207 reqWidth = mReqWidth ? mReqWidth : mUserWidth;
208 reqHeight = mReqHeight ? mReqHeight : mUserHeight;
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800209
210 swapIntervalZero = mSwapIntervalZero;
211 reqFormat = mReqFormat;
212 reqUsage = mReqUsage;
213 } // Drop the lock so that we can still touch the Surface while blocking in IGBP::dequeueBuffer
214
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800215 int buf = -1;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800216 sp<Fence> fence;
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800217 status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, swapIntervalZero,
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800218 reqWidth, reqHeight, reqFormat, reqUsage);
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800219
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800220 if (result < 0) {
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800221 ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d, %d)"
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800222 "failed: %d", swapIntervalZero, reqWidth, reqHeight, reqFormat,
223 reqUsage, result);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800224 return result;
Mathias Agopian62185b72009-04-16 16:19:50 -0700225 }
Igor Murashkin0f1889e2014-02-28 18:44:21 -0800226
227 Mutex::Autolock lock(mMutex);
228
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800229 sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
Mathias Agopianba93b3f2013-08-01 15:48:40 -0700230
231 // this should never happen
232 ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);
233
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800234 if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
235 freeAllBuffers();
Mathias Agopian579b3f82010-06-08 19:54:15 -0700236 }
Ted Bonkenburgbd050ab2011-07-15 15:10:10 -0700237
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800238 if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
239 result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
240 if (result != NO_ERROR) {
Mathias Agopianba93b3f2013-08-01 15:48:40 -0700241 ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result);
Jesse Hall9f5a1b62014-10-02 11:09:03 -0700242 mGraphicBufferProducer->cancelBuffer(buf, fence);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800243 return result;
244 }
245 }
Mathias Agopian579b3f82010-06-08 19:54:15 -0700246
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800247 if (fence->isValid()) {
248 *fenceFd = fence->dup();
249 if (*fenceFd == -1) {
250 ALOGE("dequeueBuffer: error duping fence: %d", errno);
251 // dup() should never fail; something is badly wrong. Soldier on
252 // and hope for the best; the worst that should happen is some
253 // visible corruption that lasts until the next frame.
254 }
Ted Bonkenburge5d6eb82011-08-09 22:38:41 -0700255 } else {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800256 *fenceFd = -1;
Mathias Agopiana0c30e92010-06-04 18:26:32 -0700257 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800258
259 *buffer = gbuf.get();
260 return OK;
Jamie Gennisaca4e222010-07-15 17:29:15 -0700261}
262
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800263int Surface::cancelBuffer(android_native_buffer_t* buffer,
264 int fenceFd) {
265 ATRACE_CALL();
266 ALOGV("Surface::cancelBuffer");
267 Mutex::Autolock lock(mMutex);
268 int i = getSlotFromBufferLocked(buffer);
269 if (i < 0) {
Taiju Tsuiki4d0cd3f2015-04-30 22:15:33 +0900270 if (fenceFd >= 0) {
271 close(fenceFd);
272 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800273 return i;
274 }
275 sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
276 mGraphicBufferProducer->cancelBuffer(i, fence);
277 return OK;
278}
279
280int Surface::getSlotFromBufferLocked(
281 android_native_buffer_t* buffer) const {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800282 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
283 if (mSlots[i].buffer != NULL &&
284 mSlots[i].buffer->handle == buffer->handle) {
285 return i;
Jamie Gennisaca4e222010-07-15 17:29:15 -0700286 }
287 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800288 ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
289 return BAD_VALUE;
Mathias Agopiana0c30e92010-06-04 18:26:32 -0700290}
291
Igor Murashkin7d2d1602013-11-12 18:02:20 -0800292int Surface::lockBuffer_DEPRECATED(android_native_buffer_t* buffer __attribute__((unused))) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800293 ALOGV("Surface::lockBuffer");
294 Mutex::Autolock lock(mMutex);
295 return OK;
296}
Mathias Agopian631f3582010-05-25 17:51:34 -0700297
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800298int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
299 ATRACE_CALL();
300 ALOGV("Surface::queueBuffer");
301 Mutex::Autolock lock(mMutex);
302 int64_t timestamp;
Andy McFadden3c256212013-08-16 14:55:39 -0700303 bool isAutoTimestamp = false;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800304 if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
Andy McFadden4b49e082013-08-02 15:31:45 -0700305 timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
Andy McFadden3c256212013-08-16 14:55:39 -0700306 isAutoTimestamp = true;
Andy McFadden4b49e082013-08-02 15:31:45 -0700307 ALOGV("Surface::queueBuffer making up timestamp: %.2f ms",
308 timestamp / 1000000.f);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800309 } else {
310 timestamp = mTimestamp;
Mathias Agopian631f3582010-05-25 17:51:34 -0700311 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800312 int i = getSlotFromBufferLocked(buffer);
313 if (i < 0) {
Taiju Tsuiki4d0cd3f2015-04-30 22:15:33 +0900314 if (fenceFd >= 0) {
315 close(fenceFd);
316 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800317 return i;
318 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800319
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800320
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800321 // Make sure the crop rectangle is entirely inside the buffer.
322 Rect crop;
323 mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800324
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800325 sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
326 IGraphicBufferProducer::QueueBufferOutput output;
Andy McFadden3c256212013-08-16 14:55:39 -0700327 IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800328 mDataSpace, crop, mScalingMode, mTransform ^ mStickyTransform,
329 mSwapIntervalZero, fence, mStickyTransform);
Dan Stoza5065a552015-03-17 16:23:42 -0700330
Dan Stozac62acbd2015-04-21 16:42:49 -0700331 if (mConnectedToCpu || mDirtyRegion.bounds() == Rect::INVALID_RECT) {
Dan Stoza5065a552015-03-17 16:23:42 -0700332 input.setSurfaceDamage(Region::INVALID_REGION);
333 } else {
334 // The surface damage was specified using the OpenGL ES convention of
335 // the origin being in the bottom-left corner. Here we flip to the
336 // convention that the rest of the system uses (top-left corner) by
337 // subtracting all top/bottom coordinates from the buffer height.
338 Region flippedRegion;
339 for (auto rect : mDirtyRegion) {
340 auto top = buffer->height - rect.bottom;
341 auto bottom = buffer->height - rect.top;
342 Rect flippedRect{rect.left, top, rect.right, bottom};
343 flippedRegion.orSelf(flippedRect);
344 }
345
346 input.setSurfaceDamage(flippedRegion);
347 }
348
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800349 status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
350 if (err != OK) {
351 ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
352 }
353 uint32_t numPendingBuffers = 0;
Ruben Brunk1681d952014-06-27 15:51:55 -0700354 uint32_t hint = 0;
355 output.deflate(&mDefaultWidth, &mDefaultHeight, &hint,
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800356 &numPendingBuffers);
tedbo1e7fa9e2011-06-22 15:52:53 -0700357
Ruben Brunk1681d952014-06-27 15:51:55 -0700358 // Disable transform hint if sticky transform is set.
359 if (mStickyTransform == 0) {
360 mTransformHint = hint;
361 }
362
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800363 mConsumerRunningBehind = (numPendingBuffers >= 2);
Mathias Agopian631f3582010-05-25 17:51:34 -0700364
Dan Stozac62acbd2015-04-21 16:42:49 -0700365 if (!mConnectedToCpu) {
366 // Clear surface damage back to full-buffer
367 mDirtyRegion = Region::INVALID_REGION;
368 }
Dan Stoza5065a552015-03-17 16:23:42 -0700369
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800370 return err;
371}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700372
Mathias Agopiana67932f2011-04-20 14:20:59 -0700373int Surface::query(int what, int* value) const {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800374 ATRACE_CALL();
375 ALOGV("Surface::query");
376 { // scope for the lock
377 Mutex::Autolock lock(mMutex);
378 switch (what) {
379 case NATIVE_WINDOW_FORMAT:
380 if (mReqFormat) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800381 *value = static_cast<int>(mReqFormat);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800382 return NO_ERROR;
383 }
384 break;
385 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
386 sp<ISurfaceComposer> composer(
387 ComposerService::getComposerService());
388 if (composer->authenticateSurfaceTexture(mGraphicBufferProducer)) {
389 *value = 1;
390 } else {
391 *value = 0;
392 }
393 return NO_ERROR;
394 }
395 case NATIVE_WINDOW_CONCRETE_TYPE:
396 *value = NATIVE_WINDOW_SURFACE;
397 return NO_ERROR;
398 case NATIVE_WINDOW_DEFAULT_WIDTH:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800399 *value = static_cast<int>(
400 mUserWidth ? mUserWidth : mDefaultWidth);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800401 return NO_ERROR;
402 case NATIVE_WINDOW_DEFAULT_HEIGHT:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800403 *value = static_cast<int>(
404 mUserHeight ? mUserHeight : mDefaultHeight);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800405 return NO_ERROR;
406 case NATIVE_WINDOW_TRANSFORM_HINT:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800407 *value = static_cast<int>(mTransformHint);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800408 return NO_ERROR;
409 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: {
410 status_t err = NO_ERROR;
411 if (!mConsumerRunningBehind) {
412 *value = 0;
413 } else {
414 err = mGraphicBufferProducer->query(what, value);
415 if (err == NO_ERROR) {
416 mConsumerRunningBehind = *value;
417 }
418 }
419 return err;
420 }
421 }
Jamie Gennis391bbe22011-03-14 15:00:06 -0700422 }
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800423 return mGraphicBufferProducer->query(what, value);
Eino-Ville Talvala1d01a122011-02-18 11:02:42 -0800424}
425
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800426int Surface::perform(int operation, va_list args)
427{
428 int res = NO_ERROR;
429 switch (operation) {
430 case NATIVE_WINDOW_CONNECT:
431 // deprecated. must return NO_ERROR.
432 break;
433 case NATIVE_WINDOW_DISCONNECT:
434 // deprecated. must return NO_ERROR.
435 break;
436 case NATIVE_WINDOW_SET_USAGE:
437 res = dispatchSetUsage(args);
438 break;
439 case NATIVE_WINDOW_SET_CROP:
440 res = dispatchSetCrop(args);
441 break;
442 case NATIVE_WINDOW_SET_BUFFER_COUNT:
443 res = dispatchSetBufferCount(args);
444 break;
445 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
446 res = dispatchSetBuffersGeometry(args);
447 break;
448 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
449 res = dispatchSetBuffersTransform(args);
450 break;
Ruben Brunk1681d952014-06-27 15:51:55 -0700451 case NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM:
452 res = dispatchSetBuffersStickyTransform(args);
453 break;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800454 case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
455 res = dispatchSetBuffersTimestamp(args);
456 break;
457 case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
458 res = dispatchSetBuffersDimensions(args);
459 break;
460 case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS:
461 res = dispatchSetBuffersUserDimensions(args);
462 break;
463 case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
464 res = dispatchSetBuffersFormat(args);
465 break;
466 case NATIVE_WINDOW_LOCK:
467 res = dispatchLock(args);
468 break;
469 case NATIVE_WINDOW_UNLOCK_AND_POST:
470 res = dispatchUnlockAndPost(args);
471 break;
472 case NATIVE_WINDOW_SET_SCALING_MODE:
473 res = dispatchSetScalingMode(args);
474 break;
475 case NATIVE_WINDOW_API_CONNECT:
476 res = dispatchConnect(args);
477 break;
478 case NATIVE_WINDOW_API_DISCONNECT:
479 res = dispatchDisconnect(args);
480 break;
Rachad7cb0d392014-07-29 17:53:53 -0700481 case NATIVE_WINDOW_SET_SIDEBAND_STREAM:
482 res = dispatchSetSidebandStream(args);
483 break;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800484 case NATIVE_WINDOW_SET_BUFFERS_DATASPACE:
485 res = dispatchSetBuffersDataSpace(args);
486 break;
Dan Stoza5065a552015-03-17 16:23:42 -0700487 case NATIVE_WINDOW_SET_SURFACE_DAMAGE:
488 res = dispatchSetSurfaceDamage(args);
489 break;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800490 default:
491 res = NAME_NOT_FOUND;
492 break;
493 }
494 return res;
495}
Mathias Agopiana138f892010-05-21 17:24:35 -0700496
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800497int Surface::dispatchConnect(va_list args) {
498 int api = va_arg(args, int);
499 return connect(api);
500}
Mathias Agopian55fa2512010-03-11 15:06:54 -0800501
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800502int Surface::dispatchDisconnect(va_list args) {
503 int api = va_arg(args, int);
504 return disconnect(api);
505}
506
507int Surface::dispatchSetUsage(va_list args) {
508 int usage = va_arg(args, int);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800509 return setUsage(static_cast<uint32_t>(usage));
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800510}
511
512int Surface::dispatchSetCrop(va_list args) {
513 android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
514 return setCrop(reinterpret_cast<Rect const*>(rect));
515}
516
517int Surface::dispatchSetBufferCount(va_list args) {
518 size_t bufferCount = va_arg(args, size_t);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800519 return setBufferCount(static_cast<int32_t>(bufferCount));
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800520}
521
522int Surface::dispatchSetBuffersGeometry(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800523 uint32_t width = va_arg(args, uint32_t);
524 uint32_t height = va_arg(args, uint32_t);
525 PixelFormat format = va_arg(args, PixelFormat);
526 int err = setBuffersDimensions(width, height);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800527 if (err != 0) {
528 return err;
529 }
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800530 return setBuffersFormat(format);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800531}
532
533int Surface::dispatchSetBuffersDimensions(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800534 uint32_t width = va_arg(args, uint32_t);
535 uint32_t height = va_arg(args, uint32_t);
536 return setBuffersDimensions(width, height);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800537}
538
539int Surface::dispatchSetBuffersUserDimensions(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800540 uint32_t width = va_arg(args, uint32_t);
541 uint32_t height = va_arg(args, uint32_t);
542 return setBuffersUserDimensions(width, height);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800543}
544
545int Surface::dispatchSetBuffersFormat(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800546 PixelFormat format = va_arg(args, PixelFormat);
547 return setBuffersFormat(format);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800548}
549
550int Surface::dispatchSetScalingMode(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800551 int mode = va_arg(args, int);
552 return setScalingMode(mode);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800553}
554
555int Surface::dispatchSetBuffersTransform(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800556 uint32_t transform = va_arg(args, uint32_t);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800557 return setBuffersTransform(transform);
558}
559
Ruben Brunk1681d952014-06-27 15:51:55 -0700560int Surface::dispatchSetBuffersStickyTransform(va_list args) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800561 uint32_t transform = va_arg(args, uint32_t);
Ruben Brunk1681d952014-06-27 15:51:55 -0700562 return setBuffersStickyTransform(transform);
563}
564
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800565int Surface::dispatchSetBuffersTimestamp(va_list args) {
566 int64_t timestamp = va_arg(args, int64_t);
567 return setBuffersTimestamp(timestamp);
568}
569
570int Surface::dispatchLock(va_list args) {
571 ANativeWindow_Buffer* outBuffer = va_arg(args, ANativeWindow_Buffer*);
572 ARect* inOutDirtyBounds = va_arg(args, ARect*);
573 return lock(outBuffer, inOutDirtyBounds);
574}
575
Igor Murashkin7d2d1602013-11-12 18:02:20 -0800576int Surface::dispatchUnlockAndPost(va_list args __attribute__((unused))) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800577 return unlockAndPost();
578}
579
Rachad7cb0d392014-07-29 17:53:53 -0700580int Surface::dispatchSetSidebandStream(va_list args) {
581 native_handle_t* sH = va_arg(args, native_handle_t*);
582 sp<NativeHandle> sidebandHandle = NativeHandle::create(sH, false);
583 setSidebandStream(sidebandHandle);
584 return OK;
585}
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800586
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800587int Surface::dispatchSetBuffersDataSpace(va_list args) {
588 android_dataspace dataspace =
589 static_cast<android_dataspace>(va_arg(args, int));
590 return setBuffersDataSpace(dataspace);
591}
592
Dan Stoza5065a552015-03-17 16:23:42 -0700593int Surface::dispatchSetSurfaceDamage(va_list args) {
594 android_native_rect_t* rects = va_arg(args, android_native_rect_t*);
595 size_t numRects = va_arg(args, size_t);
596 setSurfaceDamage(rects, numRects);
597 return NO_ERROR;
598}
599
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800600int Surface::connect(int api) {
Dan Stoza966b98b2015-03-02 22:12:37 -0800601 static sp<IProducerListener> listener = new DummyProducerListener();
602 return connect(api, listener);
603}
604
605int Surface::connect(int api, const sp<IProducerListener>& listener) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800606 ATRACE_CALL();
607 ALOGV("Surface::connect");
608 Mutex::Autolock lock(mMutex);
609 IGraphicBufferProducer::QueueBufferOutput output;
Dan Stozaf0eaf252014-03-21 13:05:51 -0700610 int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800611 if (err == NO_ERROR) {
612 uint32_t numPendingBuffers = 0;
Ruben Brunk1681d952014-06-27 15:51:55 -0700613 uint32_t hint = 0;
614 output.deflate(&mDefaultWidth, &mDefaultHeight, &hint,
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800615 &numPendingBuffers);
Ruben Brunk1681d952014-06-27 15:51:55 -0700616
617 // Disable transform hint if sticky transform is set.
618 if (mStickyTransform == 0) {
619 mTransformHint = hint;
620 }
621
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800622 mConsumerRunningBehind = (numPendingBuffers >= 2);
623 }
624 if (!err && api == NATIVE_WINDOW_API_CPU) {
625 mConnectedToCpu = true;
Dan Stoza5065a552015-03-17 16:23:42 -0700626 // Clear the dirty region in case we're switching from a non-CPU API
627 mDirtyRegion.clear();
628 } else if (!err) {
629 // Initialize the dirty region for tracking surface damage
630 mDirtyRegion = Region::INVALID_REGION;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800631 }
Dan Stoza5065a552015-03-17 16:23:42 -0700632
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800633 return err;
634}
635
Mathias Agopian365857d2013-09-11 19:35:45 -0700636
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800637int Surface::disconnect(int api) {
638 ATRACE_CALL();
639 ALOGV("Surface::disconnect");
640 Mutex::Autolock lock(mMutex);
641 freeAllBuffers();
642 int err = mGraphicBufferProducer->disconnect(api);
643 if (!err) {
644 mReqFormat = 0;
645 mReqWidth = 0;
646 mReqHeight = 0;
647 mReqUsage = 0;
648 mCrop.clear();
649 mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
650 mTransform = 0;
Ruben Brunk1681d952014-06-27 15:51:55 -0700651 mStickyTransform = 0;
652
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800653 if (api == NATIVE_WINDOW_API_CPU) {
654 mConnectedToCpu = false;
655 }
656 }
657 return err;
658}
659
Dan Stozad9c49712015-04-27 11:06:01 -0700660int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
Dan Stoza231832e2015-03-11 11:55:01 -0700661 sp<Fence>* outFence) {
662 ATRACE_CALL();
663 ALOGV("Surface::detachNextBuffer");
664
665 if (outBuffer == NULL || outFence == NULL) {
666 return BAD_VALUE;
667 }
668
669 Mutex::Autolock lock(mMutex);
670
671 sp<GraphicBuffer> buffer(NULL);
672 sp<Fence> fence(NULL);
673 status_t result = mGraphicBufferProducer->detachNextBuffer(
674 &buffer, &fence);
675 if (result != NO_ERROR) {
676 return result;
677 }
678
Dan Stozad9c49712015-04-27 11:06:01 -0700679 *outBuffer = buffer;
Dan Stoza231832e2015-03-11 11:55:01 -0700680 if (fence != NULL && fence->isValid()) {
681 *outFence = fence;
682 } else {
683 *outFence = Fence::NO_FENCE;
684 }
685
686 return NO_ERROR;
687}
688
689int Surface::attachBuffer(ANativeWindowBuffer* buffer)
690{
691 ATRACE_CALL();
692 ALOGV("Surface::attachBuffer");
693
694 Mutex::Autolock lock(mMutex);
695
696 sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer));
697 int32_t attachedSlot = -1;
698 status_t result = mGraphicBufferProducer->attachBuffer(
699 &attachedSlot, graphicBuffer);
700 if (result != NO_ERROR) {
701 ALOGE("attachBuffer: IGraphicBufferProducer call failed (%d)", result);
702 return result;
703 }
704 mSlots[attachedSlot].buffer = graphicBuffer;
705
706 return NO_ERROR;
707}
708
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800709int Surface::setUsage(uint32_t reqUsage)
710{
711 ALOGV("Surface::setUsage");
712 Mutex::Autolock lock(mMutex);
713 mReqUsage = reqUsage;
714 return OK;
715}
716
717int Surface::setCrop(Rect const* rect)
718{
719 ATRACE_CALL();
720
721 Rect realRect;
722 if (rect == NULL || rect->isEmpty()) {
723 realRect.clear();
724 } else {
725 realRect = *rect;
Mathias Agopian55fa2512010-03-11 15:06:54 -0800726 }
727
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800728 ALOGV("Surface::setCrop rect=[%d %d %d %d]",
729 realRect.left, realRect.top, realRect.right, realRect.bottom);
730
731 Mutex::Autolock lock(mMutex);
732 mCrop = realRect;
733 return NO_ERROR;
734}
735
736int Surface::setBufferCount(int bufferCount)
737{
738 ATRACE_CALL();
739 ALOGV("Surface::setBufferCount");
740 Mutex::Autolock lock(mMutex);
741
742 status_t err = mGraphicBufferProducer->setBufferCount(bufferCount);
743 ALOGE_IF(err, "IGraphicBufferProducer::setBufferCount(%d) returned %s",
744 bufferCount, strerror(-err));
Mathias Agopian90147262010-01-22 11:47:55 -0800745
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700746 if (err == NO_ERROR) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800747 freeAllBuffers();
Mathias Agopian87a96ea2011-08-23 21:09:41 -0700748 }
749
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700750 return err;
751}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700752
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800753int Surface::setBuffersDimensions(uint32_t width, uint32_t height)
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800754{
755 ATRACE_CALL();
756 ALOGV("Surface::setBuffersDimensions");
757
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800758 if ((width && !height) || (!width && height))
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800759 return BAD_VALUE;
760
761 Mutex::Autolock lock(mMutex);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800762 mReqWidth = width;
763 mReqHeight = height;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800764 return NO_ERROR;
765}
766
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800767int Surface::setBuffersUserDimensions(uint32_t width, uint32_t height)
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800768{
769 ATRACE_CALL();
770 ALOGV("Surface::setBuffersUserDimensions");
771
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800772 if ((width && !height) || (!width && height))
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800773 return BAD_VALUE;
774
775 Mutex::Autolock lock(mMutex);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800776 mUserWidth = width;
777 mUserHeight = height;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800778 return NO_ERROR;
779}
780
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800781int Surface::setBuffersFormat(PixelFormat format)
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800782{
783 ALOGV("Surface::setBuffersFormat");
784
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800785 Mutex::Autolock lock(mMutex);
786 mReqFormat = format;
787 return NO_ERROR;
788}
789
790int Surface::setScalingMode(int mode)
791{
792 ATRACE_CALL();
793 ALOGV("Surface::setScalingMode(%d)", mode);
794
795 switch (mode) {
796 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
797 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
798 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
799 break;
800 default:
801 ALOGE("unknown scaling mode: %d", mode);
802 return BAD_VALUE;
803 }
804
805 Mutex::Autolock lock(mMutex);
806 mScalingMode = mode;
807 return NO_ERROR;
808}
809
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800810int Surface::setBuffersTransform(uint32_t transform)
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800811{
812 ATRACE_CALL();
813 ALOGV("Surface::setBuffersTransform");
814 Mutex::Autolock lock(mMutex);
815 mTransform = transform;
816 return NO_ERROR;
817}
818
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800819int Surface::setBuffersStickyTransform(uint32_t transform)
Ruben Brunk1681d952014-06-27 15:51:55 -0700820{
821 ATRACE_CALL();
822 ALOGV("Surface::setBuffersStickyTransform");
823 Mutex::Autolock lock(mMutex);
824 mStickyTransform = transform;
825 return NO_ERROR;
826}
827
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800828int Surface::setBuffersTimestamp(int64_t timestamp)
829{
830 ALOGV("Surface::setBuffersTimestamp");
831 Mutex::Autolock lock(mMutex);
832 mTimestamp = timestamp;
833 return NO_ERROR;
834}
835
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800836int Surface::setBuffersDataSpace(android_dataspace dataSpace)
837{
838 ALOGV("Surface::setBuffersDataSpace");
839 Mutex::Autolock lock(mMutex);
840 mDataSpace = dataSpace;
841 return NO_ERROR;
842}
843
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800844void Surface::freeAllBuffers() {
845 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
846 mSlots[i].buffer = 0;
847 }
848}
849
Dan Stoza5065a552015-03-17 16:23:42 -0700850void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) {
851 ATRACE_CALL();
852 ALOGV("Surface::setSurfaceDamage");
853 Mutex::Autolock lock(mMutex);
854
Dan Stozac62acbd2015-04-21 16:42:49 -0700855 if (mConnectedToCpu || numRects == 0) {
Dan Stoza5065a552015-03-17 16:23:42 -0700856 mDirtyRegion = Region::INVALID_REGION;
857 return;
858 }
859
860 mDirtyRegion.clear();
861 for (size_t r = 0; r < numRects; ++r) {
862 // We intentionally flip top and bottom here, since because they're
863 // specified with a bottom-left origin, top > bottom, which fails
864 // validation in the Region class. We will fix this up when we flip to a
865 // top-left origin in queueBuffer.
866 Rect rect(rects[r].left, rects[r].bottom, rects[r].right, rects[r].top);
867 mDirtyRegion.orSelf(rect);
868 }
869}
870
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800871// ----------------------------------------------------------------------
872// the lock/unlock APIs must be used from the same thread
873
874static status_t copyBlt(
875 const sp<GraphicBuffer>& dst,
876 const sp<GraphicBuffer>& src,
877 const Region& reg)
878{
879 // src and dst with, height and format must be identical. no verification
880 // is done here.
881 status_t err;
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800882 uint8_t* src_bits = NULL;
883 err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(),
884 reinterpret_cast<void**>(&src_bits));
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800885 ALOGE_IF(err, "error locking src buffer %s", strerror(-err));
886
887 uint8_t* dst_bits = NULL;
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800888 err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(),
889 reinterpret_cast<void**>(&dst_bits));
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800890 ALOGE_IF(err, "error locking dst buffer %s", strerror(-err));
891
892 Region::const_iterator head(reg.begin());
893 Region::const_iterator tail(reg.end());
894 if (head != tail && src_bits && dst_bits) {
895 const size_t bpp = bytesPerPixel(src->format);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800896 const size_t dbpr = static_cast<uint32_t>(dst->stride) * bpp;
897 const size_t sbpr = static_cast<uint32_t>(src->stride) * bpp;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800898
899 while (head != tail) {
900 const Rect& r(*head++);
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800901 int32_t h = r.height();
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800902 if (h <= 0) continue;
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800903 size_t size = static_cast<uint32_t>(r.width()) * bpp;
904 uint8_t const * s = src_bits +
905 static_cast<uint32_t>(r.left + src->stride * r.top) * bpp;
906 uint8_t * d = dst_bits +
907 static_cast<uint32_t>(r.left + dst->stride * r.top) * bpp;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800908 if (dbpr==sbpr && size==sbpr) {
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800909 size *= static_cast<size_t>(h);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800910 h = 1;
911 }
912 do {
913 memcpy(d, s, size);
914 d += dbpr;
915 s += sbpr;
916 } while (--h > 0);
917 }
918 }
919
920 if (src_bits)
921 src->unlock();
922
923 if (dst_bits)
924 dst->unlock();
925
926 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800927}
928
Mathias Agopiana138f892010-05-21 17:24:35 -0700929// ----------------------------------------------------------------------------
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800930
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800931status_t Surface::lock(
932 ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
933{
934 if (mLockedBuffer != 0) {
935 ALOGE("Surface::lock failed, already locked");
936 return INVALID_OPERATION;
937 }
938
939 if (!mConnectedToCpu) {
940 int err = Surface::connect(NATIVE_WINDOW_API_CPU);
941 if (err) {
942 return err;
943 }
944 // we're intending to do software rendering from this point
945 setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
946 }
947
948 ANativeWindowBuffer* out;
949 int fenceFd = -1;
950 status_t err = dequeueBuffer(&out, &fenceFd);
951 ALOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
952 if (err == NO_ERROR) {
953 sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800954 const Rect bounds(backBuffer->width, backBuffer->height);
955
956 Region newDirtyRegion;
957 if (inOutDirtyBounds) {
958 newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds));
959 newDirtyRegion.andSelf(bounds);
960 } else {
961 newDirtyRegion.set(bounds);
962 }
963
964 // figure out if we can copy the frontbuffer back
965 const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
966 const bool canCopyBack = (frontBuffer != 0 &&
967 backBuffer->width == frontBuffer->width &&
968 backBuffer->height == frontBuffer->height &&
969 backBuffer->format == frontBuffer->format);
970
971 if (canCopyBack) {
972 // copy the area that is invalid and not repainted this round
973 const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
974 if (!copyback.isEmpty())
975 copyBlt(backBuffer, frontBuffer, copyback);
976 } else {
977 // if we can't copy-back anything, modify the user's dirty
978 // region to make sure they redraw the whole buffer
979 newDirtyRegion.set(bounds);
980 mDirtyRegion.clear();
981 Mutex::Autolock lock(mMutex);
982 for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
983 mSlots[i].dirtyRegion.clear();
984 }
985 }
986
987
988 { // scope for the lock
989 Mutex::Autolock lock(mMutex);
990 int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
991 if (backBufferSlot >= 0) {
992 Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
993 mDirtyRegion.subtract(dirtyRegion);
994 dirtyRegion = newDirtyRegion;
995 }
996 }
997
998 mDirtyRegion.orSelf(newDirtyRegion);
999 if (inOutDirtyBounds) {
1000 *inOutDirtyBounds = newDirtyRegion.getBounds();
1001 }
1002
1003 void* vaddr;
Francis Hart8f396012014-04-01 15:30:53 +03001004 status_t res = backBuffer->lockAsync(
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001005 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
Francis Hart8f396012014-04-01 15:30:53 +03001006 newDirtyRegion.bounds(), &vaddr, fenceFd);
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001007
1008 ALOGW_IF(res, "failed locking buffer (handle = %p)",
1009 backBuffer->handle);
1010
1011 if (res != 0) {
1012 err = INVALID_OPERATION;
1013 } else {
1014 mLockedBuffer = backBuffer;
1015 outBuffer->width = backBuffer->width;
1016 outBuffer->height = backBuffer->height;
1017 outBuffer->stride = backBuffer->stride;
1018 outBuffer->format = backBuffer->format;
1019 outBuffer->bits = vaddr;
1020 }
1021 }
1022 return err;
1023}
1024
1025status_t Surface::unlockAndPost()
1026{
1027 if (mLockedBuffer == 0) {
1028 ALOGE("Surface::unlockAndPost failed, no locked buffer");
1029 return INVALID_OPERATION;
1030 }
1031
Francis Hart8f396012014-04-01 15:30:53 +03001032 int fd = -1;
1033 status_t err = mLockedBuffer->unlockAsync(&fd);
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001034 ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
1035
Francis Hart8f396012014-04-01 15:30:53 +03001036 err = queueBuffer(mLockedBuffer.get(), fd);
Mathias Agopiane3c697f2013-02-14 17:11:02 -08001037 ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
1038 mLockedBuffer->handle, strerror(-err));
1039
1040 mPostedBuffer = mLockedBuffer;
1041 mLockedBuffer = 0;
1042 return err;
1043}
1044
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001045}; // namespace android