diff options
Diffstat (limited to 'libs/gui/Surface.cpp')
-rw-r--r-- | libs/gui/Surface.cpp | 263 |
1 files changed, 196 insertions, 67 deletions
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 0e2baa2..b8acad2 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -27,6 +27,7 @@ #include <utils/NativeHandle.h> #include <ui/Fence.h> +#include <ui/Region.h> #include <gui/IProducerListener.h> #include <gui/ISurfaceComposer.h> @@ -64,6 +65,7 @@ Surface::Surface( mReqFormat = 0; mReqUsage = 0; mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO; + mDataSpace = HAL_DATASPACE_UNKNOWN; mCrop.clear(); mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; mTransform = 0; @@ -96,8 +98,8 @@ void Surface::setSidebandStream(const sp<NativeHandle>& stream) { void Surface::allocateBuffers() { uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth; uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight; - mGraphicBufferProducer->allocateBuffers(mSwapIntervalZero, mReqWidth, - mReqHeight, mReqFormat, mReqUsage); + mGraphicBufferProducer->allocateBuffers(mSwapIntervalZero, reqWidth, + reqHeight, mReqFormat, mReqUsage); } int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) { @@ -193,17 +195,17 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { ATRACE_CALL(); ALOGV("Surface::dequeueBuffer"); - int reqW; - int reqH; + uint32_t reqWidth; + uint32_t reqHeight; bool swapIntervalZero; - uint32_t reqFormat; + PixelFormat reqFormat; uint32_t reqUsage; { Mutex::Autolock lock(mMutex); - reqW = mReqWidth ? mReqWidth : mUserWidth; - reqH = mReqHeight ? mReqHeight : mUserHeight; + reqWidth = mReqWidth ? mReqWidth : mUserWidth; + reqHeight = mReqHeight ? mReqHeight : mUserHeight; swapIntervalZero = mSwapIntervalZero; reqFormat = mReqFormat; @@ -213,12 +215,12 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { int buf = -1; sp<Fence> fence; status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, swapIntervalZero, - reqW, reqH, reqFormat, reqUsage); + reqWidth, reqHeight, reqFormat, reqUsage); if (result < 0) { ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d, %d)" - "failed: %d", swapIntervalZero, reqW, reqH, reqFormat, reqUsage, - result); + "failed: %d", swapIntervalZero, reqWidth, reqHeight, reqFormat, + reqUsage, result); return result; } @@ -274,7 +276,6 @@ int Surface::cancelBuffer(android_native_buffer_t* buffer, int Surface::getSlotFromBufferLocked( android_native_buffer_t* buffer) const { - bool dumpedState = false; for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { if (mSlots[i].buffer != NULL && mSlots[i].buffer->handle == buffer->handle) { @@ -318,8 +319,27 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) { sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE); IGraphicBufferProducer::QueueBufferOutput output; IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp, - crop, mScalingMode, mTransform ^ mStickyTransform, mSwapIntervalZero, - fence, mStickyTransform); + mDataSpace, crop, mScalingMode, mTransform ^ mStickyTransform, + mSwapIntervalZero, fence, mStickyTransform); + + if (mConnectedToCpu || mDirtyRegion.bounds() == Rect::INVALID_RECT) { + input.setSurfaceDamage(Region::INVALID_REGION); + } else { + // The surface damage was specified using the OpenGL ES convention of + // the origin being in the bottom-left corner. Here we flip to the + // convention that the rest of the system uses (top-left corner) by + // subtracting all top/bottom coordinates from the buffer height. + Region flippedRegion; + for (auto rect : mDirtyRegion) { + auto top = buffer->height - rect.bottom; + auto bottom = buffer->height - rect.top; + Rect flippedRect{rect.left, top, rect.right, bottom}; + flippedRegion.orSelf(flippedRect); + } + + input.setSurfaceDamage(flippedRegion); + } + status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output); if (err != OK) { ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err); @@ -336,6 +356,11 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) { mConsumerRunningBehind = (numPendingBuffers >= 2); + if (!mConnectedToCpu) { + // Clear surface damage back to full-buffer + mDirtyRegion = Region::INVALID_REGION; + } + return err; } @@ -347,7 +372,7 @@ int Surface::query(int what, int* value) const { switch (what) { case NATIVE_WINDOW_FORMAT: if (mReqFormat) { - *value = mReqFormat; + *value = static_cast<int>(mReqFormat); return NO_ERROR; } break; @@ -365,13 +390,15 @@ int Surface::query(int what, int* value) const { *value = NATIVE_WINDOW_SURFACE; return NO_ERROR; case NATIVE_WINDOW_DEFAULT_WIDTH: - *value = mUserWidth ? mUserWidth : mDefaultWidth; + *value = static_cast<int>( + mUserWidth ? mUserWidth : mDefaultWidth); return NO_ERROR; case NATIVE_WINDOW_DEFAULT_HEIGHT: - *value = mUserHeight ? mUserHeight : mDefaultHeight; + *value = static_cast<int>( + mUserHeight ? mUserHeight : mDefaultHeight); return NO_ERROR; case NATIVE_WINDOW_TRANSFORM_HINT: - *value = mTransformHint; + *value = static_cast<int>(mTransformHint); return NO_ERROR; case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: { status_t err = NO_ERROR; @@ -448,6 +475,12 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_SET_SIDEBAND_STREAM: res = dispatchSetSidebandStream(args); break; + case NATIVE_WINDOW_SET_BUFFERS_DATASPACE: + res = dispatchSetBuffersDataSpace(args); + break; + case NATIVE_WINDOW_SET_SURFACE_DAMAGE: + res = dispatchSetSurfaceDamage(args); + break; default: res = NAME_NOT_FOUND; break; @@ -467,7 +500,7 @@ int Surface::dispatchDisconnect(va_list args) { int Surface::dispatchSetUsage(va_list args) { int usage = va_arg(args, int); - return setUsage(usage); + return setUsage(static_cast<uint32_t>(usage)); } int Surface::dispatchSetCrop(va_list args) { @@ -477,49 +510,49 @@ int Surface::dispatchSetCrop(va_list args) { int Surface::dispatchSetBufferCount(va_list args) { size_t bufferCount = va_arg(args, size_t); - return setBufferCount(bufferCount); + return setBufferCount(static_cast<int32_t>(bufferCount)); } int Surface::dispatchSetBuffersGeometry(va_list args) { - int w = va_arg(args, int); - int h = va_arg(args, int); - int f = va_arg(args, int); - int err = setBuffersDimensions(w, h); + uint32_t width = va_arg(args, uint32_t); + uint32_t height = va_arg(args, uint32_t); + PixelFormat format = va_arg(args, PixelFormat); + int err = setBuffersDimensions(width, height); if (err != 0) { return err; } - return setBuffersFormat(f); + return setBuffersFormat(format); } int Surface::dispatchSetBuffersDimensions(va_list args) { - int w = va_arg(args, int); - int h = va_arg(args, int); - return setBuffersDimensions(w, h); + uint32_t width = va_arg(args, uint32_t); + uint32_t height = va_arg(args, uint32_t); + return setBuffersDimensions(width, height); } int Surface::dispatchSetBuffersUserDimensions(va_list args) { - int w = va_arg(args, int); - int h = va_arg(args, int); - return setBuffersUserDimensions(w, h); + uint32_t width = va_arg(args, uint32_t); + uint32_t height = va_arg(args, uint32_t); + return setBuffersUserDimensions(width, height); } int Surface::dispatchSetBuffersFormat(va_list args) { - int f = va_arg(args, int); - return setBuffersFormat(f); + PixelFormat format = va_arg(args, PixelFormat); + return setBuffersFormat(format); } int Surface::dispatchSetScalingMode(va_list args) { - int m = va_arg(args, int); - return setScalingMode(m); + int mode = va_arg(args, int); + return setScalingMode(mode); } int Surface::dispatchSetBuffersTransform(va_list args) { - int transform = va_arg(args, int); + uint32_t transform = va_arg(args, uint32_t); return setBuffersTransform(transform); } int Surface::dispatchSetBuffersStickyTransform(va_list args) { - int transform = va_arg(args, int); + uint32_t transform = va_arg(args, uint32_t); return setBuffersStickyTransform(transform); } @@ -545,10 +578,27 @@ int Surface::dispatchSetSidebandStream(va_list args) { return OK; } +int Surface::dispatchSetBuffersDataSpace(va_list args) { + android_dataspace dataspace = + static_cast<android_dataspace>(va_arg(args, int)); + return setBuffersDataSpace(dataspace); +} + +int Surface::dispatchSetSurfaceDamage(va_list args) { + android_native_rect_t* rects = va_arg(args, android_native_rect_t*); + size_t numRects = va_arg(args, size_t); + setSurfaceDamage(rects, numRects); + return NO_ERROR; +} + int Surface::connect(int api) { + static sp<IProducerListener> listener = new DummyProducerListener(); + return connect(api, listener); +} + +int Surface::connect(int api, const sp<IProducerListener>& listener) { ATRACE_CALL(); ALOGV("Surface::connect"); - static sp<IProducerListener> listener = new DummyProducerListener(); Mutex::Autolock lock(mMutex); IGraphicBufferProducer::QueueBufferOutput output; int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output); @@ -567,7 +617,13 @@ int Surface::connect(int api) { } if (!err && api == NATIVE_WINDOW_API_CPU) { mConnectedToCpu = true; + // Clear the dirty region in case we're switching from a non-CPU API + mDirtyRegion.clear(); + } else if (!err) { + // Initialize the dirty region for tracking surface damage + mDirtyRegion = Region::INVALID_REGION; } + return err; } @@ -595,6 +651,55 @@ int Surface::disconnect(int api) { return err; } +int Surface::detachNextBuffer(ANativeWindowBuffer** outBuffer, + sp<Fence>* outFence) { + ATRACE_CALL(); + ALOGV("Surface::detachNextBuffer"); + + if (outBuffer == NULL || outFence == NULL) { + return BAD_VALUE; + } + + Mutex::Autolock lock(mMutex); + + sp<GraphicBuffer> buffer(NULL); + sp<Fence> fence(NULL); + status_t result = mGraphicBufferProducer->detachNextBuffer( + &buffer, &fence); + if (result != NO_ERROR) { + return result; + } + + *outBuffer = buffer.get(); + if (fence != NULL && fence->isValid()) { + *outFence = fence; + } else { + *outFence = Fence::NO_FENCE; + } + + return NO_ERROR; +} + +int Surface::attachBuffer(ANativeWindowBuffer* buffer) +{ + ATRACE_CALL(); + ALOGV("Surface::attachBuffer"); + + Mutex::Autolock lock(mMutex); + + sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer)); + int32_t attachedSlot = -1; + status_t result = mGraphicBufferProducer->attachBuffer( + &attachedSlot, graphicBuffer); + if (result != NO_ERROR) { + ALOGE("attachBuffer: IGraphicBufferProducer call failed (%d)", result); + return result; + } + mSlots[attachedSlot].buffer = graphicBuffer; + + return NO_ERROR; +} + int Surface::setUsage(uint32_t reqUsage) { ALOGV("Surface::setUsage"); @@ -639,47 +744,38 @@ int Surface::setBufferCount(int bufferCount) return err; } -int Surface::setBuffersDimensions(int w, int h) +int Surface::setBuffersDimensions(uint32_t width, uint32_t height) { ATRACE_CALL(); ALOGV("Surface::setBuffersDimensions"); - if (w<0 || h<0) - return BAD_VALUE; - - if ((w && !h) || (!w && h)) + if ((width && !height) || (!width && height)) return BAD_VALUE; Mutex::Autolock lock(mMutex); - mReqWidth = w; - mReqHeight = h; + mReqWidth = width; + mReqHeight = height; return NO_ERROR; } -int Surface::setBuffersUserDimensions(int w, int h) +int Surface::setBuffersUserDimensions(uint32_t width, uint32_t height) { ATRACE_CALL(); ALOGV("Surface::setBuffersUserDimensions"); - if (w<0 || h<0) - return BAD_VALUE; - - if ((w && !h) || (!w && h)) + if ((width && !height) || (!width && height)) return BAD_VALUE; Mutex::Autolock lock(mMutex); - mUserWidth = w; - mUserHeight = h; + mUserWidth = width; + mUserHeight = height; return NO_ERROR; } -int Surface::setBuffersFormat(int format) +int Surface::setBuffersFormat(PixelFormat format) { ALOGV("Surface::setBuffersFormat"); - if (format<0) - return BAD_VALUE; - Mutex::Autolock lock(mMutex); mReqFormat = format; return NO_ERROR; @@ -705,7 +801,7 @@ int Surface::setScalingMode(int mode) return NO_ERROR; } -int Surface::setBuffersTransform(int transform) +int Surface::setBuffersTransform(uint32_t transform) { ATRACE_CALL(); ALOGV("Surface::setBuffersTransform"); @@ -714,7 +810,7 @@ int Surface::setBuffersTransform(int transform) return NO_ERROR; } -int Surface::setBuffersStickyTransform(int transform) +int Surface::setBuffersStickyTransform(uint32_t transform) { ATRACE_CALL(); ALOGV("Surface::setBuffersStickyTransform"); @@ -731,12 +827,41 @@ int Surface::setBuffersTimestamp(int64_t timestamp) return NO_ERROR; } +int Surface::setBuffersDataSpace(android_dataspace dataSpace) +{ + ALOGV("Surface::setBuffersDataSpace"); + Mutex::Autolock lock(mMutex); + mDataSpace = dataSpace; + return NO_ERROR; +} + void Surface::freeAllBuffers() { for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { mSlots[i].buffer = 0; } } +void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) { + ATRACE_CALL(); + ALOGV("Surface::setSurfaceDamage"); + Mutex::Autolock lock(mMutex); + + if (mConnectedToCpu || numRects == 0) { + mDirtyRegion = Region::INVALID_REGION; + return; + } + + mDirtyRegion.clear(); + for (size_t r = 0; r < numRects; ++r) { + // We intentionally flip top and bottom here, since because they're + // specified with a bottom-left origin, top > bottom, which fails + // validation in the Region class. We will fix this up when we flip to a + // top-left origin in queueBuffer. + Rect rect(rects[r].left, rects[r].bottom, rects[r].right, rects[r].top); + mDirtyRegion.orSelf(rect); + } +} + // ---------------------------------------------------------------------- // the lock/unlock APIs must be used from the same thread @@ -748,30 +873,34 @@ static status_t copyBlt( // src and dst with, height and format must be identical. no verification // is done here. status_t err; - uint8_t const * src_bits = NULL; - err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits); + uint8_t* src_bits = NULL; + err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), + reinterpret_cast<void**>(&src_bits)); ALOGE_IF(err, "error locking src buffer %s", strerror(-err)); uint8_t* dst_bits = NULL; - err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits); + err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), + reinterpret_cast<void**>(&dst_bits)); ALOGE_IF(err, "error locking dst buffer %s", strerror(-err)); Region::const_iterator head(reg.begin()); Region::const_iterator tail(reg.end()); if (head != tail && src_bits && dst_bits) { const size_t bpp = bytesPerPixel(src->format); - const size_t dbpr = dst->stride * bpp; - const size_t sbpr = src->stride * bpp; + const size_t dbpr = static_cast<uint32_t>(dst->stride) * bpp; + const size_t sbpr = static_cast<uint32_t>(src->stride) * bpp; while (head != tail) { const Rect& r(*head++); - ssize_t h = r.height(); + int32_t h = r.height(); if (h <= 0) continue; - size_t size = r.width() * bpp; - uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; - uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; + size_t size = static_cast<uint32_t>(r.width()) * bpp; + uint8_t const * s = src_bits + + static_cast<uint32_t>(r.left + src->stride * r.top) * bpp; + uint8_t * d = dst_bits + + static_cast<uint32_t>(r.left + dst->stride * r.top) * bpp; if (dbpr==sbpr && size==sbpr) { - size *= h; + size *= static_cast<size_t>(h); h = 1; } do { |