diff options
| -rw-r--r-- | include/binder/IPCThreadState.h | 1 | ||||
| -rw-r--r-- | include/surfaceflinger/Surface.h | 2 | ||||
| -rw-r--r-- | include/utils/CallStack.h | 2 | ||||
| -rw-r--r-- | libs/binder/IPCThreadState.cpp | 10 | ||||
| -rw-r--r-- | libs/surfaceflinger_client/Surface.cpp | 12 | ||||
| -rw-r--r-- | opengl/tests/hwc/hwc_stress.cpp | 91 | ||||
| -rw-r--r-- | services/surfaceflinger/Android.mk | 1 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.cpp | 71 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.h | 5 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 9 |
10 files changed, 141 insertions, 63 deletions
diff --git a/include/binder/IPCThreadState.h b/include/binder/IPCThreadState.h index b54718f1a5..3378d97255 100644 --- a/include/binder/IPCThreadState.h +++ b/include/binder/IPCThreadState.h @@ -33,6 +33,7 @@ class IPCThreadState { public: static IPCThreadState* self(); + static IPCThreadState* selfOrNull(); // self(), but won't instantiate sp<ProcessState> process(); diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h index cef439c170..2df8ca3755 100644 --- a/include/surfaceflinger/Surface.h +++ b/include/surfaceflinger/Surface.h @@ -249,7 +249,7 @@ private: uint32_t *pWidth, uint32_t *pHeight, uint32_t *pFormat, uint32_t *pUsage) const; - static void cleanCachedSurfaces(); + static void cleanCachedSurfacesLocked(); class BufferInfo { uint32_t mWidth; diff --git a/include/utils/CallStack.h b/include/utils/CallStack.h index c2c8ce514b..8817120eff 100644 --- a/include/utils/CallStack.h +++ b/include/utils/CallStack.h @@ -50,7 +50,7 @@ public: void clear(); - void update(int32_t ignoreDepth=0, int32_t maxDepth=MAX_DEPTH); + void update(int32_t ignoreDepth=1, int32_t maxDepth=MAX_DEPTH); // Dump a stack trace to the log void dump(const char* prefix = 0) const; diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index 13c58f04fc..95cfddf758 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -318,6 +318,16 @@ restart: goto restart; } +IPCThreadState* IPCThreadState::selfOrNull() +{ + if (gHaveTLS) { + const pthread_key_t k = gTLS; + IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k); + return st; + } + return NULL; +} + void IPCThreadState::shutdown() { gShutdown = true; diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp index 9467a4cf0c..aa0c2e8b93 100644 --- a/libs/surfaceflinger_client/Surface.cpp +++ b/libs/surfaceflinger_client/Surface.cpp @@ -384,7 +384,7 @@ status_t Surface::writeToParcel( Mutex Surface::sCachedSurfacesLock; -DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces(wp<Surface>(0)); +DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces; sp<Surface> Surface::readFromParcel(const Parcel& data) { Mutex::Autolock _l(sCachedSurfacesLock); @@ -397,13 +397,13 @@ sp<Surface> Surface::readFromParcel(const Parcel& data) { if (surface->mSurface == 0) { surface = 0; } - cleanCachedSurfaces(); + cleanCachedSurfacesLocked(); return surface; } // Remove the stale entries from the surface cache. This should only be called // with sCachedSurfacesLock held. -void Surface::cleanCachedSurfaces() { +void Surface::cleanCachedSurfacesLocked() { for (int i = sCachedSurfaces.size()-1; i >= 0; --i) { wp<Surface> s(sCachedSurfaces.valueAt(i)); if (s == 0 || s.promote() == 0) { @@ -489,6 +489,9 @@ status_t Surface::validate() const LOGE("[Surface] using an invalid surface, " "identity=%u should be %d", mIdentity, identity); + CallStack stack; + stack.update(); + stack.dump("Surface"); return NO_INIT; } @@ -497,6 +500,9 @@ status_t Surface::validate() const if (err != NO_ERROR) { LOGE("surface (identity=%u) is invalid, err=%d (%s)", mIdentity, err, strerror(-err)); + CallStack stack; + stack.update(); + stack.dump("Surface"); return err; } diff --git a/opengl/tests/hwc/hwc_stress.cpp b/opengl/tests/hwc/hwc_stress.cpp index 35e53abfa7..580eb830cd 100644 --- a/opengl/tests/hwc/hwc_stress.cpp +++ b/opengl/tests/hwc/hwc_stress.cpp @@ -202,18 +202,19 @@ class YUVColor { }; // File scope constants -static const struct { +static const struct graphicFormat { unsigned int format; const char *desc; + unsigned int wMod, hMod; // Width/height mod this value must equal zero } graphicFormat[] = { - {HAL_PIXEL_FORMAT_RGBA_8888, "RGBA8888"}, - {HAL_PIXEL_FORMAT_RGBX_8888, "RGBX8888"}, - {HAL_PIXEL_FORMAT_RGB_888, "RGB888"}, - {HAL_PIXEL_FORMAT_RGB_565, "RGB565"}, - {HAL_PIXEL_FORMAT_BGRA_8888, "BGRA8888"}, - {HAL_PIXEL_FORMAT_RGBA_5551, "RGBA5551"}, - {HAL_PIXEL_FORMAT_RGBA_4444, "RGBA4444"}, - {HAL_PIXEL_FORMAT_YV12, "YV12"}, + {HAL_PIXEL_FORMAT_RGBA_8888, "RGBA8888", 1, 1}, + {HAL_PIXEL_FORMAT_RGBX_8888, "RGBX8888", 1, 1}, + {HAL_PIXEL_FORMAT_RGB_888, "RGB888", 1, 1}, + {HAL_PIXEL_FORMAT_RGB_565, "RGB565", 1, 1}, + {HAL_PIXEL_FORMAT_BGRA_8888, "BGRA8888", 1, 1}, + {HAL_PIXEL_FORMAT_RGBA_5551, "RGBA5551", 1, 1}, + {HAL_PIXEL_FORMAT_RGBA_4444, "RGBA4444", 1, 1}, + {HAL_PIXEL_FORMAT_YV12, "YV12", 2, 2}, }; const unsigned int blendingOps[] = { HWC_BLENDING_NONE, @@ -478,7 +479,7 @@ main(int argc, char *argv[]) exit(20); } - // Prandomly select a subset of frames to be used by this pass. + // Prandomly select a subset of frames to be used by this pass. vector <vector <sp<GraphicBuffer> > > selectedFrames; selectedFrames = vectorRandSelect(frames, list->numHwLayers); @@ -749,7 +750,6 @@ static void fillColor(GraphicBuffer *gBuf, RGBColor color, float trans) { unsigned char* buf = NULL; status_t err; - unsigned int numPixels = gBuf->getWidth() * gBuf->getHeight(); uint32_t pixel; // RGB 2 YUV conversion ratios @@ -835,9 +835,16 @@ static void fillColor(GraphicBuffer *gBuf, RGBColor color, float trans) exit(51); } - for (unsigned int n1 = 0; n1 < numPixels; n1++) { - memmove(buf, &pixel, attrib->bytes); - buf += attrib->bytes; + for (unsigned int row = 0; row < gBuf->getHeight(); row++) { + for (unsigned int col = 0; col < gBuf->getWidth(); col++) { + memmove(buf, &pixel, attrib->bytes); + buf += attrib->bytes; + } + for (unsigned int pad = 0; + pad < (gBuf->getStride() - gBuf->getWidth()) * attrib->bytes; + pad++) { + *buf++ = testRandMod(256); + } } err = gBuf->unlock(); @@ -856,14 +863,13 @@ static void fillColor(GraphicBuffer *gBuf, YUVColor color, float trans) const struct yuvAttrib { int format; - size_t padWidth; bool planar; unsigned int uSubSampX; unsigned int uSubSampY; unsigned int vSubSampX; unsigned int vSubSampY; } yuvAttributes[] = { - { HAL_PIXEL_FORMAT_YV12, 16, true, 2, 2, 2, 2}, + { HAL_PIXEL_FORMAT_YV12, true, 2, 2, 2, 2}, }; const struct yuvAttrib *attrib; @@ -879,12 +885,6 @@ static void fillColor(GraphicBuffer *gBuf, YUVColor color, float trans) assert(attrib->planar == true); // So far, only know how to handle planar - // If needed round width up to pad size - if (width % attrib->padWidth) { - width += attrib->padWidth - (width % attrib->padWidth); - } - assert((width % attrib->padWidth) == 0); - err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf)); if (err != 0) { testPrintE("fillColor lock failed: %d", err); @@ -892,23 +892,35 @@ static void fillColor(GraphicBuffer *gBuf, YUVColor color, float trans) } // Fill in Y component - for (unsigned int x = 0; x < width; x++) { - for (unsigned int y = 0; y < height; y++) { - *buf++ = (x < gBuf->getWidth()) ? (255 * color.y()) : 0; + for (unsigned int row = 0; row < height; row++) { + for (unsigned int col = 0; col < width; col++) { + *buf++ = 255 * color.y(); + } + for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth(); + pad++) { + *buf++ = testRandMod(256); } } // Fill in U component - for (unsigned int x = 0; x < width; x += attrib->uSubSampX) { - for (unsigned int y = 0; y < height; y += attrib->uSubSampY) { - *buf++ = (x < gBuf->getWidth()) ? (255 * color.u()) : 0; + for (unsigned int row = 0; row < height; row += attrib->uSubSampY) { + for (unsigned int col = 0; col < width; col += attrib->uSubSampX) { + *buf++ = 255 * color.u(); + } + for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth(); + pad += attrib->uSubSampX) { + *buf++ = testRandMod(256); } } // Fill in V component - for (unsigned int x = 0; x < width; x += attrib->vSubSampX) { - for (unsigned int y = 0; y < height; y += attrib->vSubSampY) { - *buf++ = (x < gBuf->getWidth()) ? (255 * color.v()) : 0; + for (unsigned int row = 0; row < height; row += attrib->vSubSampY) { + for (unsigned int col = 0; col < width; col += attrib->vSubSampX) { + *buf++ = 255 * color.v(); + } + for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth(); + pad += attrib->vSubSampX) { + *buf++ = testRandMod(256); } } @@ -989,7 +1001,7 @@ void init(void) eglQuerySurface(dpy, surface, EGL_HEIGHT, &height); checkEglError("eglQuerySurface"); - fprintf(stderr, "Window dimensions: %d x %d", width, height); + testPrintI("Window dimensions: %d x %d", width, height); printGLString("Version", GL_VERSION); printGLString("Vendor", GL_VENDOR); @@ -1017,7 +1029,7 @@ void init(void) * * Creates an array of graphic buffers, within the global variable * named frames. The graphic buffers are contained within a vector of - * verctors. All the graphic buffers in a particular row are of the same + * vectors. All the graphic buffers in a particular row are of the same * format and dimension. Each graphic buffer is uniformly filled with a * prandomly selected color. It is likely that each buffer, even * in the same row, will be filled with a unique color. @@ -1039,11 +1051,22 @@ void initFrames(unsigned int seed) for (unsigned int row = 0; row < rows; row++) { // All frames within a row have to have the same format and // dimensions. Width and height need to be >= 1. - int format = graphicFormat[testRandMod(NUMA(graphicFormat))].format; + unsigned int formatIdx = testRandMod(NUMA(graphicFormat)); + const struct graphicFormat *formatPtr = &graphicFormat[formatIdx]; + int format = formatPtr->format; + + // Pick width and height, which must be >= 1 and the size + // mod the wMod/hMod value must be equal to 0. size_t w = (width * maxSizeRatio) * testRandFract(); size_t h = (height * maxSizeRatio) * testRandFract(); w = max(1u, w); h = max(1u, h); + if ((w % formatPtr->wMod) != 0) { + w += formatPtr->wMod - (w % formatPtr->wMod); + } + if ((h % formatPtr->hMod) != 0) { + h += formatPtr->hMod - (h % formatPtr->hMod); + } if (verbose) { testPrintI(" frame %u width: %u height: %u format: %u %s", row, w, h, format, graphicFormat2str(format)); diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 74d1ac9f96..8a00a2ed57 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -35,7 +35,6 @@ endif LOCAL_SHARED_LIBRARIES := \ libcutils \ - libpixelflinger \ libhardware \ libutils \ libEGL \ diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 80aef5fcc2..fde68f6e07 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -83,8 +83,28 @@ status_t Layer::setToken(const sp<UserClient>& userClient, sharedClient, token, mBufferManager.getDefaultBufferCount(), getIdentity()); - status_t err = mUserClientRef.setToken(userClient, lcblk, token); + sp<UserClient> ourClient(mUserClientRef.getClient()); + + /* + * Here it is guaranteed that userClient != ourClient + * (see UserClient::getTokenForSurface()). + * + * We release the token used by this surface in ourClient below. + * This should be safe to do so now, since this layer won't be attached + * to this client, it should be okay to reuse that id. + * + * If this causes problems, an other solution would be to keep a list + * of all the {UserClient, token} ever used and release them when the + * Layer is destroyed. + * + */ + + if (ourClient != 0) { + ourClient->detachLayer(this); + } + + status_t err = mUserClientRef.setToken(userClient, lcblk, token); LOGE_IF(err != NO_ERROR, "ClientRef::setToken(%p, %p, %u) failed", userClient.get(), lcblk.get(), token); @@ -226,9 +246,10 @@ void Layer::setGeometry(hwc_layer_t* hwcl) void Layer::setPerFrameData(hwc_layer_t* hwcl) { sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer()); if (buffer == NULL) { - // this situation can happen if we ran out of memory for instance. - // not much we can do. continue to use whatever texture was bound - // to this context. + // this can happen if the client never drew into this layer yet, + // or if we ran out of memory. In that case, don't let + // HWC handle it. + hwcl->flags |= HWC_SKIP_LAYER; hwcl->handle = NULL; return; } @@ -561,12 +582,20 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) } // we retired a buffer, which becomes the new front buffer + + const bool noActiveBuffer = !mBufferManager.hasActiveBuffer(); if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) { LOGE("retireAndLock() buffer index (%d) out of range", int(buf)); mPostedDirtyRegion.clear(); return; } + if (noActiveBuffer) { + // we didn't have an active buffer, we need to recompute + // our visible region + recomputeVisibleRegions = true; + } + sp<GraphicBuffer> newFrontBuffer(getBuffer(buf)); if (newFrontBuffer != NULL) { // get the dirty region @@ -775,7 +804,7 @@ Layer::ClientRef::Access::~Access() Layer::BufferManager::BufferManager(TextureManager& tm) : mNumBuffers(NUM_BUFFERS), mTextureManager(tm), - mActiveBuffer(-1), mFailover(false) + mActiveBufferIndex(-1), mFailover(false) { } @@ -790,10 +819,10 @@ status_t Layer::BufferManager::resize(size_t size, if (size < mNumBuffers) { // Move the active texture into slot 0 - BufferData activeBufferData = mBufferData[mActiveBuffer]; - mBufferData[mActiveBuffer] = mBufferData[0]; + BufferData activeBufferData = mBufferData[mActiveBufferIndex]; + mBufferData[mActiveBufferIndex] = mBufferData[0]; mBufferData[0] = activeBufferData; - mActiveBuffer = 0; + mActiveBufferIndex = 0; // Free the buffers that are no longer needed. for (size_t i = size; i < mNumBuffers; i++) { @@ -839,33 +868,33 @@ sp<GraphicBuffer> Layer::BufferManager::getBuffer(size_t index) const { } status_t Layer::BufferManager::setActiveBufferIndex(size_t index) { - mActiveBuffer = index; + BufferData const * const buffers = mBufferData; + Mutex::Autolock _l(mLock); + mActiveBuffer = buffers[index].buffer; + mActiveBufferIndex = index; return NO_ERROR; } size_t Layer::BufferManager::getActiveBufferIndex() const { - return mActiveBuffer; + return mActiveBufferIndex; } Texture Layer::BufferManager::getActiveTexture() const { Texture res; - if (mFailover || mActiveBuffer<0) { + if (mFailover || mActiveBufferIndex<0) { res = mFailoverTexture; } else { - static_cast<Image&>(res) = mBufferData[mActiveBuffer].texture; + static_cast<Image&>(res) = mBufferData[mActiveBufferIndex].texture; } return res; } sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const { - sp<GraphicBuffer> result; - const ssize_t activeBuffer = mActiveBuffer; - if (activeBuffer >= 0) { - BufferData const * const buffers = mBufferData; - Mutex::Autolock _l(mLock); - result = buffers[activeBuffer].buffer; - } - return result; + return mActiveBuffer; +} + +bool Layer::BufferManager::hasActiveBuffer() const { + return mActiveBufferIndex >= 0; } sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index) @@ -910,7 +939,7 @@ status_t Layer::BufferManager::initEglImage(EGLDisplay dpy, const sp<GraphicBuffer>& buffer) { status_t err = NO_INIT; - ssize_t index = mActiveBuffer; + ssize_t index = mActiveBufferIndex; if (index >= 0) { if (!mFailover) { Image& texture(mBufferData[index].texture); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 30021d3a44..5444d2f194 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -164,7 +164,8 @@ private: size_t mNumBuffers; Texture mFailoverTexture; TextureManager& mTextureManager; - ssize_t mActiveBuffer; + ssize_t mActiveBufferIndex; + sp<GraphicBuffer> mActiveBuffer; bool mFailover; static status_t destroyTexture(Image* tex, EGLDisplay dpy); @@ -188,6 +189,8 @@ private: size_t getActiveBufferIndex() const; // return the active buffer sp<GraphicBuffer> getActiveBuffer() const; + // return wether we have an active buffer + bool hasActiveBuffer() const; // return the active texture (or fail-over) Texture getActiveTexture() const; // frees resources associated with all buffers diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 61d08aabdc..825d90b7d6 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -395,6 +395,7 @@ bool SurfaceFlinger::threadLoop() logger.log(GraphicLog::SF_REPAINT_DONE, index); } else { // pretend we did the post + hw.compositionComplete(); unlockClients(); usleep(16667); // 60 fps period } @@ -1023,6 +1024,8 @@ void SurfaceFlinger::drawWormhole() const glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); } } @@ -2120,6 +2123,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, // invert everything, b/c glReadPixel() below will invert the FB glViewport(0, 0, sw, sh); + glScissor(0, 0, sw, sh); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); @@ -2129,6 +2133,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, // redraw the screen entirely... glClearColor(0,0,0,1); glClear(GL_COLOR_BUFFER_BIT); + const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); const size_t count = layers.size(); for (size_t i=0 ; i<count ; ++i) { @@ -2166,7 +2171,6 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, result = NO_MEMORY; } } - glEnable(GL_SCISSOR_TEST); glViewport(0, 0, hw_w, hw_h); glMatrixMode(GL_PROJECTION); @@ -2182,6 +2186,9 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); glDeleteRenderbuffersOES(1, &tname); glDeleteFramebuffersOES(1, &name); + + hw.compositionComplete(); + return result; } |