diff options
| -rw-r--r-- | include/surfaceflinger/Surface.h | 2 | ||||
| -rw-r--r-- | include/utils/CallStack.h | 2 | ||||
| -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 | 41 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.h | 2 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 2 |
8 files changed, 109 insertions, 44 deletions
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/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..5a0f115ca1 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 @@ -868,6 +897,10 @@ sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const { return result; } +bool Layer::BufferManager::hasActiveBuffer() const { + return mActiveBuffer >= 0; +} + sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index) { BufferData* const buffers = mBufferData; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 30021d3a44..c367a8dfe2 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -188,6 +188,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..a6b14225f1 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1023,6 +1023,8 @@ void SurfaceFlinger::drawWormhole() const glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); } } |