Loading include/gui/SurfaceTextureClient.h +46 −32 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <gui/SurfaceTexture.h> #include <ui/egl/android_natives.h> #include <ui/Region.h> #include <utils/RefBase.h> #include <utils/threads.h> Loading @@ -37,29 +38,24 @@ public: sp<ISurfaceTexture> getISurfaceTexture() const; private: friend class Surface; protected: SurfaceTextureClient(); void setISurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture); private: // can't be copied SurfaceTextureClient& operator = (const SurfaceTextureClient& rhs); SurfaceTextureClient(const SurfaceTextureClient& rhs); void init(); // ANativeWindow hooks static int cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer); static int lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int perform(ANativeWindow* window, int operation, ...); static int query(const ANativeWindow* window, int what, int* value); static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int setSwapInterval(ANativeWindow* window, int interval); int cancelBuffer(ANativeWindowBuffer* buffer); int dequeueBuffer(ANativeWindowBuffer** buffer); int lockBuffer(ANativeWindowBuffer* buffer); int perform(int operation, va_list args); int query(int what, int* value) const; int queueBuffer(ANativeWindowBuffer* buffer); int setSwapInterval(int interval); static int hook_cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer); static int hook_lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int hook_perform(ANativeWindow* window, int operation, ...); static int hook_query(const ANativeWindow* window, int what, int* value); static int hook_queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int hook_setSwapInterval(ANativeWindow* window, int interval); int dispatchConnect(va_list args); int dispatchDisconnect(va_list args); Loading @@ -71,26 +67,38 @@ private: int dispatchSetBuffersTimestamp(va_list args); int dispatchSetCrop(va_list args); int dispatchSetUsage(va_list args); int connect(int api); int disconnect(int api); int setBufferCount(int bufferCount); int setBuffersDimensions(int w, int h); int setBuffersFormat(int format); int setBuffersTransform(int transform); int setBuffersTimestamp(int64_t timestamp); int setCrop(Rect const* rect); int setUsage(uint32_t reqUsage); void freeAllBuffers(); int getSlotFromBufferLocked(android_native_buffer_t* buffer) const; int getConnectedApi() const; int dispatchLock(va_list args); int dispatchUnlockAndPost(va_list args); protected: virtual int cancelBuffer(ANativeWindowBuffer* buffer); virtual int dequeueBuffer(ANativeWindowBuffer** buffer); virtual int lockBuffer(ANativeWindowBuffer* buffer); virtual int perform(int operation, va_list args); virtual int query(int what, int* value) const; virtual int queueBuffer(ANativeWindowBuffer* buffer); virtual int setSwapInterval(int interval); virtual int connect(int api); virtual int disconnect(int api); virtual int setBufferCount(int bufferCount); virtual int setBuffersDimensions(int w, int h); virtual int setBuffersFormat(int format); virtual int setBuffersTransform(int transform); virtual int setBuffersTimestamp(int64_t timestamp); virtual int setCrop(Rect const* rect); virtual int setUsage(uint32_t reqUsage); virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds); virtual int unlockAndPost(); enum { MIN_UNDEQUEUED_BUFFERS = SurfaceTexture::MIN_UNDEQUEUED_BUFFERS }; enum { NUM_BUFFER_SLOTS = SurfaceTexture::NUM_BUFFER_SLOTS }; enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 }; private: void freeAllBuffers(); int getSlotFromBufferLocked(android_native_buffer_t* buffer) const; // mSurfaceTexture is the interface to the surface texture server. All // operations on the surface texture client ultimately translate into // interactions with the server using this interface. Loading Loading @@ -145,6 +153,12 @@ private: // variables of SurfaceTexture objects. It must be locked whenever the // member variables are accessed. mutable Mutex mMutex; // must be used from the lock/unlock thread sp<GraphicBuffer> mLockedBuffer; sp<GraphicBuffer> mPostedBuffer; mutable Region mOldDirtyRegion; bool mConnectedToCpu; }; }; // namespace android Loading include/surfaceflinger/Surface.h +6 −63 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ #include <ui/Region.h> #include <ui/egl/android_natives.h> #include <gui/SurfaceTextureClient.h> #include <surfaceflinger/ISurface.h> #include <surfaceflinger/ISurfaceComposerClient.h> Loading @@ -37,14 +39,9 @@ namespace android { // --------------------------------------------------------------------------- class GraphicBuffer; class GraphicBufferMapper; class IOMX; class ISurfaceTexture; class Rect; class Surface; class SurfaceComposerClient; class SurfaceTextureClient; // --------------------------------------------------------------------------- Loading Loading @@ -129,8 +126,7 @@ private: // --------------------------------------------------------------------------- class Surface : public EGLNativeBase<ANativeWindow, Surface, RefBase> class Surface : public SurfaceTextureClient { public: struct SurfaceInfo { Loading Loading @@ -158,32 +154,14 @@ public: sp<ISurfaceTexture> getSurfaceTexture(); // the lock/unlock APIs must be used from the same thread status_t lock(SurfaceInfo* info, bool blocking = true); status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true); status_t lock(SurfaceInfo* info, Region* dirty = NULL); status_t unlockAndPost(); sp<IBinder> asBinder() const; private: /* * Android frameworks friends * (eventually this should go away and be replaced by proper APIs) */ // camera and camcorder need access to the ISurface binder interface for preview friend class CameraService; friend class MediaRecorder; // MediaPlayer needs access to ISurface for display friend class MediaPlayer; friend class IOMX; friend class SoftwareRenderer; // this is just to be able to write some unit tests friend class Test; // videoEditor preview classes friend class VideoEditorPreviewController; friend class PreviewRenderer; private: friend class SurfaceComposerClient; friend class SurfaceControl; // can't be copied Loading @@ -194,62 +172,27 @@ private: Surface(const Parcel& data, const sp<IBinder>& ref); ~Surface(); /* * ANativeWindow hooks */ static int setSwapInterval(ANativeWindow* window, int interval); static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer); static int cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int query(const ANativeWindow* window, int what, int* value); static int perform(ANativeWindow* window, int operation, ...); int setSwapInterval(int interval); int dequeueBuffer(ANativeWindowBuffer** buffer); int lockBuffer(ANativeWindowBuffer* buffer); int queueBuffer(ANativeWindowBuffer* buffer); int cancelBuffer(ANativeWindowBuffer* buffer); int query(int what, int* value) const; int perform(int operation, va_list args); /* * private stuff... */ void init(); status_t validate(bool inCancelBuffer = false) const; int getConnectedApi() const; static void cleanCachedSurfacesLocked(); virtual int query(int what, int* value) const; // constants status_t mInitCheck; sp<ISurface> mSurface; sp<SurfaceTextureClient> mSurfaceTextureClient; uint32_t mIdentity; PixelFormat mFormat; uint32_t mFlags; // protected by mSurfaceLock. These are also used from lock/unlock // but in that case, they must be called form the same thread. mutable Region mDirtyRegion; // must be used from the lock/unlock thread sp<GraphicBuffer> mLockedBuffer; sp<GraphicBuffer> mPostedBuffer; mutable Region mOldDirtyRegion; bool mReserved; // query() must be called from dequeueBuffer() thread uint32_t mWidth; uint32_t mHeight; // Inherently thread-safe mutable Mutex mSurfaceLock; mutable Mutex mApiLock; // A cache of Surface objects that have been deserialized into this process. static Mutex sCachedSurfacesLock; static DefaultKeyedVector<wp<IBinder>, wp<Surface> > sCachedSurfaces; Loading libs/gui/Surface.cpp +24 −264 Original line number Diff line number Diff line Loading @@ -46,59 +46,6 @@ namespace android { // ---------------------------------------------------------------------- static status_t copyBlt( const sp<GraphicBuffer>& dst, const sp<GraphicBuffer>& src, const Region& reg) { // 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); LOGE_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); LOGE_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; while (head != tail) { const Rect& r(*head++); ssize_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; if (dbpr==sbpr && size==sbpr) { size *= h; h = 1; } do { memcpy(d, s, size); d += dbpr; s += sbpr; } while (--h > 0); } } if (src_bits) src->unlock(); if (dst_bits) dst->unlock(); return err; } // ============================================================================ // SurfaceControl // ============================================================================ Loading Loading @@ -277,7 +224,8 @@ sp<Surface> SurfaceControl::getSurface() const // --------------------------------------------------------------------------- Surface::Surface(const sp<SurfaceControl>& surface) : mInitCheck(NO_INIT), : SurfaceTextureClient(), mInitCheck(NO_INIT), mSurface(surface->mSurface), mIdentity(surface->mIdentity), mFormat(surface->mFormat), mFlags(surface->mFlags), Loading @@ -287,7 +235,8 @@ Surface::Surface(const sp<SurfaceControl>& surface) } Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref) : mInitCheck(NO_INIT) : SurfaceTextureClient(), mInitCheck(NO_INIT) { mSurface = interface_cast<ISurface>(ref); mIdentity = parcel.readInt32(); Loading Loading @@ -363,36 +312,21 @@ void Surface::cleanCachedSurfacesLocked() { void Surface::init() { ANativeWindow::setSwapInterval = setSwapInterval; ANativeWindow::dequeueBuffer = dequeueBuffer; ANativeWindow::cancelBuffer = cancelBuffer; ANativeWindow::lockBuffer = lockBuffer; ANativeWindow::queueBuffer = queueBuffer; ANativeWindow::query = query; ANativeWindow::perform = perform; if (mSurface != NULL) { sp<ISurfaceTexture> surfaceTexture(mSurface->getSurfaceTexture()); LOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface"); if (surfaceTexture != NULL) { mSurfaceTextureClient = new SurfaceTextureClient(surfaceTexture); mSurfaceTextureClient->setUsage(GraphicBuffer::USAGE_HW_RENDER); setISurfaceTexture(surfaceTexture); setUsage(GraphicBuffer::USAGE_HW_RENDER); } DisplayInfo dinfo; SurfaceComposerClient::getDisplayInfo(0, &dinfo); const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi; const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi; const_cast<int&>(ANativeWindow::minSwapInterval) = mSurfaceTextureClient->minSwapInterval; const_cast<int&>(ANativeWindow::maxSwapInterval) = mSurfaceTextureClient->maxSwapInterval; const_cast<uint32_t&>(ANativeWindow::flags) = 0; if (mSurfaceTextureClient != 0) { if (surfaceTexture != NULL) { mInitCheck = NO_ERROR; } } Loading @@ -402,7 +336,6 @@ Surface::~Surface() { // clear all references and trigger an IPC now, to make sure things // happen without delay, since these resources are quite heavy. mSurfaceTextureClient.clear(); mSurface.clear(); IPCThreadState::self()->flushCommands(); } Loading Loading @@ -431,77 +364,6 @@ sp<IBinder> Surface::asBinder() const { // ---------------------------------------------------------------------------- int Surface::setSwapInterval(ANativeWindow* window, int interval) { Surface* self = getSelf(window); return self->setSwapInterval(interval); } int Surface::dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer) { Surface* self = getSelf(window); return self->dequeueBuffer(buffer); } int Surface::cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer) { Surface* self = getSelf(window); return self->cancelBuffer(buffer); } int Surface::lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer) { Surface* self = getSelf(window); return self->lockBuffer(buffer); } int Surface::queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer) { Surface* self = getSelf(window); return self->queueBuffer(buffer); } int Surface::query(const ANativeWindow* window, int what, int* value) { const Surface* self = getSelf(window); return self->query(what, value); } int Surface::perform(ANativeWindow* window, int operation, ...) { va_list args; va_start(args, operation); Surface* self = getSelf(window); int res = self->perform(operation, args); va_end(args); return res; } // ---------------------------------------------------------------------------- int Surface::setSwapInterval(int interval) { return mSurfaceTextureClient->setSwapInterval(interval); } int Surface::dequeueBuffer(ANativeWindowBuffer** buffer) { status_t err = mSurfaceTextureClient->dequeueBuffer(buffer); if (err == NO_ERROR) { mDirtyRegion.set(buffer[0]->width, buffer[0]->height); } return err; } int Surface::cancelBuffer(ANativeWindowBuffer* buffer) { return mSurfaceTextureClient->cancelBuffer(buffer); } int Surface::lockBuffer(ANativeWindowBuffer* buffer) { return mSurfaceTextureClient->lockBuffer(buffer); } int Surface::queueBuffer(ANativeWindowBuffer* buffer) { return mSurfaceTextureClient->queueBuffer(buffer); } int Surface::query(int what, int* value) const { switch (what) { case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: Loading @@ -509,141 +371,39 @@ int Surface::query(int what, int* value) const { *value = 1; return NO_ERROR; case NATIVE_WINDOW_CONCRETE_TYPE: // TODO: this is not needed anymore *value = NATIVE_WINDOW_SURFACE; return NO_ERROR; } return mSurfaceTextureClient->query(what, value); } int Surface::perform(int operation, va_list args) { return mSurfaceTextureClient->perform(operation, args); return SurfaceTextureClient::query(what, value); } // ---------------------------------------------------------------------------- int Surface::getConnectedApi() const { return mSurfaceTextureClient->getConnectedApi(); } // ---------------------------------------------------------------------------- status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn) { ANativeWindow_Buffer outBuffer; status_t Surface::lock(SurfaceInfo* info, bool blocking) { return Surface::lock(info, NULL, blocking); ARect temp; ARect* inOutDirtyBounds = NULL; if (dirtyIn) { temp = dirtyIn->getBounds(); inOutDirtyBounds = &temp; } status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) { if (getConnectedApi()) { LOGE("Surface::lock(%p) failed. Already connected to another API", (ANativeWindow*)this); CallStack stack; stack.update(); stack.dump(""); return INVALID_OPERATION; } if (mApiLock.tryLock() != NO_ERROR) { LOGE("calling Surface::lock from different threads!"); CallStack stack; stack.update(); stack.dump(""); return WOULD_BLOCK; } /* Here we're holding mApiLock */ status_t err = SurfaceTextureClient::lock(&outBuffer, inOutDirtyBounds); if (mLockedBuffer != 0) { LOGE("Surface::lock failed, already locked"); mApiLock.unlock(); return INVALID_OPERATION; } // we're intending to do software rendering from this point mSurfaceTextureClient->setUsage( GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); ANativeWindowBuffer* out; status_t err = mSurfaceTextureClient->dequeueBuffer(&out); LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err)); if (err == NO_ERROR) { sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out)); err = mSurfaceTextureClient->lockBuffer(backBuffer.get()); LOGE_IF(err, "lockBuffer (handle=%p) failed (%s)", backBuffer->handle, strerror(-err)); if (err == NO_ERROR) { const Rect bounds(backBuffer->width, backBuffer->height); const Region boundsRegion(bounds); Region scratch(boundsRegion); Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch); newDirtyRegion &= boundsRegion; // figure out if we can copy the frontbuffer back const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); const bool canCopyBack = (frontBuffer != 0 && backBuffer->width == frontBuffer->width && backBuffer->height == frontBuffer->height && backBuffer->format == frontBuffer->format && !(mFlags & ISurfaceComposer::eDestroyBackbuffer)); // the dirty region we report to surfaceflinger is the one // given by the user (as opposed to the one *we* return to the // user). mDirtyRegion = newDirtyRegion; if (canCopyBack) { // copy the area that is invalid and not repainted this round const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion)); if (!copyback.isEmpty()) copyBlt(backBuffer, frontBuffer, copyback); } else { // if we can't copy-back anything, modify the user's dirty // region to make sure they redraw the whole buffer newDirtyRegion = boundsRegion; } // keep track of the are of the buffer that is "clean" // (ie: that will be redrawn) mOldDirtyRegion = newDirtyRegion; void* vaddr; status_t res = backBuffer->lock( GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, newDirtyRegion.bounds(), &vaddr); LOGW_IF(res, "failed locking buffer (handle = %p)", backBuffer->handle); mLockedBuffer = backBuffer; other->w = backBuffer->width; other->h = backBuffer->height; other->s = backBuffer->stride; other->usage = backBuffer->usage; other->format = backBuffer->format; other->bits = vaddr; } } mApiLock.unlock(); return err; other->w = uint32_t(outBuffer.width); other->h = uint32_t(outBuffer.height); other->s = uint32_t(outBuffer.stride); other->usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; other->format = uint32_t(outBuffer.format); other->bits = outBuffer.bits; } status_t Surface::unlockAndPost() { if (mLockedBuffer == 0) { LOGE("Surface::unlockAndPost failed, no locked buffer"); return INVALID_OPERATION; return err; } status_t err = mLockedBuffer->unlock(); LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle); err = mSurfaceTextureClient->queueBuffer(mLockedBuffer.get()); LOGE_IF(err, "queueBuffer (handle=%p) failed (%s)", mLockedBuffer->handle, strerror(-err)); mPostedBuffer = mLockedBuffer; mLockedBuffer = 0; return err; status_t Surface::unlockAndPost() { return SurfaceTextureClient::unlockAndPost(); } // ---------------------------------------------------------------------------- Loading libs/gui/SurfaceTexture.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -495,7 +495,7 @@ status_t SurfaceTexture::setTransform(uint32_t transform) { } status_t SurfaceTexture::connect(int api) { LOGV("SurfaceTexture::connect"); LOGV("SurfaceTexture::connect(this=%p, %d)", this, api); Mutex::Autolock lock(mMutex); int err = NO_ERROR; switch (api) { Loading @@ -504,6 +504,8 @@ status_t SurfaceTexture::connect(int api) { case NATIVE_WINDOW_API_MEDIA: case NATIVE_WINDOW_API_CAMERA: if (mConnectedApi != NO_CONNECTED_API) { LOGE("connect: already connected (cur=%d, req=%d)", mConnectedApi, api); err = -EINVAL; } else { mConnectedApi = api; Loading @@ -517,7 +519,7 @@ status_t SurfaceTexture::connect(int api) { } status_t SurfaceTexture::disconnect(int api) { LOGV("SurfaceTexture::disconnect"); LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api); Mutex::Autolock lock(mMutex); int err = NO_ERROR; switch (api) { Loading @@ -528,6 +530,8 @@ status_t SurfaceTexture::disconnect(int api) { if (mConnectedApi == api) { mConnectedApi = NO_CONNECTED_API; } else { LOGE("disconnect: connected to another api (cur=%d, req=%d)", mConnectedApi, api); err = -EINVAL; } break; Loading libs/gui/SurfaceTextureClient.cpp +224 −33 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
include/gui/SurfaceTextureClient.h +46 −32 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <gui/SurfaceTexture.h> #include <ui/egl/android_natives.h> #include <ui/Region.h> #include <utils/RefBase.h> #include <utils/threads.h> Loading @@ -37,29 +38,24 @@ public: sp<ISurfaceTexture> getISurfaceTexture() const; private: friend class Surface; protected: SurfaceTextureClient(); void setISurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture); private: // can't be copied SurfaceTextureClient& operator = (const SurfaceTextureClient& rhs); SurfaceTextureClient(const SurfaceTextureClient& rhs); void init(); // ANativeWindow hooks static int cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer); static int lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int perform(ANativeWindow* window, int operation, ...); static int query(const ANativeWindow* window, int what, int* value); static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int setSwapInterval(ANativeWindow* window, int interval); int cancelBuffer(ANativeWindowBuffer* buffer); int dequeueBuffer(ANativeWindowBuffer** buffer); int lockBuffer(ANativeWindowBuffer* buffer); int perform(int operation, va_list args); int query(int what, int* value) const; int queueBuffer(ANativeWindowBuffer* buffer); int setSwapInterval(int interval); static int hook_cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer); static int hook_lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int hook_perform(ANativeWindow* window, int operation, ...); static int hook_query(const ANativeWindow* window, int what, int* value); static int hook_queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int hook_setSwapInterval(ANativeWindow* window, int interval); int dispatchConnect(va_list args); int dispatchDisconnect(va_list args); Loading @@ -71,26 +67,38 @@ private: int dispatchSetBuffersTimestamp(va_list args); int dispatchSetCrop(va_list args); int dispatchSetUsage(va_list args); int connect(int api); int disconnect(int api); int setBufferCount(int bufferCount); int setBuffersDimensions(int w, int h); int setBuffersFormat(int format); int setBuffersTransform(int transform); int setBuffersTimestamp(int64_t timestamp); int setCrop(Rect const* rect); int setUsage(uint32_t reqUsage); void freeAllBuffers(); int getSlotFromBufferLocked(android_native_buffer_t* buffer) const; int getConnectedApi() const; int dispatchLock(va_list args); int dispatchUnlockAndPost(va_list args); protected: virtual int cancelBuffer(ANativeWindowBuffer* buffer); virtual int dequeueBuffer(ANativeWindowBuffer** buffer); virtual int lockBuffer(ANativeWindowBuffer* buffer); virtual int perform(int operation, va_list args); virtual int query(int what, int* value) const; virtual int queueBuffer(ANativeWindowBuffer* buffer); virtual int setSwapInterval(int interval); virtual int connect(int api); virtual int disconnect(int api); virtual int setBufferCount(int bufferCount); virtual int setBuffersDimensions(int w, int h); virtual int setBuffersFormat(int format); virtual int setBuffersTransform(int transform); virtual int setBuffersTimestamp(int64_t timestamp); virtual int setCrop(Rect const* rect); virtual int setUsage(uint32_t reqUsage); virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds); virtual int unlockAndPost(); enum { MIN_UNDEQUEUED_BUFFERS = SurfaceTexture::MIN_UNDEQUEUED_BUFFERS }; enum { NUM_BUFFER_SLOTS = SurfaceTexture::NUM_BUFFER_SLOTS }; enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 }; private: void freeAllBuffers(); int getSlotFromBufferLocked(android_native_buffer_t* buffer) const; // mSurfaceTexture is the interface to the surface texture server. All // operations on the surface texture client ultimately translate into // interactions with the server using this interface. Loading Loading @@ -145,6 +153,12 @@ private: // variables of SurfaceTexture objects. It must be locked whenever the // member variables are accessed. mutable Mutex mMutex; // must be used from the lock/unlock thread sp<GraphicBuffer> mLockedBuffer; sp<GraphicBuffer> mPostedBuffer; mutable Region mOldDirtyRegion; bool mConnectedToCpu; }; }; // namespace android Loading
include/surfaceflinger/Surface.h +6 −63 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ #include <ui/Region.h> #include <ui/egl/android_natives.h> #include <gui/SurfaceTextureClient.h> #include <surfaceflinger/ISurface.h> #include <surfaceflinger/ISurfaceComposerClient.h> Loading @@ -37,14 +39,9 @@ namespace android { // --------------------------------------------------------------------------- class GraphicBuffer; class GraphicBufferMapper; class IOMX; class ISurfaceTexture; class Rect; class Surface; class SurfaceComposerClient; class SurfaceTextureClient; // --------------------------------------------------------------------------- Loading Loading @@ -129,8 +126,7 @@ private: // --------------------------------------------------------------------------- class Surface : public EGLNativeBase<ANativeWindow, Surface, RefBase> class Surface : public SurfaceTextureClient { public: struct SurfaceInfo { Loading Loading @@ -158,32 +154,14 @@ public: sp<ISurfaceTexture> getSurfaceTexture(); // the lock/unlock APIs must be used from the same thread status_t lock(SurfaceInfo* info, bool blocking = true); status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true); status_t lock(SurfaceInfo* info, Region* dirty = NULL); status_t unlockAndPost(); sp<IBinder> asBinder() const; private: /* * Android frameworks friends * (eventually this should go away and be replaced by proper APIs) */ // camera and camcorder need access to the ISurface binder interface for preview friend class CameraService; friend class MediaRecorder; // MediaPlayer needs access to ISurface for display friend class MediaPlayer; friend class IOMX; friend class SoftwareRenderer; // this is just to be able to write some unit tests friend class Test; // videoEditor preview classes friend class VideoEditorPreviewController; friend class PreviewRenderer; private: friend class SurfaceComposerClient; friend class SurfaceControl; // can't be copied Loading @@ -194,62 +172,27 @@ private: Surface(const Parcel& data, const sp<IBinder>& ref); ~Surface(); /* * ANativeWindow hooks */ static int setSwapInterval(ANativeWindow* window, int interval); static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer); static int cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int query(const ANativeWindow* window, int what, int* value); static int perform(ANativeWindow* window, int operation, ...); int setSwapInterval(int interval); int dequeueBuffer(ANativeWindowBuffer** buffer); int lockBuffer(ANativeWindowBuffer* buffer); int queueBuffer(ANativeWindowBuffer* buffer); int cancelBuffer(ANativeWindowBuffer* buffer); int query(int what, int* value) const; int perform(int operation, va_list args); /* * private stuff... */ void init(); status_t validate(bool inCancelBuffer = false) const; int getConnectedApi() const; static void cleanCachedSurfacesLocked(); virtual int query(int what, int* value) const; // constants status_t mInitCheck; sp<ISurface> mSurface; sp<SurfaceTextureClient> mSurfaceTextureClient; uint32_t mIdentity; PixelFormat mFormat; uint32_t mFlags; // protected by mSurfaceLock. These are also used from lock/unlock // but in that case, they must be called form the same thread. mutable Region mDirtyRegion; // must be used from the lock/unlock thread sp<GraphicBuffer> mLockedBuffer; sp<GraphicBuffer> mPostedBuffer; mutable Region mOldDirtyRegion; bool mReserved; // query() must be called from dequeueBuffer() thread uint32_t mWidth; uint32_t mHeight; // Inherently thread-safe mutable Mutex mSurfaceLock; mutable Mutex mApiLock; // A cache of Surface objects that have been deserialized into this process. static Mutex sCachedSurfacesLock; static DefaultKeyedVector<wp<IBinder>, wp<Surface> > sCachedSurfaces; Loading
libs/gui/Surface.cpp +24 −264 Original line number Diff line number Diff line Loading @@ -46,59 +46,6 @@ namespace android { // ---------------------------------------------------------------------- static status_t copyBlt( const sp<GraphicBuffer>& dst, const sp<GraphicBuffer>& src, const Region& reg) { // 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); LOGE_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); LOGE_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; while (head != tail) { const Rect& r(*head++); ssize_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; if (dbpr==sbpr && size==sbpr) { size *= h; h = 1; } do { memcpy(d, s, size); d += dbpr; s += sbpr; } while (--h > 0); } } if (src_bits) src->unlock(); if (dst_bits) dst->unlock(); return err; } // ============================================================================ // SurfaceControl // ============================================================================ Loading Loading @@ -277,7 +224,8 @@ sp<Surface> SurfaceControl::getSurface() const // --------------------------------------------------------------------------- Surface::Surface(const sp<SurfaceControl>& surface) : mInitCheck(NO_INIT), : SurfaceTextureClient(), mInitCheck(NO_INIT), mSurface(surface->mSurface), mIdentity(surface->mIdentity), mFormat(surface->mFormat), mFlags(surface->mFlags), Loading @@ -287,7 +235,8 @@ Surface::Surface(const sp<SurfaceControl>& surface) } Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref) : mInitCheck(NO_INIT) : SurfaceTextureClient(), mInitCheck(NO_INIT) { mSurface = interface_cast<ISurface>(ref); mIdentity = parcel.readInt32(); Loading Loading @@ -363,36 +312,21 @@ void Surface::cleanCachedSurfacesLocked() { void Surface::init() { ANativeWindow::setSwapInterval = setSwapInterval; ANativeWindow::dequeueBuffer = dequeueBuffer; ANativeWindow::cancelBuffer = cancelBuffer; ANativeWindow::lockBuffer = lockBuffer; ANativeWindow::queueBuffer = queueBuffer; ANativeWindow::query = query; ANativeWindow::perform = perform; if (mSurface != NULL) { sp<ISurfaceTexture> surfaceTexture(mSurface->getSurfaceTexture()); LOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface"); if (surfaceTexture != NULL) { mSurfaceTextureClient = new SurfaceTextureClient(surfaceTexture); mSurfaceTextureClient->setUsage(GraphicBuffer::USAGE_HW_RENDER); setISurfaceTexture(surfaceTexture); setUsage(GraphicBuffer::USAGE_HW_RENDER); } DisplayInfo dinfo; SurfaceComposerClient::getDisplayInfo(0, &dinfo); const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi; const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi; const_cast<int&>(ANativeWindow::minSwapInterval) = mSurfaceTextureClient->minSwapInterval; const_cast<int&>(ANativeWindow::maxSwapInterval) = mSurfaceTextureClient->maxSwapInterval; const_cast<uint32_t&>(ANativeWindow::flags) = 0; if (mSurfaceTextureClient != 0) { if (surfaceTexture != NULL) { mInitCheck = NO_ERROR; } } Loading @@ -402,7 +336,6 @@ Surface::~Surface() { // clear all references and trigger an IPC now, to make sure things // happen without delay, since these resources are quite heavy. mSurfaceTextureClient.clear(); mSurface.clear(); IPCThreadState::self()->flushCommands(); } Loading Loading @@ -431,77 +364,6 @@ sp<IBinder> Surface::asBinder() const { // ---------------------------------------------------------------------------- int Surface::setSwapInterval(ANativeWindow* window, int interval) { Surface* self = getSelf(window); return self->setSwapInterval(interval); } int Surface::dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer) { Surface* self = getSelf(window); return self->dequeueBuffer(buffer); } int Surface::cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer) { Surface* self = getSelf(window); return self->cancelBuffer(buffer); } int Surface::lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer) { Surface* self = getSelf(window); return self->lockBuffer(buffer); } int Surface::queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer) { Surface* self = getSelf(window); return self->queueBuffer(buffer); } int Surface::query(const ANativeWindow* window, int what, int* value) { const Surface* self = getSelf(window); return self->query(what, value); } int Surface::perform(ANativeWindow* window, int operation, ...) { va_list args; va_start(args, operation); Surface* self = getSelf(window); int res = self->perform(operation, args); va_end(args); return res; } // ---------------------------------------------------------------------------- int Surface::setSwapInterval(int interval) { return mSurfaceTextureClient->setSwapInterval(interval); } int Surface::dequeueBuffer(ANativeWindowBuffer** buffer) { status_t err = mSurfaceTextureClient->dequeueBuffer(buffer); if (err == NO_ERROR) { mDirtyRegion.set(buffer[0]->width, buffer[0]->height); } return err; } int Surface::cancelBuffer(ANativeWindowBuffer* buffer) { return mSurfaceTextureClient->cancelBuffer(buffer); } int Surface::lockBuffer(ANativeWindowBuffer* buffer) { return mSurfaceTextureClient->lockBuffer(buffer); } int Surface::queueBuffer(ANativeWindowBuffer* buffer) { return mSurfaceTextureClient->queueBuffer(buffer); } int Surface::query(int what, int* value) const { switch (what) { case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: Loading @@ -509,141 +371,39 @@ int Surface::query(int what, int* value) const { *value = 1; return NO_ERROR; case NATIVE_WINDOW_CONCRETE_TYPE: // TODO: this is not needed anymore *value = NATIVE_WINDOW_SURFACE; return NO_ERROR; } return mSurfaceTextureClient->query(what, value); } int Surface::perform(int operation, va_list args) { return mSurfaceTextureClient->perform(operation, args); return SurfaceTextureClient::query(what, value); } // ---------------------------------------------------------------------------- int Surface::getConnectedApi() const { return mSurfaceTextureClient->getConnectedApi(); } // ---------------------------------------------------------------------------- status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn) { ANativeWindow_Buffer outBuffer; status_t Surface::lock(SurfaceInfo* info, bool blocking) { return Surface::lock(info, NULL, blocking); ARect temp; ARect* inOutDirtyBounds = NULL; if (dirtyIn) { temp = dirtyIn->getBounds(); inOutDirtyBounds = &temp; } status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) { if (getConnectedApi()) { LOGE("Surface::lock(%p) failed. Already connected to another API", (ANativeWindow*)this); CallStack stack; stack.update(); stack.dump(""); return INVALID_OPERATION; } if (mApiLock.tryLock() != NO_ERROR) { LOGE("calling Surface::lock from different threads!"); CallStack stack; stack.update(); stack.dump(""); return WOULD_BLOCK; } /* Here we're holding mApiLock */ status_t err = SurfaceTextureClient::lock(&outBuffer, inOutDirtyBounds); if (mLockedBuffer != 0) { LOGE("Surface::lock failed, already locked"); mApiLock.unlock(); return INVALID_OPERATION; } // we're intending to do software rendering from this point mSurfaceTextureClient->setUsage( GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); ANativeWindowBuffer* out; status_t err = mSurfaceTextureClient->dequeueBuffer(&out); LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err)); if (err == NO_ERROR) { sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out)); err = mSurfaceTextureClient->lockBuffer(backBuffer.get()); LOGE_IF(err, "lockBuffer (handle=%p) failed (%s)", backBuffer->handle, strerror(-err)); if (err == NO_ERROR) { const Rect bounds(backBuffer->width, backBuffer->height); const Region boundsRegion(bounds); Region scratch(boundsRegion); Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch); newDirtyRegion &= boundsRegion; // figure out if we can copy the frontbuffer back const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); const bool canCopyBack = (frontBuffer != 0 && backBuffer->width == frontBuffer->width && backBuffer->height == frontBuffer->height && backBuffer->format == frontBuffer->format && !(mFlags & ISurfaceComposer::eDestroyBackbuffer)); // the dirty region we report to surfaceflinger is the one // given by the user (as opposed to the one *we* return to the // user). mDirtyRegion = newDirtyRegion; if (canCopyBack) { // copy the area that is invalid and not repainted this round const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion)); if (!copyback.isEmpty()) copyBlt(backBuffer, frontBuffer, copyback); } else { // if we can't copy-back anything, modify the user's dirty // region to make sure they redraw the whole buffer newDirtyRegion = boundsRegion; } // keep track of the are of the buffer that is "clean" // (ie: that will be redrawn) mOldDirtyRegion = newDirtyRegion; void* vaddr; status_t res = backBuffer->lock( GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, newDirtyRegion.bounds(), &vaddr); LOGW_IF(res, "failed locking buffer (handle = %p)", backBuffer->handle); mLockedBuffer = backBuffer; other->w = backBuffer->width; other->h = backBuffer->height; other->s = backBuffer->stride; other->usage = backBuffer->usage; other->format = backBuffer->format; other->bits = vaddr; } } mApiLock.unlock(); return err; other->w = uint32_t(outBuffer.width); other->h = uint32_t(outBuffer.height); other->s = uint32_t(outBuffer.stride); other->usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; other->format = uint32_t(outBuffer.format); other->bits = outBuffer.bits; } status_t Surface::unlockAndPost() { if (mLockedBuffer == 0) { LOGE("Surface::unlockAndPost failed, no locked buffer"); return INVALID_OPERATION; return err; } status_t err = mLockedBuffer->unlock(); LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle); err = mSurfaceTextureClient->queueBuffer(mLockedBuffer.get()); LOGE_IF(err, "queueBuffer (handle=%p) failed (%s)", mLockedBuffer->handle, strerror(-err)); mPostedBuffer = mLockedBuffer; mLockedBuffer = 0; return err; status_t Surface::unlockAndPost() { return SurfaceTextureClient::unlockAndPost(); } // ---------------------------------------------------------------------------- Loading
libs/gui/SurfaceTexture.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -495,7 +495,7 @@ status_t SurfaceTexture::setTransform(uint32_t transform) { } status_t SurfaceTexture::connect(int api) { LOGV("SurfaceTexture::connect"); LOGV("SurfaceTexture::connect(this=%p, %d)", this, api); Mutex::Autolock lock(mMutex); int err = NO_ERROR; switch (api) { Loading @@ -504,6 +504,8 @@ status_t SurfaceTexture::connect(int api) { case NATIVE_WINDOW_API_MEDIA: case NATIVE_WINDOW_API_CAMERA: if (mConnectedApi != NO_CONNECTED_API) { LOGE("connect: already connected (cur=%d, req=%d)", mConnectedApi, api); err = -EINVAL; } else { mConnectedApi = api; Loading @@ -517,7 +519,7 @@ status_t SurfaceTexture::connect(int api) { } status_t SurfaceTexture::disconnect(int api) { LOGV("SurfaceTexture::disconnect"); LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api); Mutex::Autolock lock(mMutex); int err = NO_ERROR; switch (api) { Loading @@ -528,6 +530,8 @@ status_t SurfaceTexture::disconnect(int api) { if (mConnectedApi == api) { mConnectedApi = NO_CONNECTED_API; } else { LOGE("disconnect: connected to another api (cur=%d, req=%d)", mConnectedApi, api); err = -EINVAL; } break; Loading
libs/gui/SurfaceTextureClient.cpp +224 −33 File changed.Preview size limit exceeded, changes collapsed. Show changes