Loading include/gui/BufferQueue.h +15 −8 Original line number Diff line number Diff line Loading @@ -137,7 +137,7 @@ public: virtual status_t queueBuffer(int buf, const QueueBufferInput& input, QueueBufferOutput* output); virtual void cancelBuffer(int buf); virtual void cancelBuffer(int buf, sp<Fence> fence); // setSynchronousMode set whether dequeueBuffer is synchronous or // asynchronous. In synchronous mode, dequeueBuffer blocks until Loading Loading @@ -307,7 +307,7 @@ private: mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mTimestamp(0), mFrameNumber(0), mFence(EGL_NO_SYNC_KHR), mEglFence(EGL_NO_SYNC_KHR), mAcquireCalled(false), mNeedsCleanupOnRelease(false) { mCrop.makeInvalid(); Loading Loading @@ -380,15 +380,22 @@ private: // mFrameNumber is the number of the queued frame for this slot. uint64_t mFrameNumber; // mFence is the EGL sync object that must signal before the buffer // mEglFence is the EGL sync object that must signal before the buffer // associated with this buffer slot may be dequeued. It is initialized // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based // on a compile-time option) set to a new sync object in updateTexImage. EGLSyncKHR mFence; // mReleaseFence is a fence which must signal before the contents of // the buffer associated with this buffer slot may be overwritten. sp<Fence> mReleaseFence; EGLSyncKHR mEglFence; // mFence is a fence which will signal when work initiated by the // previous owner of the buffer is finished. When the buffer is FREE, // the fence indicates when the consumer has finished reading // from the buffer, or when the producer has finished writing if it // called cancelBuffer after queueing some writes. When the buffer is // QUEUED, it indicates when the producer has finished filling the // buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been // passed to the consumer or producer along with ownership of the // buffer, and mFence is empty. sp<Fence> mFence; // Indicates whether this buffer has been seen by a consumer yet bool mAcquireCalled; Loading include/gui/ISurfaceTexture.h +19 −6 Original line number Diff line number Diff line Loading @@ -89,24 +89,37 @@ protected: // and height of the window and current transform applied to buffers, // respectively. // QueueBufferInput must be a POD structure struct QueueBufferInput { struct QueueBufferInput : public Flattenable { inline QueueBufferInput(const Parcel& parcel); inline QueueBufferInput(int64_t timestamp, const Rect& crop, int scalingMode, uint32_t transform) const Rect& crop, int scalingMode, uint32_t transform, sp<Fence> fence) : timestamp(timestamp), crop(crop), scalingMode(scalingMode), transform(transform) { } transform(transform), fence(fence) { } inline void deflate(int64_t* outTimestamp, Rect* outCrop, int* outScalingMode, uint32_t* outTransform) const { int* outScalingMode, uint32_t* outTransform, sp<Fence>* outFence) const { *outTimestamp = timestamp; *outCrop = crop; *outScalingMode = scalingMode; *outTransform = transform; *outFence = fence; } // Flattenable interface virtual size_t getFlattenedSize() const; virtual size_t getFdCount() const; virtual status_t flatten(void* buffer, size_t size, int fds[], size_t count) const; virtual status_t unflatten(void const* buffer, size_t size, int fds[], size_t count); private: int64_t timestamp; Rect crop; int scalingMode; uint32_t transform; sp<Fence> fence; }; // QueueBufferOutput must be a POD structure Loading Loading @@ -141,7 +154,7 @@ protected: // cancelBuffer indicates that the client does not wish to fill in the // buffer associated with slot and transfers ownership of the slot back to // the server. virtual void cancelBuffer(int slot) = 0; virtual void cancelBuffer(int slot, sp<Fence> fence) = 0; // query retrieves some information for this surface // 'what' tokens allowed are that of android_natives.h Loading include/ui/Fence.h +5 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,11 @@ public: // closed. Fence(int fenceFd); // Check whether the Fence has an open fence file descriptor. Most Fence // methods treat an invalid file descriptor just like a valid fence that // is already signalled, so using this is usually not necessary. bool isValid() const { return mFenceFd != -1; } // wait waits for up to timeout milliseconds for the fence to signal. If // the fence signals then NO_ERROR is returned. If the timeout expires // before the fence signals then -ETIME is returned. A timeout of Loading libs/gui/BufferQueue.cpp +21 −18 Original line number Diff line number Diff line Loading @@ -306,7 +306,7 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence, status_t returnFlags(OK); EGLDisplay dpy = EGL_NO_DISPLAY; EGLSyncKHR fence = EGL_NO_SYNC_KHR; EGLSyncKHR eglFence = EGL_NO_SYNC_KHR; { // Scope for the lock Mutex::Autolock lock(mMutex); Loading Loading @@ -480,22 +480,22 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence, mSlots[buf].mAcquireCalled = false; mSlots[buf].mGraphicBuffer = graphicBuffer; mSlots[buf].mRequestBufferCalled = false; mSlots[buf].mFence = EGL_NO_SYNC_KHR; mSlots[buf].mReleaseFence.clear(); mSlots[buf].mEglFence = EGL_NO_SYNC_KHR; mSlots[buf].mFence.clear(); mSlots[buf].mEglDisplay = EGL_NO_DISPLAY; returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; } dpy = mSlots[buf].mEglDisplay; fence = mSlots[buf].mFence; outFence = mSlots[buf].mReleaseFence; mSlots[buf].mFence = EGL_NO_SYNC_KHR; mSlots[buf].mReleaseFence.clear(); eglFence = mSlots[buf].mEglFence; outFence = mSlots[buf].mFence; mSlots[buf].mEglFence = EGL_NO_SYNC_KHR; mSlots[buf].mFence.clear(); } // end lock scope if (fence != EGL_NO_SYNC_KHR) { EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000); if (eglFence != EGL_NO_SYNC_KHR) { EGLint result = eglClientWaitSyncKHR(dpy, eglFence, 0, 1000000000); // If something goes wrong, log the error, but return the buffer without // synchronizing access to it. It's too late at this point to abort the // dequeue operation. Loading @@ -504,7 +504,7 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence, } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { ST_LOGE("dequeueBuffer: timeout waiting for fence"); } eglDestroySyncKHR(dpy, fence); eglDestroySyncKHR(dpy, eglFence); } ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf, Loading Loading @@ -554,8 +554,9 @@ status_t BufferQueue::queueBuffer(int buf, uint32_t transform; int scalingMode; int64_t timestamp; sp<Fence> fence; input.deflate(×tamp, &crop, &scalingMode, &transform); input.deflate(×tamp, &crop, &scalingMode, &transform, &fence); ST_LOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x " "scale=%s", Loading Loading @@ -622,6 +623,7 @@ status_t BufferQueue::queueBuffer(int buf, mSlots[buf].mTimestamp = timestamp; mSlots[buf].mCrop = crop; mSlots[buf].mTransform = transform; mSlots[buf].mFence = fence; switch (scalingMode) { case NATIVE_WINDOW_SCALING_MODE_FREEZE: Loading Loading @@ -655,7 +657,7 @@ status_t BufferQueue::queueBuffer(int buf, return OK; } void BufferQueue::cancelBuffer(int buf) { void BufferQueue::cancelBuffer(int buf, sp<Fence> fence) { ATRACE_CALL(); ST_LOGV("cancelBuffer: slot=%d", buf); Mutex::Autolock lock(mMutex); Loading @@ -676,6 +678,7 @@ void BufferQueue::cancelBuffer(int buf) { } mSlots[buf].mBufferState = BufferSlot::FREE; mSlots[buf].mFrameNumber = 0; mSlots[buf].mFence = fence; mDequeueCondition.broadcast(); } Loading Loading @@ -842,11 +845,11 @@ void BufferQueue::freeBufferLocked(int i) { mSlots[i].mAcquireCalled = false; // destroy fence as BufferQueue now takes ownership if (mSlots[i].mFence != EGL_NO_SYNC_KHR) { eglDestroySyncKHR(mSlots[i].mEglDisplay, mSlots[i].mFence); mSlots[i].mFence = EGL_NO_SYNC_KHR; if (mSlots[i].mEglFence != EGL_NO_SYNC_KHR) { eglDestroySyncKHR(mSlots[i].mEglDisplay, mSlots[i].mEglFence); mSlots[i].mEglFence = EGL_NO_SYNC_KHR; } mSlots[i].mReleaseFence.clear(); mSlots[i].mFence.clear(); } void BufferQueue::freeAllBuffersLocked() { Loading Loading @@ -897,7 +900,7 @@ status_t BufferQueue::acquireBuffer(BufferItem *buffer) { } status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display, EGLSyncKHR fence, const sp<Fence>& releaseFence) { EGLSyncKHR eglFence, const sp<Fence>& fence) { ATRACE_CALL(); ATRACE_BUFFER_INDEX(buf); Loading @@ -908,8 +911,8 @@ status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display, } mSlots[buf].mEglDisplay = display; mSlots[buf].mEglFence = eglFence; mSlots[buf].mFence = fence; mSlots[buf].mReleaseFence = releaseFence; // The buffer can now only be released if its in the acquired state if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) { Loading libs/gui/ISurfaceTexture.cpp +77 −9 Original line number Diff line number Diff line Loading @@ -109,7 +109,7 @@ public: Parcel data, reply; data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); data.writeInt32(buf); memcpy(data.writeInplace(sizeof(input)), &input, sizeof(input)); data.write(input); status_t result = remote()->transact(QUEUE_BUFFER, data, &reply); if (result != NO_ERROR) { return result; Loading @@ -119,10 +119,15 @@ public: return result; } virtual void cancelBuffer(int buf) { virtual void cancelBuffer(int buf, sp<Fence> fence) { Parcel data, reply; bool hasFence = fence.get() && fence->isValid(); data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); data.writeInt32(buf); data.writeInt32(hasFence); if (hasFence) { data.write(*fence.get()); } remote()->transact(CANCEL_BUFFER, data, &reply); } Loading Loading @@ -213,9 +218,10 @@ status_t BnSurfaceTexture::onTransact( int buf; sp<Fence> fence; int result = dequeueBuffer(&buf, fence, w, h, format, usage); bool hasFence = fence.get() && fence->isValid(); reply->writeInt32(buf); reply->writeInt32(fence.get() != NULL); if (fence.get() != NULL) { reply->writeInt32(hasFence); if (hasFence) { reply->write(*fence.get()); } reply->writeInt32(result); Loading @@ -224,20 +230,24 @@ status_t BnSurfaceTexture::onTransact( case QUEUE_BUFFER: { CHECK_INTERFACE(ISurfaceTexture, data, reply); int buf = data.readInt32(); QueueBufferInput const* const input = reinterpret_cast<QueueBufferInput const *>( data.readInplace(sizeof(QueueBufferInput))); QueueBufferInput input(data); QueueBufferOutput* const output = reinterpret_cast<QueueBufferOutput *>( reply->writeInplace(sizeof(QueueBufferOutput))); status_t result = queueBuffer(buf, *input, output); status_t result = queueBuffer(buf, input, output); reply->writeInt32(result); return NO_ERROR; } break; case CANCEL_BUFFER: { CHECK_INTERFACE(ISurfaceTexture, data, reply); int buf = data.readInt32(); cancelBuffer(buf); sp<Fence> fence; bool hasFence = data.readInt32(); if (hasFence) { fence = new Fence(); data.read(*fence.get()); } cancelBuffer(buf, fence); return NO_ERROR; } break; case QUERY: { Loading Loading @@ -279,4 +289,62 @@ status_t BnSurfaceTexture::onTransact( // ---------------------------------------------------------------------------- static bool isValid(const sp<Fence>& fence) { return fence.get() && fence->isValid(); } ISurfaceTexture::QueueBufferInput::QueueBufferInput(const Parcel& parcel) { parcel.read(*this); } size_t ISurfaceTexture::QueueBufferInput::getFlattenedSize() const { return sizeof(timestamp) + sizeof(crop) + sizeof(scalingMode) + sizeof(transform) + sizeof(bool) + (isValid(fence) ? fence->getFlattenedSize() : 0); } size_t ISurfaceTexture::QueueBufferInput::getFdCount() const { return isValid(fence) ? fence->getFdCount() : 0; } status_t ISurfaceTexture::QueueBufferInput::flatten(void* buffer, size_t size, int fds[], size_t count) const { status_t err = NO_ERROR; bool haveFence = isValid(fence); char* p = (char*)buffer; memcpy(p, ×tamp, sizeof(timestamp)); p += sizeof(timestamp); memcpy(p, &crop, sizeof(crop)); p += sizeof(crop); memcpy(p, &scalingMode, sizeof(scalingMode)); p += sizeof(scalingMode); memcpy(p, &transform, sizeof(transform)); p += sizeof(transform); memcpy(p, &haveFence, sizeof(haveFence)); p += sizeof(haveFence); if (haveFence) { err = fence->flatten(p, size - (p - (char*)buffer), fds, count); } return err; } status_t ISurfaceTexture::QueueBufferInput::unflatten(void const* buffer, size_t size, int fds[], size_t count) { status_t err = NO_ERROR; bool haveFence; const char* p = (const char*)buffer; memcpy(×tamp, p, sizeof(timestamp)); p += sizeof(timestamp); memcpy(&crop, p, sizeof(crop)); p += sizeof(crop); memcpy(&scalingMode, p, sizeof(scalingMode)); p += sizeof(scalingMode); memcpy(&transform, p, sizeof(transform)); p += sizeof(transform); memcpy(&haveFence, p, sizeof(haveFence)); p += sizeof(haveFence); if (haveFence) { fence = new Fence(); err = fence->unflatten(p, size - (p - (const char*)buffer), fds, count); } return err; } }; // namespace android Loading
include/gui/BufferQueue.h +15 −8 Original line number Diff line number Diff line Loading @@ -137,7 +137,7 @@ public: virtual status_t queueBuffer(int buf, const QueueBufferInput& input, QueueBufferOutput* output); virtual void cancelBuffer(int buf); virtual void cancelBuffer(int buf, sp<Fence> fence); // setSynchronousMode set whether dequeueBuffer is synchronous or // asynchronous. In synchronous mode, dequeueBuffer blocks until Loading Loading @@ -307,7 +307,7 @@ private: mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mTimestamp(0), mFrameNumber(0), mFence(EGL_NO_SYNC_KHR), mEglFence(EGL_NO_SYNC_KHR), mAcquireCalled(false), mNeedsCleanupOnRelease(false) { mCrop.makeInvalid(); Loading Loading @@ -380,15 +380,22 @@ private: // mFrameNumber is the number of the queued frame for this slot. uint64_t mFrameNumber; // mFence is the EGL sync object that must signal before the buffer // mEglFence is the EGL sync object that must signal before the buffer // associated with this buffer slot may be dequeued. It is initialized // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based // on a compile-time option) set to a new sync object in updateTexImage. EGLSyncKHR mFence; // mReleaseFence is a fence which must signal before the contents of // the buffer associated with this buffer slot may be overwritten. sp<Fence> mReleaseFence; EGLSyncKHR mEglFence; // mFence is a fence which will signal when work initiated by the // previous owner of the buffer is finished. When the buffer is FREE, // the fence indicates when the consumer has finished reading // from the buffer, or when the producer has finished writing if it // called cancelBuffer after queueing some writes. When the buffer is // QUEUED, it indicates when the producer has finished filling the // buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been // passed to the consumer or producer along with ownership of the // buffer, and mFence is empty. sp<Fence> mFence; // Indicates whether this buffer has been seen by a consumer yet bool mAcquireCalled; Loading
include/gui/ISurfaceTexture.h +19 −6 Original line number Diff line number Diff line Loading @@ -89,24 +89,37 @@ protected: // and height of the window and current transform applied to buffers, // respectively. // QueueBufferInput must be a POD structure struct QueueBufferInput { struct QueueBufferInput : public Flattenable { inline QueueBufferInput(const Parcel& parcel); inline QueueBufferInput(int64_t timestamp, const Rect& crop, int scalingMode, uint32_t transform) const Rect& crop, int scalingMode, uint32_t transform, sp<Fence> fence) : timestamp(timestamp), crop(crop), scalingMode(scalingMode), transform(transform) { } transform(transform), fence(fence) { } inline void deflate(int64_t* outTimestamp, Rect* outCrop, int* outScalingMode, uint32_t* outTransform) const { int* outScalingMode, uint32_t* outTransform, sp<Fence>* outFence) const { *outTimestamp = timestamp; *outCrop = crop; *outScalingMode = scalingMode; *outTransform = transform; *outFence = fence; } // Flattenable interface virtual size_t getFlattenedSize() const; virtual size_t getFdCount() const; virtual status_t flatten(void* buffer, size_t size, int fds[], size_t count) const; virtual status_t unflatten(void const* buffer, size_t size, int fds[], size_t count); private: int64_t timestamp; Rect crop; int scalingMode; uint32_t transform; sp<Fence> fence; }; // QueueBufferOutput must be a POD structure Loading Loading @@ -141,7 +154,7 @@ protected: // cancelBuffer indicates that the client does not wish to fill in the // buffer associated with slot and transfers ownership of the slot back to // the server. virtual void cancelBuffer(int slot) = 0; virtual void cancelBuffer(int slot, sp<Fence> fence) = 0; // query retrieves some information for this surface // 'what' tokens allowed are that of android_natives.h Loading
include/ui/Fence.h +5 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,11 @@ public: // closed. Fence(int fenceFd); // Check whether the Fence has an open fence file descriptor. Most Fence // methods treat an invalid file descriptor just like a valid fence that // is already signalled, so using this is usually not necessary. bool isValid() const { return mFenceFd != -1; } // wait waits for up to timeout milliseconds for the fence to signal. If // the fence signals then NO_ERROR is returned. If the timeout expires // before the fence signals then -ETIME is returned. A timeout of Loading
libs/gui/BufferQueue.cpp +21 −18 Original line number Diff line number Diff line Loading @@ -306,7 +306,7 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence, status_t returnFlags(OK); EGLDisplay dpy = EGL_NO_DISPLAY; EGLSyncKHR fence = EGL_NO_SYNC_KHR; EGLSyncKHR eglFence = EGL_NO_SYNC_KHR; { // Scope for the lock Mutex::Autolock lock(mMutex); Loading Loading @@ -480,22 +480,22 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence, mSlots[buf].mAcquireCalled = false; mSlots[buf].mGraphicBuffer = graphicBuffer; mSlots[buf].mRequestBufferCalled = false; mSlots[buf].mFence = EGL_NO_SYNC_KHR; mSlots[buf].mReleaseFence.clear(); mSlots[buf].mEglFence = EGL_NO_SYNC_KHR; mSlots[buf].mFence.clear(); mSlots[buf].mEglDisplay = EGL_NO_DISPLAY; returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; } dpy = mSlots[buf].mEglDisplay; fence = mSlots[buf].mFence; outFence = mSlots[buf].mReleaseFence; mSlots[buf].mFence = EGL_NO_SYNC_KHR; mSlots[buf].mReleaseFence.clear(); eglFence = mSlots[buf].mEglFence; outFence = mSlots[buf].mFence; mSlots[buf].mEglFence = EGL_NO_SYNC_KHR; mSlots[buf].mFence.clear(); } // end lock scope if (fence != EGL_NO_SYNC_KHR) { EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000); if (eglFence != EGL_NO_SYNC_KHR) { EGLint result = eglClientWaitSyncKHR(dpy, eglFence, 0, 1000000000); // If something goes wrong, log the error, but return the buffer without // synchronizing access to it. It's too late at this point to abort the // dequeue operation. Loading @@ -504,7 +504,7 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence, } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { ST_LOGE("dequeueBuffer: timeout waiting for fence"); } eglDestroySyncKHR(dpy, fence); eglDestroySyncKHR(dpy, eglFence); } ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf, Loading Loading @@ -554,8 +554,9 @@ status_t BufferQueue::queueBuffer(int buf, uint32_t transform; int scalingMode; int64_t timestamp; sp<Fence> fence; input.deflate(×tamp, &crop, &scalingMode, &transform); input.deflate(×tamp, &crop, &scalingMode, &transform, &fence); ST_LOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x " "scale=%s", Loading Loading @@ -622,6 +623,7 @@ status_t BufferQueue::queueBuffer(int buf, mSlots[buf].mTimestamp = timestamp; mSlots[buf].mCrop = crop; mSlots[buf].mTransform = transform; mSlots[buf].mFence = fence; switch (scalingMode) { case NATIVE_WINDOW_SCALING_MODE_FREEZE: Loading Loading @@ -655,7 +657,7 @@ status_t BufferQueue::queueBuffer(int buf, return OK; } void BufferQueue::cancelBuffer(int buf) { void BufferQueue::cancelBuffer(int buf, sp<Fence> fence) { ATRACE_CALL(); ST_LOGV("cancelBuffer: slot=%d", buf); Mutex::Autolock lock(mMutex); Loading @@ -676,6 +678,7 @@ void BufferQueue::cancelBuffer(int buf) { } mSlots[buf].mBufferState = BufferSlot::FREE; mSlots[buf].mFrameNumber = 0; mSlots[buf].mFence = fence; mDequeueCondition.broadcast(); } Loading Loading @@ -842,11 +845,11 @@ void BufferQueue::freeBufferLocked(int i) { mSlots[i].mAcquireCalled = false; // destroy fence as BufferQueue now takes ownership if (mSlots[i].mFence != EGL_NO_SYNC_KHR) { eglDestroySyncKHR(mSlots[i].mEglDisplay, mSlots[i].mFence); mSlots[i].mFence = EGL_NO_SYNC_KHR; if (mSlots[i].mEglFence != EGL_NO_SYNC_KHR) { eglDestroySyncKHR(mSlots[i].mEglDisplay, mSlots[i].mEglFence); mSlots[i].mEglFence = EGL_NO_SYNC_KHR; } mSlots[i].mReleaseFence.clear(); mSlots[i].mFence.clear(); } void BufferQueue::freeAllBuffersLocked() { Loading Loading @@ -897,7 +900,7 @@ status_t BufferQueue::acquireBuffer(BufferItem *buffer) { } status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display, EGLSyncKHR fence, const sp<Fence>& releaseFence) { EGLSyncKHR eglFence, const sp<Fence>& fence) { ATRACE_CALL(); ATRACE_BUFFER_INDEX(buf); Loading @@ -908,8 +911,8 @@ status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display, } mSlots[buf].mEglDisplay = display; mSlots[buf].mEglFence = eglFence; mSlots[buf].mFence = fence; mSlots[buf].mReleaseFence = releaseFence; // The buffer can now only be released if its in the acquired state if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) { Loading
libs/gui/ISurfaceTexture.cpp +77 −9 Original line number Diff line number Diff line Loading @@ -109,7 +109,7 @@ public: Parcel data, reply; data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); data.writeInt32(buf); memcpy(data.writeInplace(sizeof(input)), &input, sizeof(input)); data.write(input); status_t result = remote()->transact(QUEUE_BUFFER, data, &reply); if (result != NO_ERROR) { return result; Loading @@ -119,10 +119,15 @@ public: return result; } virtual void cancelBuffer(int buf) { virtual void cancelBuffer(int buf, sp<Fence> fence) { Parcel data, reply; bool hasFence = fence.get() && fence->isValid(); data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); data.writeInt32(buf); data.writeInt32(hasFence); if (hasFence) { data.write(*fence.get()); } remote()->transact(CANCEL_BUFFER, data, &reply); } Loading Loading @@ -213,9 +218,10 @@ status_t BnSurfaceTexture::onTransact( int buf; sp<Fence> fence; int result = dequeueBuffer(&buf, fence, w, h, format, usage); bool hasFence = fence.get() && fence->isValid(); reply->writeInt32(buf); reply->writeInt32(fence.get() != NULL); if (fence.get() != NULL) { reply->writeInt32(hasFence); if (hasFence) { reply->write(*fence.get()); } reply->writeInt32(result); Loading @@ -224,20 +230,24 @@ status_t BnSurfaceTexture::onTransact( case QUEUE_BUFFER: { CHECK_INTERFACE(ISurfaceTexture, data, reply); int buf = data.readInt32(); QueueBufferInput const* const input = reinterpret_cast<QueueBufferInput const *>( data.readInplace(sizeof(QueueBufferInput))); QueueBufferInput input(data); QueueBufferOutput* const output = reinterpret_cast<QueueBufferOutput *>( reply->writeInplace(sizeof(QueueBufferOutput))); status_t result = queueBuffer(buf, *input, output); status_t result = queueBuffer(buf, input, output); reply->writeInt32(result); return NO_ERROR; } break; case CANCEL_BUFFER: { CHECK_INTERFACE(ISurfaceTexture, data, reply); int buf = data.readInt32(); cancelBuffer(buf); sp<Fence> fence; bool hasFence = data.readInt32(); if (hasFence) { fence = new Fence(); data.read(*fence.get()); } cancelBuffer(buf, fence); return NO_ERROR; } break; case QUERY: { Loading Loading @@ -279,4 +289,62 @@ status_t BnSurfaceTexture::onTransact( // ---------------------------------------------------------------------------- static bool isValid(const sp<Fence>& fence) { return fence.get() && fence->isValid(); } ISurfaceTexture::QueueBufferInput::QueueBufferInput(const Parcel& parcel) { parcel.read(*this); } size_t ISurfaceTexture::QueueBufferInput::getFlattenedSize() const { return sizeof(timestamp) + sizeof(crop) + sizeof(scalingMode) + sizeof(transform) + sizeof(bool) + (isValid(fence) ? fence->getFlattenedSize() : 0); } size_t ISurfaceTexture::QueueBufferInput::getFdCount() const { return isValid(fence) ? fence->getFdCount() : 0; } status_t ISurfaceTexture::QueueBufferInput::flatten(void* buffer, size_t size, int fds[], size_t count) const { status_t err = NO_ERROR; bool haveFence = isValid(fence); char* p = (char*)buffer; memcpy(p, ×tamp, sizeof(timestamp)); p += sizeof(timestamp); memcpy(p, &crop, sizeof(crop)); p += sizeof(crop); memcpy(p, &scalingMode, sizeof(scalingMode)); p += sizeof(scalingMode); memcpy(p, &transform, sizeof(transform)); p += sizeof(transform); memcpy(p, &haveFence, sizeof(haveFence)); p += sizeof(haveFence); if (haveFence) { err = fence->flatten(p, size - (p - (char*)buffer), fds, count); } return err; } status_t ISurfaceTexture::QueueBufferInput::unflatten(void const* buffer, size_t size, int fds[], size_t count) { status_t err = NO_ERROR; bool haveFence; const char* p = (const char*)buffer; memcpy(×tamp, p, sizeof(timestamp)); p += sizeof(timestamp); memcpy(&crop, p, sizeof(crop)); p += sizeof(crop); memcpy(&scalingMode, p, sizeof(scalingMode)); p += sizeof(scalingMode); memcpy(&transform, p, sizeof(transform)); p += sizeof(transform); memcpy(&haveFence, p, sizeof(haveFence)); p += sizeof(haveFence); if (haveFence) { fence = new Fence(); err = fence->unflatten(p, size - (p - (const char*)buffer), fds, count); } return err; } }; // namespace android