2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "Surface"
18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19 //#define LOG_NDEBUG 0
21 #include <android/native_window.h>
23 #include <binder/Parcel.h>
25 #include <utils/Log.h>
26 #include <utils/Trace.h>
27 #include <utils/NativeHandle.h>
30 #include <ui/Region.h>
32 #include <gui/IProducerListener.h>
33 #include <gui/ISurfaceComposer.h>
34 #include <gui/SurfaceComposerClient.h>
35 #include <gui/GLConsumer.h>
36 #include <gui/Surface.h>
38 #include <private/gui/ComposerService.h>
43 const sp<IGraphicBufferProducer>& bufferProducer,
45 : mGraphicBufferProducer(bufferProducer),
48 // Initialize the ANativeWindow function pointers.
49 ANativeWindow::setSwapInterval = hook_setSwapInterval;
50 ANativeWindow::dequeueBuffer = hook_dequeueBuffer;
51 ANativeWindow::cancelBuffer = hook_cancelBuffer;
52 ANativeWindow::queueBuffer = hook_queueBuffer;
53 ANativeWindow::query = hook_query;
54 ANativeWindow::perform = hook_perform;
56 ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
57 ANativeWindow::cancelBuffer_DEPRECATED = hook_cancelBuffer_DEPRECATED;
58 ANativeWindow::lockBuffer_DEPRECATED = hook_lockBuffer_DEPRECATED;
59 ANativeWindow::queueBuffer_DEPRECATED = hook_queueBuffer_DEPRECATED;
61 const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
62 const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
68 mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
69 mDataSpace = HAL_DATASPACE_UNKNOWN;
71 mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
79 mConsumerRunningBehind = false;
80 mConnectedToCpu = false;
81 mProducerControlledByApp = controlledByApp;
82 mSwapIntervalZero = false;
86 if (mConnectedToCpu) {
87 Surface::disconnect(NATIVE_WINDOW_API_CPU);
91 sp<IGraphicBufferProducer> Surface::getIGraphicBufferProducer() const {
92 return mGraphicBufferProducer;
95 void Surface::setSidebandStream(const sp<NativeHandle>& stream) {
96 mGraphicBufferProducer->setSidebandStream(stream);
99 void Surface::allocateBuffers() {
100 uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth;
101 uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight;
102 mGraphicBufferProducer->allocateBuffers(mSwapIntervalZero, reqWidth,
103 reqHeight, mReqFormat, mReqUsage);
106 status_t Surface::setGenerationNumber(uint32_t generation) {
107 status_t result = mGraphicBufferProducer->setGenerationNumber(generation);
108 if (result == NO_ERROR) {
109 mGenerationNumber = generation;
114 String8 Surface::getConsumerName() const {
115 return mGraphicBufferProducer->getConsumerName();
118 int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
119 Surface* c = getSelf(window);
120 return c->setSwapInterval(interval);
123 int Surface::hook_dequeueBuffer(ANativeWindow* window,
124 ANativeWindowBuffer** buffer, int* fenceFd) {
125 Surface* c = getSelf(window);
126 return c->dequeueBuffer(buffer, fenceFd);
129 int Surface::hook_cancelBuffer(ANativeWindow* window,
130 ANativeWindowBuffer* buffer, int fenceFd) {
131 Surface* c = getSelf(window);
132 return c->cancelBuffer(buffer, fenceFd);
135 int Surface::hook_queueBuffer(ANativeWindow* window,
136 ANativeWindowBuffer* buffer, int fenceFd) {
137 Surface* c = getSelf(window);
138 return c->queueBuffer(buffer, fenceFd);
141 int Surface::hook_dequeueBuffer_DEPRECATED(ANativeWindow* window,
142 ANativeWindowBuffer** buffer) {
143 Surface* c = getSelf(window);
144 ANativeWindowBuffer* buf = NULL;
146 int result = c->dequeueBuffer(&buf, &fenceFd);
148 if (result != NO_ERROR) return result;
150 sp<Fence> fence(new Fence(fenceFd));
151 int waitResult = fence->waitForever("dequeueBuffer_DEPRECATED");
152 if (waitResult != OK) {
153 ALOGE("dequeueBuffer_DEPRECATED: Fence::wait returned an error: %d",
155 c->cancelBuffer(buf, -1);
162 int Surface::hook_cancelBuffer_DEPRECATED(ANativeWindow* window,
163 ANativeWindowBuffer* buffer) {
164 Surface* c = getSelf(window);
165 return c->cancelBuffer(buffer, -1);
168 int Surface::hook_lockBuffer_DEPRECATED(ANativeWindow* window,
169 ANativeWindowBuffer* buffer) {
170 Surface* c = getSelf(window);
171 return c->lockBuffer_DEPRECATED(buffer);
174 int Surface::hook_queueBuffer_DEPRECATED(ANativeWindow* window,
175 ANativeWindowBuffer* buffer) {
176 Surface* c = getSelf(window);
177 return c->queueBuffer(buffer, -1);
180 int Surface::hook_query(const ANativeWindow* window,
181 int what, int* value) {
182 const Surface* c = getSelf(window);
183 return c->query(what, value);
186 int Surface::hook_perform(ANativeWindow* window, int operation, ...) {
188 va_start(args, operation);
189 Surface* c = getSelf(window);
190 return c->perform(operation, args);
193 int Surface::setSwapInterval(int interval) {
195 // EGL specification states:
196 // interval is silently clamped to minimum and maximum implementation
197 // dependent values before being stored.
199 if (interval < minSwapInterval)
200 interval = minSwapInterval;
202 if (interval > maxSwapInterval)
203 interval = maxSwapInterval;
205 mSwapIntervalZero = (interval == 0);
210 int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
212 ALOGV("Surface::dequeueBuffer");
216 bool swapIntervalZero;
217 PixelFormat reqFormat;
221 Mutex::Autolock lock(mMutex);
223 reqWidth = mReqWidth ? mReqWidth : mUserWidth;
224 reqHeight = mReqHeight ? mReqHeight : mUserHeight;
226 swapIntervalZero = mSwapIntervalZero;
227 reqFormat = mReqFormat;
228 reqUsage = mReqUsage;
229 } // Drop the lock so that we can still touch the Surface while blocking in IGBP::dequeueBuffer
233 status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, swapIntervalZero,
234 reqWidth, reqHeight, reqFormat, reqUsage);
237 ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d, %d)"
238 "failed: %d", swapIntervalZero, reqWidth, reqHeight, reqFormat,
243 Mutex::Autolock lock(mMutex);
245 sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
247 // this should never happen
248 ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);
250 if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
254 if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
255 result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
256 if (result != NO_ERROR) {
257 ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result);
258 mGraphicBufferProducer->cancelBuffer(buf, fence);
263 if ((fence != NULL) && fence->isValid()) {
264 *fenceFd = fence->dup();
265 if (*fenceFd == -1) {
266 ALOGE("dequeueBuffer: error duping fence: %d", errno);
267 // dup() should never fail; something is badly wrong. Soldier on
268 // and hope for the best; the worst that should happen is some
269 // visible corruption that lasts until the next frame.
275 *buffer = gbuf.get();
279 int Surface::cancelBuffer(android_native_buffer_t* buffer,
282 ALOGV("Surface::cancelBuffer");
283 Mutex::Autolock lock(mMutex);
284 int i = getSlotFromBufferLocked(buffer);
291 sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
292 mGraphicBufferProducer->cancelBuffer(i, fence);
296 int Surface::getSlotFromBufferLocked(
297 android_native_buffer_t* buffer) const {
298 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
299 if (mSlots[i].buffer != NULL &&
300 mSlots[i].buffer->handle == buffer->handle) {
304 ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
308 int Surface::lockBuffer_DEPRECATED(android_native_buffer_t* buffer __attribute__((unused))) {
309 ALOGV("Surface::lockBuffer");
310 Mutex::Autolock lock(mMutex);
314 int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
316 ALOGV("Surface::queueBuffer");
317 Mutex::Autolock lock(mMutex);
319 bool isAutoTimestamp = false;
320 if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
321 timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
322 isAutoTimestamp = true;
323 ALOGV("Surface::queueBuffer making up timestamp: %.2f ms",
324 timestamp / 1000000.f);
326 timestamp = mTimestamp;
328 int i = getSlotFromBufferLocked(buffer);
337 // Make sure the crop rectangle is entirely inside the buffer.
339 mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
341 sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
342 IGraphicBufferProducer::QueueBufferOutput output;
343 IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
344 mDataSpace, crop, mScalingMode, mTransform ^ mStickyTransform,
345 mSwapIntervalZero, fence, mStickyTransform);
347 if (mConnectedToCpu || mDirtyRegion.bounds() == Rect::INVALID_RECT) {
348 input.setSurfaceDamage(Region::INVALID_REGION);
350 // Here we do two things:
351 // 1) The surface damage was specified using the OpenGL ES convention of
352 // the origin being in the bottom-left corner. Here we flip to the
353 // convention that the rest of the system uses (top-left corner) by
354 // subtracting all top/bottom coordinates from the buffer height.
355 // 2) If the buffer is coming in rotated (for example, because the EGL
356 // implementation is reacting to the transform hint coming back from
357 // SurfaceFlinger), the surface damage needs to be rotated the
358 // opposite direction, since it was generated assuming an unrotated
359 // buffer (the app doesn't know that the EGL implementation is
360 // reacting to the transform hint behind its back). The
361 // transformations in the switch statement below apply those
362 // complementary rotations (e.g., if 90 degrees, rotate 270 degrees).
364 int width = buffer->width;
365 int height = buffer->height;
366 bool rotated90 = (mTransform ^ mStickyTransform) &
367 NATIVE_WINDOW_TRANSFORM_ROT_90;
369 std::swap(width, height);
372 Region flippedRegion;
373 for (auto rect : mDirtyRegion) {
374 int left = rect.left;
375 int right = rect.right;
376 int top = height - rect.bottom; // Flip from OpenGL convention
377 int bottom = height - rect.top; // Flip from OpenGL convention
378 switch (mTransform ^ mStickyTransform) {
379 case NATIVE_WINDOW_TRANSFORM_ROT_90: {
380 // Rotate 270 degrees
381 Rect flippedRect{top, width - right, bottom, width - left};
382 flippedRegion.orSelf(flippedRect);
385 case NATIVE_WINDOW_TRANSFORM_ROT_180: {
386 // Rotate 180 degrees
387 Rect flippedRect{width - right, height - bottom,
388 width - left, height - top};
389 flippedRegion.orSelf(flippedRect);
392 case NATIVE_WINDOW_TRANSFORM_ROT_270: {
394 Rect flippedRect{height - bottom, left,
395 height - top, right};
396 flippedRegion.orSelf(flippedRect);
400 Rect flippedRect{left, top, right, bottom};
401 flippedRegion.orSelf(flippedRect);
407 input.setSurfaceDamage(flippedRegion);
410 status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
412 ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
414 uint32_t numPendingBuffers = 0;
416 output.deflate(&mDefaultWidth, &mDefaultHeight, &hint,
419 // Disable transform hint if sticky transform is set.
420 if (mStickyTransform == 0) {
421 mTransformHint = hint;
424 mConsumerRunningBehind = (numPendingBuffers >= 2);
426 if (!mConnectedToCpu) {
427 // Clear surface damage back to full-buffer
428 mDirtyRegion = Region::INVALID_REGION;
434 int Surface::query(int what, int* value) const {
436 ALOGV("Surface::query");
437 { // scope for the lock
438 Mutex::Autolock lock(mMutex);
440 case NATIVE_WINDOW_FORMAT:
442 *value = static_cast<int>(mReqFormat);
446 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
447 sp<ISurfaceComposer> composer(
448 ComposerService::getComposerService());
449 if (composer->authenticateSurfaceTexture(mGraphicBufferProducer)) {
456 case NATIVE_WINDOW_CONCRETE_TYPE:
457 *value = NATIVE_WINDOW_SURFACE;
459 case NATIVE_WINDOW_DEFAULT_WIDTH:
460 *value = static_cast<int>(
461 mUserWidth ? mUserWidth : mDefaultWidth);
463 case NATIVE_WINDOW_DEFAULT_HEIGHT:
464 *value = static_cast<int>(
465 mUserHeight ? mUserHeight : mDefaultHeight);
467 case NATIVE_WINDOW_TRANSFORM_HINT:
468 *value = static_cast<int>(mTransformHint);
470 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: {
471 status_t err = NO_ERROR;
472 if (!mConsumerRunningBehind) {
475 err = mGraphicBufferProducer->query(what, value);
476 if (err == NO_ERROR) {
477 mConsumerRunningBehind = *value;
484 return mGraphicBufferProducer->query(what, value);
487 int Surface::perform(int operation, va_list args)
491 case NATIVE_WINDOW_CONNECT:
492 // deprecated. must return NO_ERROR.
494 case NATIVE_WINDOW_DISCONNECT:
495 // deprecated. must return NO_ERROR.
497 case NATIVE_WINDOW_SET_USAGE:
498 res = dispatchSetUsage(args);
500 case NATIVE_WINDOW_SET_CROP:
501 res = dispatchSetCrop(args);
503 case NATIVE_WINDOW_SET_BUFFER_COUNT:
504 res = dispatchSetBufferCount(args);
506 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
507 res = dispatchSetBuffersGeometry(args);
509 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
510 res = dispatchSetBuffersTransform(args);
512 case NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM:
513 res = dispatchSetBuffersStickyTransform(args);
515 case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
516 res = dispatchSetBuffersTimestamp(args);
518 case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
519 res = dispatchSetBuffersDimensions(args);
521 case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS:
522 res = dispatchSetBuffersUserDimensions(args);
524 case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
525 res = dispatchSetBuffersFormat(args);
527 case NATIVE_WINDOW_LOCK:
528 res = dispatchLock(args);
530 case NATIVE_WINDOW_UNLOCK_AND_POST:
531 res = dispatchUnlockAndPost(args);
533 case NATIVE_WINDOW_SET_SCALING_MODE:
534 res = dispatchSetScalingMode(args);
536 case NATIVE_WINDOW_API_CONNECT:
537 res = dispatchConnect(args);
539 case NATIVE_WINDOW_API_DISCONNECT:
540 res = dispatchDisconnect(args);
542 case NATIVE_WINDOW_SET_SIDEBAND_STREAM:
543 res = dispatchSetSidebandStream(args);
545 case NATIVE_WINDOW_SET_BUFFERS_DATASPACE:
546 res = dispatchSetBuffersDataSpace(args);
548 case NATIVE_WINDOW_SET_SURFACE_DAMAGE:
549 res = dispatchSetSurfaceDamage(args);
552 res = NAME_NOT_FOUND;
558 int Surface::dispatchConnect(va_list args) {
559 int api = va_arg(args, int);
563 int Surface::dispatchDisconnect(va_list args) {
564 int api = va_arg(args, int);
565 return disconnect(api);
568 int Surface::dispatchSetUsage(va_list args) {
569 int usage = va_arg(args, int);
570 return setUsage(static_cast<uint32_t>(usage));
573 int Surface::dispatchSetCrop(va_list args) {
574 android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
575 return setCrop(reinterpret_cast<Rect const*>(rect));
578 int Surface::dispatchSetBufferCount(va_list args) {
579 size_t bufferCount = va_arg(args, size_t);
580 return setBufferCount(static_cast<int32_t>(bufferCount));
583 int Surface::dispatchSetBuffersGeometry(va_list args) {
584 uint32_t width = va_arg(args, uint32_t);
585 uint32_t height = va_arg(args, uint32_t);
586 PixelFormat format = va_arg(args, PixelFormat);
587 int err = setBuffersDimensions(width, height);
591 return setBuffersFormat(format);
594 int Surface::dispatchSetBuffersDimensions(va_list args) {
595 uint32_t width = va_arg(args, uint32_t);
596 uint32_t height = va_arg(args, uint32_t);
597 return setBuffersDimensions(width, height);
600 int Surface::dispatchSetBuffersUserDimensions(va_list args) {
601 uint32_t width = va_arg(args, uint32_t);
602 uint32_t height = va_arg(args, uint32_t);
603 return setBuffersUserDimensions(width, height);
606 int Surface::dispatchSetBuffersFormat(va_list args) {
607 PixelFormat format = va_arg(args, PixelFormat);
608 return setBuffersFormat(format);
611 int Surface::dispatchSetScalingMode(va_list args) {
612 int mode = va_arg(args, int);
613 return setScalingMode(mode);
616 int Surface::dispatchSetBuffersTransform(va_list args) {
617 uint32_t transform = va_arg(args, uint32_t);
618 return setBuffersTransform(transform);
621 int Surface::dispatchSetBuffersStickyTransform(va_list args) {
622 uint32_t transform = va_arg(args, uint32_t);
623 return setBuffersStickyTransform(transform);
626 int Surface::dispatchSetBuffersTimestamp(va_list args) {
627 int64_t timestamp = va_arg(args, int64_t);
628 return setBuffersTimestamp(timestamp);
631 int Surface::dispatchLock(va_list args) {
632 ANativeWindow_Buffer* outBuffer = va_arg(args, ANativeWindow_Buffer*);
633 ARect* inOutDirtyBounds = va_arg(args, ARect*);
634 return lock(outBuffer, inOutDirtyBounds);
637 int Surface::dispatchUnlockAndPost(va_list args __attribute__((unused))) {
638 return unlockAndPost();
641 int Surface::dispatchSetSidebandStream(va_list args) {
642 native_handle_t* sH = va_arg(args, native_handle_t*);
643 sp<NativeHandle> sidebandHandle = NativeHandle::create(sH, false);
644 setSidebandStream(sidebandHandle);
648 int Surface::dispatchSetBuffersDataSpace(va_list args) {
649 android_dataspace dataspace =
650 static_cast<android_dataspace>(va_arg(args, int));
651 return setBuffersDataSpace(dataspace);
654 int Surface::dispatchSetSurfaceDamage(va_list args) {
655 android_native_rect_t* rects = va_arg(args, android_native_rect_t*);
656 size_t numRects = va_arg(args, size_t);
657 setSurfaceDamage(rects, numRects);
661 int Surface::connect(int api) {
662 static sp<IProducerListener> listener = new DummyProducerListener();
663 return connect(api, listener);
666 int Surface::connect(int api, const sp<IProducerListener>& listener) {
668 ALOGV("Surface::connect");
669 Mutex::Autolock lock(mMutex);
670 IGraphicBufferProducer::QueueBufferOutput output;
671 int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output);
672 if (err == NO_ERROR) {
673 uint32_t numPendingBuffers = 0;
675 output.deflate(&mDefaultWidth, &mDefaultHeight, &hint,
678 // Disable transform hint if sticky transform is set.
679 if (mStickyTransform == 0) {
680 mTransformHint = hint;
683 mConsumerRunningBehind = (numPendingBuffers >= 2);
685 if (!err && api == NATIVE_WINDOW_API_CPU) {
686 mConnectedToCpu = true;
687 // Clear the dirty region in case we're switching from a non-CPU API
688 mDirtyRegion.clear();
690 // Initialize the dirty region for tracking surface damage
691 mDirtyRegion = Region::INVALID_REGION;
698 int Surface::disconnect(int api) {
700 ALOGV("Surface::disconnect");
701 Mutex::Autolock lock(mMutex);
703 int err = mGraphicBufferProducer->disconnect(api);
710 mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
712 mStickyTransform = 0;
714 if (api == NATIVE_WINDOW_API_CPU) {
715 mConnectedToCpu = false;
721 int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
722 sp<Fence>* outFence) {
724 ALOGV("Surface::detachNextBuffer");
726 if (outBuffer == NULL || outFence == NULL) {
730 Mutex::Autolock lock(mMutex);
732 sp<GraphicBuffer> buffer(NULL);
733 sp<Fence> fence(NULL);
734 status_t result = mGraphicBufferProducer->detachNextBuffer(
736 if (result != NO_ERROR) {
741 if (fence != NULL && fence->isValid()) {
744 *outFence = Fence::NO_FENCE;
750 int Surface::attachBuffer(ANativeWindowBuffer* buffer)
753 ALOGV("Surface::attachBuffer");
755 Mutex::Autolock lock(mMutex);
757 sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer));
758 uint32_t priorGeneration = graphicBuffer->mGenerationNumber;
759 graphicBuffer->mGenerationNumber = mGenerationNumber;
760 int32_t attachedSlot = -1;
761 status_t result = mGraphicBufferProducer->attachBuffer(
762 &attachedSlot, graphicBuffer);
763 if (result != NO_ERROR) {
764 ALOGE("attachBuffer: IGraphicBufferProducer call failed (%d)", result);
765 graphicBuffer->mGenerationNumber = priorGeneration;
768 mSlots[attachedSlot].buffer = graphicBuffer;
773 int Surface::setUsage(uint32_t reqUsage)
775 ALOGV("Surface::setUsage");
776 Mutex::Autolock lock(mMutex);
777 mReqUsage = reqUsage;
781 int Surface::setCrop(Rect const* rect)
786 if (rect == NULL || rect->isEmpty()) {
792 ALOGV("Surface::setCrop rect=[%d %d %d %d]",
793 realRect.left, realRect.top, realRect.right, realRect.bottom);
795 Mutex::Autolock lock(mMutex);
800 int Surface::setBufferCount(int bufferCount)
803 ALOGV("Surface::setBufferCount");
804 Mutex::Autolock lock(mMutex);
806 status_t err = mGraphicBufferProducer->setBufferCount(bufferCount);
807 ALOGE_IF(err, "IGraphicBufferProducer::setBufferCount(%d) returned %s",
808 bufferCount, strerror(-err));
810 if (err == NO_ERROR) {
817 int Surface::setBuffersDimensions(uint32_t width, uint32_t height)
820 ALOGV("Surface::setBuffersDimensions");
822 if ((width && !height) || (!width && height))
825 Mutex::Autolock lock(mMutex);
831 int Surface::setBuffersUserDimensions(uint32_t width, uint32_t height)
834 ALOGV("Surface::setBuffersUserDimensions");
836 if ((width && !height) || (!width && height))
839 Mutex::Autolock lock(mMutex);
841 mUserHeight = height;
845 int Surface::setBuffersFormat(PixelFormat format)
847 ALOGV("Surface::setBuffersFormat");
849 Mutex::Autolock lock(mMutex);
854 int Surface::setScalingMode(int mode)
857 ALOGV("Surface::setScalingMode(%d)", mode);
860 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
861 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
862 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
865 ALOGE("unknown scaling mode: %d", mode);
869 Mutex::Autolock lock(mMutex);
874 int Surface::setBuffersTransform(uint32_t transform)
877 ALOGV("Surface::setBuffersTransform");
878 Mutex::Autolock lock(mMutex);
879 mTransform = transform;
883 int Surface::setBuffersStickyTransform(uint32_t transform)
886 ALOGV("Surface::setBuffersStickyTransform");
887 Mutex::Autolock lock(mMutex);
888 mStickyTransform = transform;
892 int Surface::setBuffersTimestamp(int64_t timestamp)
894 ALOGV("Surface::setBuffersTimestamp");
895 Mutex::Autolock lock(mMutex);
896 mTimestamp = timestamp;
900 int Surface::setBuffersDataSpace(android_dataspace dataSpace)
902 ALOGV("Surface::setBuffersDataSpace");
903 Mutex::Autolock lock(mMutex);
904 mDataSpace = dataSpace;
908 void Surface::freeAllBuffers() {
909 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
910 mSlots[i].buffer = 0;
914 void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) {
916 ALOGV("Surface::setSurfaceDamage");
917 Mutex::Autolock lock(mMutex);
919 if (mConnectedToCpu || numRects == 0) {
920 mDirtyRegion = Region::INVALID_REGION;
924 mDirtyRegion.clear();
925 for (size_t r = 0; r < numRects; ++r) {
926 // We intentionally flip top and bottom here, since because they're
927 // specified with a bottom-left origin, top > bottom, which fails
928 // validation in the Region class. We will fix this up when we flip to a
929 // top-left origin in queueBuffer.
930 Rect rect(rects[r].left, rects[r].bottom, rects[r].right, rects[r].top);
931 mDirtyRegion.orSelf(rect);
935 // ----------------------------------------------------------------------
936 // the lock/unlock APIs must be used from the same thread
938 static status_t copyBlt(
939 const sp<GraphicBuffer>& dst,
940 const sp<GraphicBuffer>& src,
943 // src and dst with, height and format must be identical. no verification
946 uint8_t* src_bits = NULL;
947 err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(),
948 reinterpret_cast<void**>(&src_bits));
949 ALOGE_IF(err, "error locking src buffer %s", strerror(-err));
951 uint8_t* dst_bits = NULL;
952 err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(),
953 reinterpret_cast<void**>(&dst_bits));
954 ALOGE_IF(err, "error locking dst buffer %s", strerror(-err));
956 Region::const_iterator head(reg.begin());
957 Region::const_iterator tail(reg.end());
958 if (head != tail && src_bits && dst_bits) {
959 const size_t bpp = bytesPerPixel(src->format);
960 const size_t dbpr = static_cast<uint32_t>(dst->stride) * bpp;
961 const size_t sbpr = static_cast<uint32_t>(src->stride) * bpp;
963 while (head != tail) {
964 const Rect& r(*head++);
965 int32_t h = r.height();
966 if (h <= 0) continue;
967 size_t size = static_cast<uint32_t>(r.width()) * bpp;
968 uint8_t const * s = src_bits +
969 static_cast<uint32_t>(r.left + src->stride * r.top) * bpp;
970 uint8_t * d = dst_bits +
971 static_cast<uint32_t>(r.left + dst->stride * r.top) * bpp;
972 if (dbpr==sbpr && size==sbpr) {
973 size *= static_cast<size_t>(h);
993 // ----------------------------------------------------------------------------
995 status_t Surface::lock(
996 ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
998 if (mLockedBuffer != 0) {
999 ALOGE("Surface::lock failed, already locked");
1000 return INVALID_OPERATION;
1003 if (!mConnectedToCpu) {
1004 int err = Surface::connect(NATIVE_WINDOW_API_CPU);
1008 // we're intending to do software rendering from this point
1009 setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
1012 ANativeWindowBuffer* out;
1014 status_t err = dequeueBuffer(&out, &fenceFd);
1015 ALOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
1016 if (err == NO_ERROR) {
1017 sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
1018 const Rect bounds(backBuffer->width, backBuffer->height);
1020 Region newDirtyRegion;
1021 if (inOutDirtyBounds) {
1022 newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds));
1023 newDirtyRegion.andSelf(bounds);
1025 newDirtyRegion.set(bounds);
1028 // figure out if we can copy the frontbuffer back
1029 const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
1030 const bool canCopyBack = (frontBuffer != 0 &&
1031 backBuffer->width == frontBuffer->width &&
1032 backBuffer->height == frontBuffer->height &&
1033 backBuffer->format == frontBuffer->format);
1036 // copy the area that is invalid and not repainted this round
1037 const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
1038 if (!copyback.isEmpty())
1039 copyBlt(backBuffer, frontBuffer, copyback);
1041 // if we can't copy-back anything, modify the user's dirty
1042 // region to make sure they redraw the whole buffer
1043 newDirtyRegion.set(bounds);
1044 mDirtyRegion.clear();
1045 Mutex::Autolock lock(mMutex);
1046 for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
1047 mSlots[i].dirtyRegion.clear();
1052 { // scope for the lock
1053 Mutex::Autolock lock(mMutex);
1054 int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
1055 if (backBufferSlot >= 0) {
1056 Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
1057 mDirtyRegion.subtract(dirtyRegion);
1058 dirtyRegion = newDirtyRegion;
1062 mDirtyRegion.orSelf(newDirtyRegion);
1063 if (inOutDirtyBounds) {
1064 *inOutDirtyBounds = newDirtyRegion.getBounds();
1068 status_t res = backBuffer->lockAsync(
1069 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
1070 newDirtyRegion.bounds(), &vaddr, fenceFd);
1072 ALOGW_IF(res, "failed locking buffer (handle = %p)",
1073 backBuffer->handle);
1076 err = INVALID_OPERATION;
1078 mLockedBuffer = backBuffer;
1079 outBuffer->width = backBuffer->width;
1080 outBuffer->height = backBuffer->height;
1081 outBuffer->stride = backBuffer->stride;
1082 outBuffer->format = backBuffer->format;
1083 outBuffer->bits = vaddr;
1089 status_t Surface::unlockAndPost()
1091 if (mLockedBuffer == 0) {
1092 ALOGE("Surface::unlockAndPost failed, no locked buffer");
1093 return INVALID_OPERATION;
1097 status_t err = mLockedBuffer->unlockAsync(&fd);
1098 ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
1100 err = queueBuffer(mLockedBuffer.get(), fd);
1101 ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
1102 mLockedBuffer->handle, strerror(-err));
1104 mPostedBuffer = mLockedBuffer;
1109 }; // namespace android