diff options
Diffstat (limited to 'libs')
23 files changed, 646 insertions, 353 deletions
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index ea68352..d979f00 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -266,9 +266,6 @@ void DisplayHardware::init(uint32_t dpy) if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) { mFlags |= NPOT_EXTENSION; } - if (strstr(gl_extensions, "GL_OES_draw_texture")) { - mFlags |= DRAW_TEXTURE_EXTENSION; - } #ifdef EGL_ANDROID_image_native_buffer if (strstr( gl_extensions, "GL_OES_EGL_image") && (strstr(egl_extensions, "EGL_KHR_image_base") || diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h index df046af..897a6ed 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -46,7 +46,6 @@ public: DIRECT_TEXTURE = 0x00000002, COPY_BITS_EXTENSION = 0x00000008, NPOT_EXTENSION = 0x00000100, - DRAW_TEXTURE_EXTENSION = 0x00000200, BUFFER_PRESERVED = 0x00010000, PARTIAL_UPDATES = 0x00020000, // video driver feature SLOW_CONFIG = 0x00040000, // software diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index 0a3254d..566428f 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -47,11 +47,6 @@ template <typename T> inline T min(T a, T b) { // --------------------------------------------------------------------------- -const uint32_t Layer::typeInfo = LayerBaseClient::typeInfo | 4; -const char* const Layer::typeID = "Layer"; - -// --------------------------------------------------------------------------- - Layer::Layer(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& c, int32_t i) : LayerBaseClient(flinger, display, c, i), @@ -540,9 +535,15 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) mFlinger->signalEvent(); } - if (!mPostedDirtyRegion.isEmpty()) { - reloadTexture( mPostedDirtyRegion ); - } + /* a buffer was posted, so we need to call reloadTexture(), which + * will update our internal data structures (eg: EGLImageKHR or + * texture names). we need to do this even if mPostedDirtyRegion is + * empty -- it's orthogonal to the fact that a new buffer was posted, + * for instance, a degenerate case could be that the user did an empty + * update but repainted the buffer with appropriate content (after a + * resize for instance). + */ + reloadTexture( mPostedDirtyRegion ); } void Layer::unlockPageFlip( @@ -566,7 +567,7 @@ void Layer::unlockPageFlip( } if (visibleRegionScreen.isEmpty()) { // an invisible layer should not hold a freeze-lock - // (because it may never be updated and thereore never release it) + // (because it may never be updated and therefore never release it) mFreezeLock.clear(); } } @@ -579,6 +580,38 @@ void Layer::finishPageFlip() this, mFrontBufferIndex); } + +void Layer::dump(String8& result, char* buffer, size_t SIZE) const +{ + LayerBaseClient::dump(result, buffer, SIZE); + + SharedBufferStack::Statistics stats = lcblk->getStats(); + result.append( lcblk->dump(" ") ); + sp<const GraphicBuffer> buf0(getBuffer(0)); + sp<const GraphicBuffer> buf1(getBuffer(1)); + uint32_t w0=0, h0=0, s0=0; + uint32_t w1=0, h1=0, s1=0; + if (buf0 != 0) { + w0 = buf0->getWidth(); + h0 = buf0->getHeight(); + s0 = buf0->getStride(); + } + if (buf1 != 0) { + w1 = buf1->getWidth(); + h1 = buf1->getHeight(); + s1 = buf1->getStride(); + } + snprintf(buffer, SIZE, + " " + "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u]," + " freezeLock=%p, dq-q-time=%u us\n", + pixelFormat(), + w0, h0, s0, w1, h1, s1, + getFreezeLock().get(), stats.totalTime); + + result.append(buffer); +} + // --------------------------------------------------------------------------- Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger, diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h index 743afb4..98e30d7 100644 --- a/libs/surfaceflinger/Layer.h +++ b/libs/surfaceflinger/Layer.h @@ -46,11 +46,6 @@ const size_t NUM_BUFFERS = 2; class Layer : public LayerBaseClient { public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - Layer(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& client, int32_t i); @@ -73,7 +68,7 @@ public: virtual status_t ditch(); // only for debugging - inline sp<GraphicBuffer> getBuffer(int i) { return mBuffers[i]; } + inline sp<GraphicBuffer> getBuffer(int i) const { return mBuffers[i]; } // only for debugging inline const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; } // only for debugging @@ -81,6 +76,11 @@ public: // only for debugging inline int getFrontBufferIndex() const { return mFrontBufferIndex; } + virtual const char* getTypeId() const { return "Layer"; } + +protected: + virtual void dump(String8& result, char* scratch, size_t size) const; + private: inline sp<GraphicBuffer> getFrontBufferLocked() { return mBuffers[mFrontBufferIndex]; diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp index a8b735e..48b0e47 100644 --- a/libs/surfaceflinger/LayerBase.cpp +++ b/libs/surfaceflinger/LayerBase.cpp @@ -38,14 +38,6 @@ namespace android { // --------------------------------------------------------------------------- -const uint32_t LayerBase::typeInfo = 1; -const char* const LayerBase::typeID = "LayerBase"; - -const uint32_t LayerBaseClient::typeInfo = LayerBase::typeInfo | 2; -const char* const LayerBaseClient::typeID = "LayerBaseClient"; - -// --------------------------------------------------------------------------- - LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) : dpy(display), contentDirty(false), mFlinger(flinger), @@ -54,7 +46,7 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) mOrientation(0), mLeft(0), mTop(0), mTransactionFlags(0), - mPremultipliedAlpha(true), mDebug(false), + mPremultipliedAlpha(true), mName("unnamed"), mDebug(false), mInvalidate(0) { const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware()); @@ -374,7 +366,7 @@ void LayerBase::clearWithOpenGL(const Region& clip, GLclampx red, Region::const_iterator it = clip.begin(); Region::const_iterator const end = clip.end(); glEnable(GL_SCISSOR_TEST); - glVertexPointer(2, GL_FIXED, 0, mVertices); + glVertexPointer(2, GL_FLOAT, 0, mVertices); while (it != end) { const Rect& r = *it++; const GLint sy = fbHeight - (r.top + r.height()); @@ -418,14 +410,14 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const env = GL_REPLACE; src = GL_SRC_ALPHA; } - const GGLfixed alpha = (s.alpha << 16)/255; - glColor4x(alpha, alpha, alpha, alpha); + const GLfloat alpha = s.alpha * (1.0f/255.0f); + glColor4f(alpha, alpha, alpha, alpha); glEnable(GL_BLEND); glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env); } else { glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glColor4x(0x10000, 0x10000, 0x10000, 0x10000); + glColor4f(1, 1, 1, 1); if (needsBlending()) { GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA; glEnable(GL_BLEND); @@ -437,13 +429,11 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const Region::const_iterator it = clip.begin(); Region::const_iterator const end = clip.end(); - - //StopWatch watch("GL transformed"); - const GLfixed texCoords[4][2] = { - { 0, 0 }, - { 0, 0x10000 }, - { 0x10000, 0x10000 }, - { 0x10000, 0 } + const GLfloat texCoords[4][2] = { + { 0, 0 }, + { 0, 1 }, + { 1, 1 }, + { 1, 0 } }; glMatrixMode(GL_TEXTURE); @@ -470,8 +460,8 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const } glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glVertexPointer(2, GL_FIXED, 0, mVertices); - glTexCoordPointer(2, GL_FIXED, 0, texCoords); + glVertexPointer(2, GL_FLOAT, 0, mVertices); + glTexCoordPointer(2, GL_FLOAT, 0, texCoords); while (it != end) { const Rect& r = *it++; @@ -683,6 +673,22 @@ status_t LayerBase::initializeEglImage( return err; } +void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const +{ + const Layer::State& s(drawingState()); + snprintf(buffer, SIZE, + "+ %s %p\n" + " " + "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), " + "needsBlending=%1d, needsDithering=%1d, invalidate=%1d, " + "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n", + getTypeId(), this, s.z, tx(), ty(), s.w, s.h, + needsBlending(), needsDithering(), contentDirty, + s.alpha, s.flags, + s.transform[0][0], s.transform[0][1], + s.transform[1][0], s.transform[1][1]); + result.append(buffer); +} // --------------------------------------------------------------------------- @@ -715,13 +721,13 @@ LayerBaseClient::~LayerBaseClient() delete lcblk; } -int32_t LayerBaseClient::serverIndex() const +ssize_t LayerBaseClient::serverIndex() const { sp<Client> client(this->client.promote()); if (client != 0) { return (client->cid<<16)|mIndex; } - return 0xFFFF0000 | mIndex; + return ssize_t(0xFFFF0000 | mIndex); } sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() @@ -750,6 +756,21 @@ void LayerBaseClient::onRemoved() lcblk->setStatus(NO_INIT); } +void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const +{ + LayerBase::dump(result, buffer, SIZE); + + sp<Client> client(this->client.promote()); + snprintf(buffer, SIZE, + " name=%s\n" + " id=0x%08x, client=0x%08x, identity=%u\n", + getName().string(), + clientIndex(), client.get() ? client->cid : 0, + getIdentity()); + + result.append(buffer); +} + // --------------------------------------------------------------------------- LayerBaseClient::Surface::Surface( diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h index 62ec839..219a53c 100644 --- a/libs/surfaceflinger/LayerBase.h +++ b/libs/surfaceflinger/LayerBase.h @@ -51,35 +51,9 @@ class SurfaceFlinger; class LayerBase : public RefBase { - // poor man's dynamic_cast below - template<typename T> - struct getTypeInfoOfAnyType { - static uint32_t get() { return T::typeInfo; } - }; - - template<typename T> - struct getTypeInfoOfAnyType<T*> { - static uint32_t get() { return getTypeInfoOfAnyType<T>::get(); } - }; - public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - - template<typename T> - static T dynamicCast(LayerBase* base) { - uint32_t mostDerivedInfo = base->getTypeInfo(); - uint32_t castToInfo = getTypeInfoOfAnyType<T>::get(); - if ((mostDerivedInfo & castToInfo) == castToInfo) - return static_cast<T>(base); - return 0; - } + LayerBase(SurfaceFlinger* flinger, DisplayID display); - - LayerBase(SurfaceFlinger* flinger, DisplayID display); - DisplayID dpy; mutable bool contentDirty; Region visibleRegionScreen; @@ -125,6 +99,9 @@ public: void invalidate(); + virtual const char* getTypeId() const { return "LayerBase"; } + virtual ssize_t serverIndex() const { return -1; } + /** * draw - performs some global clipping optimizations * and calls onDraw(). @@ -217,7 +194,10 @@ public: * current list */ virtual void onRemoved() { }; - + /** always call base class first */ + virtual void dump(String8& result, char* scratch, size_t size) const; + + enum { // flags for doTransaction() eVisibleRegion = 0x00000002, }; @@ -278,7 +258,7 @@ protected: bool mTransformed; bool mUseLinearFiltering; int32_t mOrientation; - GLfixed mVertices[4][2]; + GLfloat mVertices[4][2]; Rect mTransformedBounds; int mLeft; int mTop; @@ -313,10 +293,6 @@ class LayerBaseClient : public LayerBase { public: class Surface; - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } // lcblk is (almost) only accessed from the main SF thread, in the places // where it's not, a reference to Client must be held @@ -331,14 +307,12 @@ public: inline uint32_t getIdentity() const { return mIdentity; } inline int32_t clientIndex() const { return mIndex; } - int32_t serverIndex() const; - sp<Surface> getSurface(); virtual sp<Surface> createSurface() const; - - virtual void onRemoved(); - + virtual ssize_t serverIndex() const; + virtual void onRemoved(); + virtual const char* getTypeId() const { return "LayerBaseClient"; } class Surface : public BnSurface { @@ -373,8 +347,11 @@ public: friend class Surface; +protected: + virtual void dump(String8& result, char* scratch, size_t size) const; + private: - int32_t mIndex; + int32_t mIndex; mutable Mutex mLock; mutable wp<Surface> mClientSurface; // only read diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp index 5fd7904..2d77876 100644 --- a/libs/surfaceflinger/LayerBlur.cpp +++ b/libs/surfaceflinger/LayerBlur.cpp @@ -33,11 +33,6 @@ namespace android { // --------------------------------------------------------------------------- -const uint32_t LayerBlur::typeInfo = LayerBaseClient::typeInfo | 8; -const char* const LayerBlur::typeID = "LayerBlur"; - -// --------------------------------------------------------------------------- - LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& client, int32_t i) : LayerBaseClient(flinger, display, client, i), mCacheDirty(true), @@ -206,8 +201,8 @@ void LayerBlur::onDraw(const Region& clip) const const State& s = drawingState(); if (UNLIKELY(s.alpha < 0xFF)) { - const GGLfixed alpha = (s.alpha << 16)/255; - glColor4x(0, 0, 0, alpha); + const GLfloat alpha = s.alpha * (1.0f/255.0f); + glColor4f(0, 0, 0, alpha); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); @@ -225,38 +220,20 @@ void LayerBlur::onDraw(const Region& clip) const glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - if (UNLIKELY(transformed() - || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) { - // This is a very rare scenario. - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glScalef(mWidthScale, mHeightScale, 1); - glTranslatef(-x, mYOffset - y, 0); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glVertexPointer(2, GL_FIXED, 0, mVertices); - glTexCoordPointer(2, GL_FIXED, 0, mVertices); - while (it != end) { - const Rect& r = *it++; - const GLint sy = fbHeight - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } else { - // NOTE: this is marginally faster with the software gl, because - // glReadPixels() reads the fb bottom-to-top, however we'll - // skip all the jaccobian computations. - Rect r; - GLint crop[4] = { 0, 0, w, h }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); - y = fbHeight - (y + h); - while (it != end) { - const Rect& r = *it++; - const GLint sy = fbHeight - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawTexiOES(x, y, 0, w, h); - } + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glScalef(mWidthScale, mHeightScale, 1); + glTranslatef(-x, mYOffset - y, 0); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, mVertices); + glTexCoordPointer(2, GL_FLOAT, 0, mVertices); + while (it != end) { + const Rect& r = *it++; + const GLint sy = fbHeight - (r.top + r.height()); + glScissor(r.left, sy, r.width(), r.height()); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } + glDisableClientState(GL_TEXTURE_COORD_ARRAY); } } diff --git a/libs/surfaceflinger/LayerBlur.h b/libs/surfaceflinger/LayerBlur.h index 5b63dec..380f587 100644 --- a/libs/surfaceflinger/LayerBlur.h +++ b/libs/surfaceflinger/LayerBlur.h @@ -31,11 +31,6 @@ namespace android { class LayerBlur : public LayerBaseClient { public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - LayerBlur(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& client, int32_t i); virtual ~LayerBlur(); @@ -43,6 +38,7 @@ public: virtual void onDraw(const Region& clip) const; virtual bool needsBlending() const { return true; } virtual bool isSecure() const { return false; } + virtual const char* getTypeId() const { return "LayerBlur"; } virtual uint32_t doTransaction(uint32_t flags); virtual void setVisibleRegion(const Region& visibleRegion); diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index 5c21593..0041a0f 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -39,8 +39,6 @@ namespace android { // --------------------------------------------------------------------------- -const uint32_t LayerBuffer::typeInfo = LayerBaseClient::typeInfo | 0x20; -const char* const LayerBuffer::typeID = "LayerBuffer"; gralloc_module_t const* LayerBuffer::sGrallocModule = 0; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h index b176623..243cc43 100644 --- a/libs/surfaceflinger/LayerBuffer.h +++ b/libs/surfaceflinger/LayerBuffer.h @@ -52,17 +52,13 @@ class LayerBuffer : public LayerBaseClient }; public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - LayerBuffer(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& client, int32_t i); virtual ~LayerBuffer(); virtual void onFirstRef(); virtual bool needsBlending() const; + virtual const char* getTypeId() const { return "LayerBuffer"; } virtual sp<LayerBaseClient::Surface> createSurface() const; virtual status_t ditch(); diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp index fd61e30..568fedb 100644 --- a/libs/surfaceflinger/LayerDim.cpp +++ b/libs/surfaceflinger/LayerDim.cpp @@ -30,9 +30,6 @@ namespace android { // --------------------------------------------------------------------------- -const uint32_t LayerDim::typeInfo = LayerBaseClient::typeInfo | 0x10; -const char* const LayerDim::typeID = "LayerDim"; - bool LayerDim::sUseTexture; GLuint LayerDim::sTexId; EGLImageKHR LayerDim::sImage; diff --git a/libs/surfaceflinger/LayerDim.h b/libs/surfaceflinger/LayerDim.h index d4672a1..19a9990 100644 --- a/libs/surfaceflinger/LayerDim.h +++ b/libs/surfaceflinger/LayerDim.h @@ -37,11 +37,6 @@ class LayerDim : public LayerBaseClient static int32_t sWidth; static int32_t sHeight; public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - LayerDim(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& client, int32_t i); virtual ~LayerDim(); @@ -49,6 +44,7 @@ public: virtual void onDraw(const Region& clip) const; virtual bool needsBlending() const { return true; } virtual bool isSecure() const { return false; } + virtual const char* getTypeId() const { return "LayerDim"; } static void initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h); }; diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index 0722fda..62d829b 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -206,8 +206,8 @@ void SurfaceFlinger::init() property_get("debug.sf.showbackground", value, "0"); mDebugBackground = atoi(value); - LOGI_IF(mDebugRegion, "showupdates enabled"); - LOGI_IF(mDebugBackground, "showbackground enabled"); + LOGI_IF(mDebugRegion, "showupdates enabled"); + LOGI_IF(mDebugBackground, "showbackground enabled"); } SurfaceFlinger::~SurfaceFlinger() @@ -357,7 +357,6 @@ status_t SurfaceFlinger::readyToRun() dcblk->ydpi = hw.getDpiY(); dcblk->fps = hw.getRefreshRate(); dcblk->density = hw.getDensity(); - asm volatile ("":::"memory"); // Initialize OpenGL|ES glActiveTexture(GL_TEXTURE0); @@ -1079,15 +1078,15 @@ status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer) status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer) { - if (layer == 0) - return BAD_VALUE; ssize_t i = mCurrentState.layersSortedByZ.add( layer, &LayerBase::compareCurrentStateZ); - sp<LayerBaseClient> lbc = LayerBase::dynamicCast< LayerBaseClient* >(layer.get()); - if (lbc != 0) { - mLayerMap.add(lbc->serverIndex(), lbc); - } - return NO_ERROR; + return (i < 0) ? status_t(i) : status_t(NO_ERROR); +} + +status_t SurfaceFlinger::addClientLayer_l(const sp<LayerBaseClient>& lbc) +{ + ssize_t serverIndex = lbc->serverIndex(); + return mLayerMap.add(serverIndex, lbc); } status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase) @@ -1095,10 +1094,9 @@ status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase) ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase); if (index >= 0) { mLayersRemoved = true; - sp<LayerBaseClient> layer = - LayerBase::dynamicCast< LayerBaseClient* >(layerBase.get()); - if (layer != 0) { - mLayerMap.removeItem(layer->serverIndex()); + ssize_t serverIndex = layerBase->serverIndex(); + if (serverIndex >= 0) { + mLayerMap.removeItem(serverIndex); } return NO_ERROR; } @@ -1298,7 +1296,7 @@ sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked( format = PIXEL_FORMAT_RGBA_8888; break; case PIXEL_FORMAT_OPAQUE: - format = PIXEL_FORMAT_RGB_565; + format = PIXEL_FORMAT_RGBX_8888; break; } @@ -1307,6 +1305,7 @@ sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked( if (LIKELY(err == NO_ERROR)) { layer->initStates(w, h, flags); addLayer_l(layer); + addClientLayer_l(layer); } else { LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err)); layer.clear(); @@ -1321,6 +1320,7 @@ sp<LayerBaseClient> SurfaceFlinger::createBlurSurfaceLocked( sp<LayerBlur> layer = new LayerBlur(this, display, client, id); layer->initStates(w, h, flags); addLayer_l(layer); + addClientLayer_l(layer); return layer; } @@ -1331,6 +1331,7 @@ sp<LayerBaseClient> SurfaceFlinger::createDimSurfaceLocked( sp<LayerDim> layer = new LayerDim(this, display, client, id); layer->initStates(w, h, flags); addLayer_l(layer); + addClientLayer_l(layer); return layer; } @@ -1341,6 +1342,7 @@ sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurfaceLocked( sp<LayerBuffer> layer = new LayerBuffer(this, display, client, id); layer->initStates(w, h, flags); addLayer_l(layer); + addClientLayer_l(layer); return layer; } @@ -1512,83 +1514,17 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) result.append(buffer); } - size_t s = mClientsMap.size(); - char name[64]; - for (size_t i=0 ; i<s ; i++) { - sp<Client> client = mClientsMap.valueAt(i); - sprintf(name, " Client (id=0x%08x)", client->cid); - client->dump(name); - } const LayerVector& currentLayers = mCurrentState.layersSortedByZ; const size_t count = currentLayers.size(); for (size_t i=0 ; i<count ; i++) { - /*** LayerBase ***/ - const sp<LayerBase>& layer = currentLayers[i]; - const Layer::State& s = layer->drawingState(); - snprintf(buffer, SIZE, - "+ %s %p\n" - " " - "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), " - "needsBlending=%1d, needsDithering=%1d, invalidate=%1d, " - "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n", - layer->getTypeID(), layer.get(), - s.z, layer->tx(), layer->ty(), s.w, s.h, - layer->needsBlending(), layer->needsDithering(), - layer->contentDirty, - s.alpha, s.flags, - s.transform[0][0], s.transform[0][1], - s.transform[1][0], s.transform[1][1]); - result.append(buffer); - buffer[0] = 0; - /*** LayerBaseClient ***/ - sp<LayerBaseClient> lbc = - LayerBase::dynamicCast< LayerBaseClient* >(layer.get()); - if (lbc != 0) { - sp<Client> client(lbc->client.promote()); - snprintf(buffer, SIZE, - " name=%s\n", lbc->getName().string()); - result.append(buffer); - snprintf(buffer, SIZE, - " id=0x%08x, client=0x%08x, identity=%u\n", - lbc->clientIndex(), client.get() ? client->cid : 0, - lbc->getIdentity()); - - result.append(buffer); - buffer[0] = 0; - } - /*** Layer ***/ - sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get()); - if (l != 0) { - SharedBufferStack::Statistics stats = l->lcblk->getStats(); - result.append( l->lcblk->dump(" ") ); - sp<const GraphicBuffer> buf0(l->getBuffer(0)); - sp<const GraphicBuffer> buf1(l->getBuffer(1)); - uint32_t w0=0, h0=0, s0=0; - uint32_t w1=0, h1=0, s1=0; - if (buf0 != 0) { - w0 = buf0->getWidth(); - h0 = buf0->getHeight(); - s0 = buf0->getStride(); - } - if (buf1 != 0) { - w1 = buf1->getWidth(); - h1 = buf1->getHeight(); - s1 = buf1->getStride(); - } - snprintf(buffer, SIZE, - " " - "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u]," - " freezeLock=%p, dq-q-time=%u us\n", - l->pixelFormat(), - w0, h0, s0, w1, h1, s1, - l->getFreezeLock().get(), stats.totalTime); - result.append(buffer); - buffer[0] = 0; - } + const sp<LayerBase>& layer(currentLayers[i]); + layer->dump(result, buffer, SIZE); + const Layer::State& s(layer->drawingState()); s.transparentRegion.dump(result, "transparentRegion"); layer->transparentRegionScreen.dump(result, "transparentRegionScreen"); layer->visibleRegionScreen.dump(result, "visibleRegionScreen"); } + mWormholeRegion.dump(result, "WormholeRegion"); const DisplayHardware& hw(graphicPlane(0).displayHardware()); snprintf(buffer, SIZE, @@ -1601,16 +1537,19 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) " last transaction time : %f us\n", mLastSwapBufferTime/1000.0, mLastTransactionTime/1000.0); result.append(buffer); + if (inSwapBuffersDuration || !locked) { snprintf(buffer, SIZE, " eglSwapBuffers time: %f us\n", inSwapBuffersDuration/1000.0); result.append(buffer); } + if (inTransactionDuration || !locked) { snprintf(buffer, SIZE, " transaction time: %f us\n", inTransactionDuration/1000.0); result.append(buffer); } + snprintf(buffer, SIZE, " client count: %d\n", mClientsMap.size()); result.append(buffer); const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get()); @@ -1773,10 +1712,6 @@ sp<LayerBaseClient> Client::getLayerUser(int32_t i) const { return lbc; } -void Client::dump(const char* what) -{ -} - // --------------------------------------------------------------------------- #if 0 #pragma mark - diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h index d75dc15..9c8de51 100644 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ b/libs/surfaceflinger/SurfaceFlinger.h @@ -73,7 +73,6 @@ public: inline bool isValid(int32_t i) const; sp<LayerBaseClient> getLayerUser(int32_t i) const; - void dump(const char* what); const Vector< wp<LayerBaseClient> >& getLayers() const { return mLayers; @@ -281,6 +280,7 @@ private: void destroyConnection(ClientID cid); sp<LayerBaseClient> getLayerUser_l(SurfaceID index) const; status_t addLayer_l(const sp<LayerBase>& layer); + status_t addClientLayer_l(const sp<LayerBaseClient>& lbc); status_t removeLayer_l(const sp<LayerBase>& layer); status_t purgatorizeLayer_l(const sp<LayerBase>& layer); void free_resources_l(); diff --git a/libs/surfaceflinger/Transform.cpp b/libs/surfaceflinger/Transform.cpp index 175f989..5e27cc9 100644 --- a/libs/surfaceflinger/Transform.cpp +++ b/libs/surfaceflinger/Transform.cpp @@ -229,14 +229,13 @@ Transform::vec3 Transform::transform(const vec3& v) const { return r; } -void Transform::transform(fixed1616* point, int x, int y) const +void Transform::transform(float* point, int x, int y) const { - const float toFixed = 65536.0f; const mat33& M(mMatrix); vec2 v(x, y); v = transform(v); - point[0] = v[0] * toFixed; - point[1] = v[1] * toFixed; + point[0] = v[0]; + point[1] = v[1]; } Rect Transform::makeBounds(int w, int h) const diff --git a/libs/surfaceflinger/Transform.h b/libs/surfaceflinger/Transform.h index 2e5b893..20fa11a 100644 --- a/libs/surfaceflinger/Transform.h +++ b/libs/surfaceflinger/Transform.h @@ -37,8 +37,6 @@ public: explicit Transform(uint32_t orientation); ~Transform(); - typedef int32_t fixed1616; - // FIXME: must match OVERLAY_TRANSFORM_*, pull from hardware.h enum orientation_flags { ROT_0 = 0x00000000, @@ -76,7 +74,7 @@ public: // transform data Rect makeBounds(int w, int h) const; - void transform(fixed1616* point, int x, int y) const; + void transform(float* point, int x, int y) const; Region transform(const Region& reg) const; Transform operator * (const Transform& rhs) const; diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp index a17e8ac..c42cd53 100644 --- a/libs/surfaceflinger_client/SharedBufferStack.cpp +++ b/libs/surfaceflinger_client/SharedBufferStack.cpp @@ -67,19 +67,47 @@ void SharedBufferStack::init(int32_t i) identity = i; } +status_t SharedBufferStack::setCrop(int buffer, const Rect& crop) +{ + if (uint32_t(buffer) >= NUM_BUFFER_MAX) + return BAD_INDEX; + + buffers[buffer].crop.l = uint16_t(crop.left); + buffers[buffer].crop.t = uint16_t(crop.top); + buffers[buffer].crop.r = uint16_t(crop.right); + buffers[buffer].crop.b = uint16_t(crop.bottom); + return NO_ERROR; +} + status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty) { if (uint32_t(buffer) >= NUM_BUFFER_MAX) return BAD_INDEX; - // in the current implementation we only send a single rectangle - const Rect bounds(dirty.getBounds()); - FlatRegion& reg(dirtyRegion[buffer]); - reg.count = 1; - reg.rects[0] = uint16_t(bounds.left); - reg.rects[1] = uint16_t(bounds.top); - reg.rects[2] = uint16_t(bounds.right); - reg.rects[3] = uint16_t(bounds.bottom); + FlatRegion& reg(buffers[buffer].dirtyRegion); + if (dirty.isEmpty()) { + reg.count = 0; + return NO_ERROR; + } + + size_t count; + Rect const* r = dirty.getArray(&count); + if (count > FlatRegion::NUM_RECT_MAX) { + const Rect bounds(dirty.getBounds()); + reg.count = 1; + reg.rects[0].l = uint16_t(bounds.left); + reg.rects[0].t = uint16_t(bounds.top); + reg.rects[0].r = uint16_t(bounds.right); + reg.rects[0].b = uint16_t(bounds.bottom); + } else { + reg.count = count; + for (size_t i=0 ; i<count ; i++) { + reg.rects[i].l = uint16_t(r[i].left); + reg.rects[i].t = uint16_t(r[i].top); + reg.rects[i].r = uint16_t(r[i].right); + reg.rects[i].b = uint16_t(r[i].bottom); + } + } return NO_ERROR; } @@ -89,8 +117,27 @@ Region SharedBufferStack::getDirtyRegion(int buffer) const if (uint32_t(buffer) >= NUM_BUFFER_MAX) return res; - const FlatRegion& reg(dirtyRegion[buffer]); - res.set(Rect(reg.rects[0], reg.rects[1], reg.rects[2], reg.rects[3])); + const FlatRegion& reg(buffers[buffer].dirtyRegion); + if (reg.count > FlatRegion::NUM_RECT_MAX) + return res; + + if (reg.count == 1) { + const Rect r( + reg.rects[0].l, + reg.rects[0].t, + reg.rects[0].r, + reg.rects[0].b); + res.set(r); + } else { + for (size_t i=0 ; i<reg.count ; i++) { + const Rect r( + reg.rects[i].l, + reg.rects[i].t, + reg.rects[i].r, + reg.rects[i].b); + res.orSelf(r); + } + } return res; } @@ -132,7 +179,7 @@ String8 SharedBufferBase::dump(char const* prefix) const char buffer[SIZE]; String8 result; SharedBufferStack& stack( *mSharedStack ); - int tail = (mNumBuffers + stack.head - stack.available + 1) % mNumBuffers; + int tail = computeTail(); snprintf(buffer, SIZE, "%s[ head=%2d, available=%2d, queued=%2d, tail=%2d ] " "reallocMask=%08x, inUse=%2d, identity=%d, status=%d\n", @@ -142,6 +189,48 @@ String8 SharedBufferBase::dump(char const* prefix) const return result; } +int32_t SharedBufferBase::computeTail() const +{ + SharedBufferStack& stack( *mSharedStack ); + return (mNumBuffers + stack.head - stack.available + 1) % mNumBuffers; +} + +status_t SharedBufferBase::waitForCondition(const ConditionBase& condition) +{ + const SharedBufferStack& stack( *mSharedStack ); + SharedClient& client( *mSharedClient ); + const nsecs_t TIMEOUT = s2ns(1); + const int identity = mIdentity; + + Mutex::Autolock _l(client.lock); + while ((condition()==false) && + (stack.identity == identity) && + (stack.status == NO_ERROR)) + { + status_t err = client.cv.waitRelative(client.lock, TIMEOUT); + // handle errors and timeouts + if (CC_UNLIKELY(err != NO_ERROR)) { + if (err == TIMED_OUT) { + if (condition()) { + LOGE("waitForCondition(%s) timed out (identity=%d), " + "but condition is true! We recovered but it " + "shouldn't happen." , condition.name(), stack.identity); + break; + } else { + LOGW("waitForCondition(%s) timed out " + "(identity=%d, status=%d). " + "CPU may be pegged. trying again.", condition.name(), + stack.identity, stack.status); + } + } else { + LOGE("waitForCondition(%s) error (%s) ", + condition.name(), strerror(-err)); + return err; + } + } + } + return (stack.identity != mIdentity) ? status_t(BAD_INDEX) : stack.status; +} // ============================================================================ // conditions and updates // ============================================================================ @@ -149,24 +238,34 @@ String8 SharedBufferBase::dump(char const* prefix) const SharedBufferClient::DequeueCondition::DequeueCondition( SharedBufferClient* sbc) : ConditionBase(sbc) { } -bool SharedBufferClient::DequeueCondition::operator()() { +bool SharedBufferClient::DequeueCondition::operator()() const { return stack.available > 0; } SharedBufferClient::LockCondition::LockCondition( SharedBufferClient* sbc, int buf) : ConditionBase(sbc), buf(buf) { } -bool SharedBufferClient::LockCondition::operator()() { - return (buf != stack.head || +bool SharedBufferClient::LockCondition::operator()() const { + // NOTE: if stack.head is messed up, we could crash the client + // or cause some drawing artifacts. This is okay, as long as it is + // limited to the client. + return (buf != stack.index[stack.head] || (stack.queued > 0 && stack.inUse != buf)); } SharedBufferServer::ReallocateCondition::ReallocateCondition( SharedBufferBase* sbb, int buf) : ConditionBase(sbb), buf(buf) { } -bool SharedBufferServer::ReallocateCondition::operator()() { +bool SharedBufferServer::ReallocateCondition::operator()() const { + int32_t head = stack.head; + if (uint32_t(head) >= NUM_BUFFER_MAX) { + // if stack.head is messed up, we cannot allow the server to + // crash (since stack.head is mapped on the client side) + stack.status = BAD_VALUE; + return false; + } // TODO: we should also check that buf has been dequeued - return (buf != stack.head); + return (buf != stack.index[head]); } // ---------------------------------------------------------------------------- @@ -208,9 +307,11 @@ SharedBufferServer::RetireUpdate::RetireUpdate( ssize_t SharedBufferServer::RetireUpdate::operator()() { // head is only written in this function, which is single-thread. int32_t head = stack.head; + if (uint32_t(head) >= NUM_BUFFER_MAX) + return BAD_VALUE; // Preventively lock the current buffer before updating queued. - android_atomic_write(head, &stack.inUse); + android_atomic_write(stack.index[head], &stack.inUse); // Decrement the number of queued buffers int32_t queued; @@ -226,7 +327,7 @@ ssize_t SharedBufferServer::RetireUpdate::operator()() { // lock the buffer before advancing head, which automatically unlocks // the buffer we preventively locked upon entering this function - android_atomic_write(head, &stack.inUse); + android_atomic_write(stack.index[head], &stack.inUse); // advance head android_atomic_write(head, &stack.head); @@ -250,37 +351,19 @@ ssize_t SharedBufferServer::StatusUpdate::operator()() { SharedBufferClient::SharedBufferClient(SharedClient* sharedClient, int surface, int num, int32_t identity) - : SharedBufferBase(sharedClient, surface, num, identity), tail(0) -{ - tail = computeTail(); -} - -int32_t SharedBufferClient::computeTail() const + : SharedBufferBase(sharedClient, surface, num, identity), + tail(0), undoDequeueTail(0) { SharedBufferStack& stack( *mSharedStack ); - // we need to make sure we read available and head coherently, - // w.r.t RetireUpdate. - int32_t newTail; - int32_t avail; - int32_t head; - do { - avail = stack.available; - head = stack.head; - } while (stack.available != avail); - newTail = head - avail + 1; - if (newTail < 0) { - newTail += mNumBuffers; - } else if (newTail >= mNumBuffers) { - newTail -= mNumBuffers; - } - return newTail; + tail = computeTail(); + queued_head = stack.head; } ssize_t SharedBufferClient::dequeue() { SharedBufferStack& stack( *mSharedStack ); - if (stack.head == tail && stack.available == 2) { + if (stack.head == tail && stack.available == mNumBuffers) { LOGW("dequeue: tail=%d, head=%d, avail=%d, queued=%d", tail, stack.head, stack.available, stack.queued); } @@ -301,9 +384,10 @@ ssize_t SharedBufferClient::dequeue() LOGW("dequeue probably called from multiple threads!"); } - int dequeued = tail; + undoDequeueTail = tail; + int dequeued = stack.index[tail]; tail = ((tail+1 >= mNumBuffers) ? 0 : tail+1); - LOGD_IF(DEBUG_ATOMICS, "dequeued=%d, tail=%d, %s", + LOGD_IF(DEBUG_ATOMICS, "dequeued=%d, tail++=%d, %s", dequeued, tail, dump("").string()); mDequeueTime[dequeued] = dequeueTime; @@ -313,16 +397,19 @@ ssize_t SharedBufferClient::dequeue() status_t SharedBufferClient::undoDequeue(int buf) { + // TODO: we can only undo the previous dequeue, we should + // enforce that in the api UndoDequeueUpdate update(this); status_t err = updateCondition( update ); if (err == NO_ERROR) { - tail = computeTail(); + tail = undoDequeueTail; } return err; } status_t SharedBufferClient::lock(int buf) { + SharedBufferStack& stack( *mSharedStack ); LockCondition condition(this, buf); status_t err = waitForCondition(condition); return err; @@ -330,26 +417,37 @@ status_t SharedBufferClient::lock(int buf) status_t SharedBufferClient::queue(int buf) { + SharedBufferStack& stack( *mSharedStack ); + + queued_head = ((queued_head+1 >= mNumBuffers) ? 0 : queued_head+1); + stack.index[queued_head] = buf; + QueueUpdate update(this); status_t err = updateCondition( update ); LOGD_IF(DEBUG_ATOMICS, "queued=%d, %s", buf, dump("").string()); - SharedBufferStack& stack( *mSharedStack ); + const nsecs_t now = systemTime(SYSTEM_TIME_THREAD); stack.stats.totalTime = ns2us(now - mDequeueTime[buf]); return err; } -bool SharedBufferClient::needNewBuffer(int buffer) const +bool SharedBufferClient::needNewBuffer(int buf) const { SharedBufferStack& stack( *mSharedStack ); - const uint32_t mask = 1<<buffer; + const uint32_t mask = 1<<buf; return (android_atomic_and(~mask, &stack.reallocMask) & mask) != 0; } -status_t SharedBufferClient::setDirtyRegion(int buffer, const Region& reg) +status_t SharedBufferClient::setCrop(int buf, const Rect& crop) { SharedBufferStack& stack( *mSharedStack ); - return stack.setDirtyRegion(buffer, reg); + return stack.setCrop(buf, crop); +} + +status_t SharedBufferClient::setDirtyRegion(int buf, const Region& reg) +{ + SharedBufferStack& stack( *mSharedStack ); + return stack.setDirtyRegion(buf, reg); } // ---------------------------------------------------------------------------- @@ -363,20 +461,30 @@ SharedBufferServer::SharedBufferServer(SharedClient* sharedClient, mSharedStack->available = num; mSharedStack->queued = 0; mSharedStack->reallocMask = 0; - memset(mSharedStack->dirtyRegion, 0, sizeof(mSharedStack->dirtyRegion)); + memset(mSharedStack->buffers, 0, sizeof(mSharedStack->buffers)); + for (int i=0 ; i<num ; i++) { + mSharedStack->index[i] = i; + } } ssize_t SharedBufferServer::retireAndLock() { RetireUpdate update(this, mNumBuffers); ssize_t buf = updateCondition( update ); - LOGD_IF(DEBUG_ATOMICS && buf>=0, "retire=%d, %s", int(buf), dump("").string()); + if (buf >= 0) { + if (uint32_t(buf) >= NUM_BUFFER_MAX) + return BAD_VALUE; + SharedBufferStack& stack( *mSharedStack ); + buf = stack.index[buf]; + LOGD_IF(DEBUG_ATOMICS && buf>=0, "retire=%d, %s", + int(buf), dump("").string()); + } return buf; } -status_t SharedBufferServer::unlock(int buffer) +status_t SharedBufferServer::unlock(int buf) { - UnlockUpdate update(this, buffer); + UnlockUpdate update(this, buf); status_t err = updateCondition( update ); return err; } @@ -403,17 +511,17 @@ int32_t SharedBufferServer::getQueuedCount() const return stack.queued; } -status_t SharedBufferServer::assertReallocate(int buffer) +status_t SharedBufferServer::assertReallocate(int buf) { - ReallocateCondition condition(this, buffer); + ReallocateCondition condition(this, buf); status_t err = waitForCondition(condition); return err; } -Region SharedBufferServer::getDirtyRegion(int buffer) const +Region SharedBufferServer::getDirtyRegion(int buf) const { SharedBufferStack& stack( *mSharedStack ); - return stack.getDirtyRegion(buffer); + return stack.getDirtyRegion(buf); } SharedBufferStack::Statistics SharedBufferServer::getStats() const diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp index 5dd75c3..eee4dae 100644 --- a/libs/surfaceflinger_client/Surface.cpp +++ b/libs/surfaceflinger_client/Surface.cpp @@ -17,8 +17,6 @@ #define LOG_TAG "Surface" #include <stdint.h> -#include <unistd.h> -#include <fcntl.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> @@ -28,8 +26,6 @@ #include <utils/CallStack.h> #include <utils/Log.h> -#include <pixelflinger/pixelflinger.h> - #include <binder/IPCThreadState.h> #include <binder/IMemory.h> @@ -55,6 +51,8 @@ static status_t copyBlt( 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); @@ -67,7 +65,6 @@ static status_t copyBlt( Region::const_iterator head(reg.begin()); Region::const_iterator tail(reg.end()); if (head != tail && src_bits && dst_bits) { - // NOTE: dst and src must be the same format const size_t bpp = bytesPerPixel(src->format); const size_t dbpr = dst->stride * bpp; const size_t sbpr = src->stride * bpp; @@ -354,7 +351,6 @@ void Surface::init() // be default we request a hardware surface mUsage = GRALLOC_USAGE_HW_RENDER; mConnected = 0; - mNeedFullUpdate = false; } Surface::~Surface() @@ -467,18 +463,6 @@ int Surface::perform(android_native_window_t* window, // ---------------------------------------------------------------------------- -status_t Surface::dequeueBuffer(sp<GraphicBuffer>* buffer) { - android_native_buffer_t* out; - status_t err = dequeueBuffer(&out); - if (err == NO_ERROR) { - *buffer = GraphicBuffer::getSelf(out); - } - return err; -} - -// ---------------------------------------------------------------------------- - - int Surface::dequeueBuffer(android_native_buffer_t** buffer) { sp<SurfaceComposerClient> client(getClient()); @@ -495,9 +479,12 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer) // below we make sure we AT LEAST have the usage flags we want const uint32_t usage(getUsage()); const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]); + + // Always call needNewBuffer(), since it clears the needed buffers flags + bool needNewBuffer = mSharedBufferClient->needNewBuffer(bufIdx); if (backBuffer == 0 || ((uint32_t(backBuffer->usage) & usage) != usage) || - mSharedBufferClient->needNewBuffer(bufIdx)) + needNewBuffer) { err = getBufferLocked(bufIdx, usage); LOGE_IF(err, "getBufferLocked(%ld, %08x) failed (%s)", @@ -531,7 +518,7 @@ int Surface::lockBuffer(android_native_buffer_t* buffer) if (err != NO_ERROR) return err; - int32_t bufIdx = GraphicBuffer::getSelf(buffer)->getIndex(); + int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer)); err = mSharedBufferClient->lock(bufIdx); LOGE_IF(err, "error locking buffer %d (%s)", bufIdx, strerror(-err)); return err; @@ -548,7 +535,8 @@ int Surface::queueBuffer(android_native_buffer_t* buffer) mDirtyRegion.set(mSwapRectangle); } - int32_t bufIdx = GraphicBuffer::getSelf(buffer)->getIndex(); + int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer)); + mSharedBufferClient->setCrop(bufIdx, mNextBufferCrop); mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion); err = mSharedBufferClient->queue(bufIdx); LOGE_IF(err, "error queuing buffer %d (%s)", bufIdx, strerror(-err)); @@ -578,6 +566,10 @@ int Surface::query(int what, int* value) int Surface::perform(int operation, va_list args) { + status_t err = validate(); + if (err != NO_ERROR) + return err; + int res = NO_ERROR; switch (operation) { case NATIVE_WINDOW_SET_USAGE: @@ -589,6 +581,9 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_DISCONNECT: res = dispatch_disconnect( args ); break; + case NATIVE_WINDOW_SET_CROP: + res = dispatch_crop( args ); + break; default: res = NAME_NOT_FOUND; break; @@ -608,6 +603,10 @@ int Surface::dispatch_disconnect(va_list args) { int api = va_arg(args, int); return disconnect( api ); } +int Surface::dispatch_crop(va_list args) { + android_native_rect_t const* rect = va_arg(args, android_native_rect_t*); + return crop( reinterpret_cast<Rect const*>(rect) ); +} void Surface::setUsage(uint32_t reqUsage) @@ -666,6 +665,14 @@ int Surface::getConnectedApi() const return mConnected; } +int Surface::crop(Rect const* rect) +{ + Mutex::Autolock _l(mSurfaceLock); + // TODO: validate rect size + mNextBufferCrop = *rect; + return NO_ERROR; +} + // ---------------------------------------------------------------------------- @@ -703,45 +710,47 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) // we're intending to do software rendering from this point setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); - sp<GraphicBuffer> backBuffer; - status_t err = dequeueBuffer(&backBuffer); + android_native_buffer_t* out; + status_t err = dequeueBuffer(&out); LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err)); if (err == NO_ERROR) { + sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out)); err = lockBuffer(backBuffer.get()); LOGE_IF(err, "lockBuffer (idx=%d) failed (%s)", - backBuffer->getIndex(), strerror(-err)); + getBufferIndex(backBuffer), strerror(-err)); if (err == NO_ERROR) { - // we handle copy-back here... - const Rect bounds(backBuffer->width, backBuffer->height); - Region scratch(bounds); + const Region boundsRegion(bounds); + Region scratch(boundsRegion); Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch); + newDirtyRegion &= boundsRegion; - if (mNeedFullUpdate) { - // reset newDirtyRegion to bounds when a buffer is reallocated - // it would be better if this information was associated with - // the buffer and made available to outside of Surface. - // This will do for now though. - mNeedFullUpdate = false; - newDirtyRegion.set(bounds); - } else { - newDirtyRegion.andSelf(bounds); - } - + // figure out if we can copy the frontbuffer back const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); - if (frontBuffer !=0 && - backBuffer->width == frontBuffer->width && - backBuffer->height == frontBuffer->height && - !(mFlags & ISurfaceComposer::eDestroyBackbuffer)) - { + 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() && frontBuffer!=0) { - // copy front to back + 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; } - mDirtyRegion = newDirtyRegion; + // keep track of the are of the buffer that is "clean" + // (ie: that will be redrawn) mOldDirtyRegion = newDirtyRegion; void* vaddr; @@ -777,7 +786,7 @@ status_t Surface::unlockAndPost() err = queueBuffer(mLockedBuffer.get()); LOGE_IF(err, "queueBuffer (idx=%d) failed (%s)", - mLockedBuffer->getIndex(), strerror(-err)); + getBufferIndex(mLockedBuffer), strerror(-err)); mPostedBuffer = mLockedBuffer; mLockedBuffer = 0; @@ -789,6 +798,11 @@ void Surface::setSwapRectangle(const Rect& r) { mSwapRectangle = r; } +int Surface::getBufferIndex(const sp<GraphicBuffer>& buffer) const +{ + return buffer->getIndex(); +} + status_t Surface::getBufferLocked(int index, int usage) { sp<ISurface> s(mSurface); @@ -820,7 +834,6 @@ status_t Surface::getBufferLocked(int index, int usage) if (err == NO_ERROR) { currentBuffer = buffer; currentBuffer->setIndex(index); - mNeedFullUpdate = true; } } else { err = err<0 ? err : NO_MEMORY; diff --git a/libs/surfaceflinger_client/tests/Android.mk b/libs/surfaceflinger_client/tests/Android.mk new file mode 100644 index 0000000..5053e7d --- /dev/null +++ b/libs/surfaceflinger_client/tests/Android.mk @@ -0,0 +1 @@ +include $(call all-subdir-makefiles) diff --git a/libs/surfaceflinger_client/tests/SharedBufferStack/Android.mk b/libs/surfaceflinger_client/tests/SharedBufferStack/Android.mk new file mode 100644 index 0000000..d3dfe04 --- /dev/null +++ b/libs/surfaceflinger_client/tests/SharedBufferStack/Android.mk @@ -0,0 +1,17 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + SharedBufferStackTest.cpp + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libutils \ + libui \ + libsurfaceflinger_client + +LOCAL_MODULE:= test-sharedbufferstack + +LOCAL_MODULE_TAGS := tests + +include $(BUILD_EXECUTABLE) diff --git a/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp b/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp new file mode 100644 index 0000000..6732580 --- /dev/null +++ b/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef NDEBUG + +#include <assert.h> +#include <cutils/memory.h> +#include <cutils/log.h> +#include <utils/Errors.h> +#include <private/surfaceflinger/SharedBufferStack.h> + +using namespace android; + + +void log(const char* prefix, int *b, size_t num) +{ + printf("%s: ", prefix); + for (size_t i=0 ; i<num ; i++) { + printf("%d ", b[i]); + } + printf("\n"); +} + +int main(int argc, char** argv) +{ + status_t err; + const size_t num = 4; + SharedClient client; + SharedBufferServer s(&client, 0, num, 0); + SharedBufferClient c(&client, 0, num, 0); + int b[num], u[num], r[num]; + + for (size_t i=0 ; i<num ; i++) { + b[i] = c.dequeue(); + assert(b[i]==i); + } + log("DQ", b, num); + + for (size_t i=0 ; i<num-1 ; i++) { + err = c.lock(b[i]); + assert(err==0); + } + log("LK", b, num-1); + + for (size_t i=0 ; i<num-1 ; i++) { + err = c.queue(b[i]); + assert(err==0); + } + log(" Q", b, num-1); + + + for (size_t i=0 ; i<num-1 ; i++) { + r[i] = s.retireAndLock(); + assert(r[i]==i); + err = s.unlock(r[i]); + assert(err == 0); + } + log("RT", r, num-1); + + err = c.lock(b[num-1]); + assert(err == 0); + log("LK", b+num-1, 1); + + err = c.queue(b[num-1]); + assert(err == 0); + log(" Q", b+num-1, 1); + + r[num-1] = s.retireAndLock(); + assert(r[num-1]==num-1); + err = s.unlock(r[num-1]); + assert(err == 0); + log("RT", r+num-1, 1); + + // ------------------------------------ + printf("\n"); + + for (size_t i=0 ; i<num ; i++) { + b[i] = c.dequeue(); + assert(b[i]==i); + } + log("DQ", b, num); + + for (size_t i=0 ; i<num-1 ; i++) { + err = c.lock(b[i]); + assert(err==0); + } + log("LK", b, num-1); + + for (size_t i=0 ; i<num-1 ; i++) { + u[i] = b[num-2-i]; + } + u[num-1] = num-1; + + for (size_t i=0 ; i<num-1 ; i++) { + err = c.queue(u[i]); + assert(err==0); + } + log(" Q", u, num-1); + + for (size_t i=0 ; i<num-1 ; i++) { + r[i] = s.retireAndLock(); + assert(r[i]==u[i]); + err = s.unlock(r[i]); + assert(err == 0); + } + log("RT", r, num-1); + + err = c.lock(b[num-1]); + assert(err == 0); + log("LK", b+num-1, 1); + + err = c.queue(b[num-1]); + assert(err == 0); + log(" Q", b+num-1, 1); + + r[num-1] = s.retireAndLock(); + assert(r[num-1]==num-1); + err = s.unlock(r[num-1]); + assert(err == 0); + log("RT", r+num-1, 1); + + // ------------------------------------ + printf("\n"); + + for (size_t i=0 ; i<num ; i++) { + b[i] = c.dequeue(); + assert(b[i]==u[i]); + } + log("DQ", b, num); + + for (size_t i=0 ; i<num-1 ; i++) { + err = c.lock(b[i]); + assert(err==0); + } + log("LK", b, num-1); + + for (size_t i=0 ; i<num-1 ; i++) { + err = c.queue(b[i]); + assert(err==0); + } + log(" Q", b, num-1); + + for (size_t i=0 ; i<num-1 ; i++) { + r[i] = s.retireAndLock(); + assert(r[i]==u[i]); + err = s.unlock(r[i]); + assert(err == 0); + } + log("RT", r, num-1); + + err = c.lock(u[num-1]); + assert(err == 0); + log("LK", u+num-1, 1); + + err = c.queue(u[num-1]); + assert(err == 0); + log(" Q", u+num-1, 1); + + r[num-1] = s.retireAndLock(); + assert(r[num-1]==num-1); + err = s.unlock(r[num-1]); + assert(err == 0); + log("RT", r+num-1, 1); + + // ------------------------------------ + printf("\n"); + + b[0] = c.dequeue(); + assert(b[0]==u[0]); + log("DQ", b, 1); + + c.undoDequeue(b[0]); + assert(err == 0); + log("UDQ", b, 1); + + // ------------------------------------ + printf("\n"); + + for (size_t i=0 ; i<num ; i++) { + b[i] = c.dequeue(); + assert(b[i]==u[i]); + } + log("DQ", b, num); + + for (size_t i=0 ; i<num-1 ; i++) { + err = c.lock(b[i]); + assert(err==0); + } + log("LK", b, num-1); + + for (size_t i=0 ; i<num-1 ; i++) { + err = c.queue(b[i]); + assert(err==0); + } + log(" Q", b, num-1); + + for (size_t i=0 ; i<num-1 ; i++) { + r[i] = s.retireAndLock(); + assert(r[i]==u[i]); + err = s.unlock(r[i]); + assert(err == 0); + } + log("RT", r, num-1); + + err = c.lock(u[num-1]); + assert(err == 0); + log("LK", u+num-1, 1); + + err = c.queue(u[num-1]); + assert(err == 0); + log(" Q", u+num-1, 1); + + r[num-1] = s.retireAndLock(); + assert(r[num-1]==num-1); + err = s.unlock(r[num-1]); + assert(err == 0); + log("RT", r+num-1, 1); + + return 0; +} diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp index 6ae7e74..d51664d 100644 --- a/libs/ui/GraphicBufferAllocator.cpp +++ b/libs/ui/GraphicBufferAllocator.cpp @@ -15,6 +15,8 @@ ** limitations under the License. */ +#define LOG_TAG "GraphicBufferAllocator" + #include <cutils/log.h> #include <utils/Singleton.h> @@ -61,9 +63,9 @@ void GraphicBufferAllocator::dump(String8& result) const const size_t c = list.size(); for (size_t i=0 ; i<c ; i++) { const alloc_rec_t& rec(list.valueAt(i)); - snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u x %4u | %2d | 0x%08x\n", + snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %2d | 0x%08x\n", list.keyAt(i), rec.size/1024.0f, - rec.w, rec.h, rec.format, rec.usage); + rec.w, rec.s, rec.h, rec.format, rec.usage); result.append(buffer); total += rec.size; } @@ -71,16 +73,13 @@ void GraphicBufferAllocator::dump(String8& result) const result.append(buffer); } -static inline uint32_t clamp(uint32_t c) { - return c>0 ? c : 1; -} - status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, int usage, buffer_handle_t* handle, int32_t* stride) { - // make sure to not allocate a 0 x 0 buffer - w = clamp(w); - h = clamp(h); + // make sure to not allocate a N x 0 or 0 x N buffer, since this is + // allowed from an API stand-point allocate a 1x1 buffer instead. + if (!w || !h) + w = h = 1; // we have a h/w allocator and h/w buffer is requested status_t err; @@ -100,9 +99,9 @@ status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat forma alloc_rec_t rec; rec.w = w; rec.h = h; + rec.s = *stride; rec.format = format; rec.usage = usage; - rec.vaddr = 0; rec.size = h * stride[0] * bytesPerPixel(format); list.add(*handle, rec); } else { diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp index 7e0f881..a1401ad 100644 --- a/libs/utils/ResourceTypes.cpp +++ b/libs/utils/ResourceTypes.cpp @@ -4178,6 +4178,9 @@ void ResTable::print(bool inclValues) const case ResTable_config::SCREENSIZE_LARGE: printf(" (large)"); break; + case ResTable_config::SCREENSIZE_XLARGE: + printf(" (xlarge)"); + break; } printf(" lng=%d", type->config.screenLayout&ResTable_config::MASK_SCREENLONG); |