diff options
Diffstat (limited to 'libs/surfaceflinger/Layer.cpp')
-rw-r--r-- | libs/surfaceflinger/Layer.cpp | 133 |
1 files changed, 87 insertions, 46 deletions
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index 1870d3a..0a3254d 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -27,7 +27,8 @@ #include <ui/GraphicBuffer.h> #include <ui/PixelFormat.h> -#include <ui/Surface.h> + +#include <surfaceflinger/Surface.h> #include "clz.h" #include "Layer.h" @@ -40,6 +41,10 @@ namespace android { +template <typename T> inline T min(T a, T b) { + return a<b ? a : b; +} + // --------------------------------------------------------------------------- const uint32_t Layer::typeInfo = LayerBaseClient::typeInfo | 4; @@ -108,17 +113,26 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, // the display's pixel format const DisplayHardware& hw(graphicPlane(0).displayHardware()); + uint32_t const maxSurfaceDims = min( + hw.getMaxTextureSize(), hw.getMaxViewportDims()); + + // never allow a surface larger than what our underlying GL implementation + // can handle. + if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) { + return BAD_VALUE; + } + PixelFormatInfo displayInfo; getPixelFormatInfo(hw.getFormat(), &displayInfo); const uint32_t hwFlags = hw.getFlags(); mFormat = format; - mWidth = w; + mWidth = w; mHeight = h; mSecure = (flags & ISurfaceComposer::eSecure) ? true : false; mNeedsBlending = (info.h_alpha - info.l_alpha) > 0; mNoEGLImageForSwBuffers = !(hwFlags & DisplayHardware::CACHED_BUFFERS); - + // we use the red index int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED); int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED); @@ -155,7 +169,11 @@ void Layer::reloadTexture(const Region& dirty) if (mFlags & DisplayHardware::DIRECT_TEXTURE) { if (buffer->usage & GraphicBuffer::USAGE_HW_TEXTURE) { if (mTextures[index].dirty) { - initializeEglImage(buffer, &mTextures[index]); + if (initializeEglImage(buffer, &mTextures[index]) != NO_ERROR) { + // not sure what we can do here... + mFlags &= ~DisplayHardware::DIRECT_TEXTURE; + goto slowpath; + } } } else { if (mHybridBuffer==0 || (mHybridBuffer->width != buffer->width || @@ -165,8 +183,13 @@ void Layer::reloadTexture(const Region& dirty) buffer->width, buffer->height, buffer->format, GraphicBuffer::USAGE_SW_WRITE_OFTEN | GraphicBuffer::USAGE_HW_TEXTURE); - initializeEglImage( - mHybridBuffer, &mTextures[0]); + if (initializeEglImage( + mHybridBuffer, &mTextures[0]) != NO_ERROR) { + // not sure what we can do here... + mFlags &= ~DisplayHardware::DIRECT_TEXTURE; + mHybridBuffer.clear(); + goto slowpath; + } } GGLSurface t; @@ -184,20 +207,20 @@ void Layer::reloadTexture(const Region& dirty) if (res == NO_ERROR) { int bpp = 0; switch (t.format) { - case GGL_PIXEL_FORMAT_RGB_565: - case GGL_PIXEL_FORMAT_RGBA_4444: + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_RGBA_4444: bpp = 2; break; - case GGL_PIXEL_FORMAT_RGBA_8888: - case GGL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: bpp = 4; break; - case GGL_PIXEL_FORMAT_YCbCr_422_SP: - case GGL_PIXEL_FORMAT_YCbCr_420_SP: - // just show the Y plane of YUV buffers - bpp = 1; - break; default: + if (isSupportedYuvFormat(t.format)) { + // just show the Y plane of YUV buffers + bpp = 1; + break; + } // oops, we don't handle this format! LOGE("layer %p, texture=%d, using format %d, which is not " "supported by the GL", this, texture->name, t.format); @@ -235,6 +258,7 @@ void Layer::reloadTexture(const Region& dirty) } else #endif { +slowpath: for (size_t i=0 ; i<NUM_BUFFERS ; i++) { mTextures[i].image = EGL_NO_IMAGE_KHR; } @@ -454,44 +478,61 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) // for composition later in the loop return; } - + + // ouch, this really should never happen + if (uint32_t(buf)>=NUM_BUFFERS) { + LOGE("retireAndLock() buffer index (%d) out of range", buf); + mPostedDirtyRegion.clear(); + return; + } + // we retired a buffer, which becomes the new front buffer mFrontBufferIndex = buf; // get the dirty region sp<GraphicBuffer> newFrontBuffer(getBuffer(buf)); - const Region dirty(lcblk->getDirtyRegion(buf)); - mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() ); - - const Layer::State& front(drawingState()); - if (newFrontBuffer->getWidth() == front.requested_w && - newFrontBuffer->getHeight() == front.requested_h) - { - if ((front.w != front.requested_w) || - (front.h != front.requested_h)) + if (newFrontBuffer != NULL) { + // compute the posted region + const Region dirty(lcblk->getDirtyRegion(buf)); + mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() ); + + // update the layer size and release freeze-lock + const Layer::State& front(drawingState()); + if (newFrontBuffer->getWidth() == front.requested_w && + newFrontBuffer->getHeight() == front.requested_h) { - // Here we pretend the transaction happened by updating the - // current and drawing states. Drawing state is only accessed - // in this thread, no need to have it locked - Layer::State& editDraw(mDrawingState); - editDraw.w = editDraw.requested_w; - editDraw.h = editDraw.requested_h; - - // We also need to update the current state so that we don't - // end-up doing too much work during the next transaction. - // NOTE: We actually don't need hold the transaction lock here - // because State::w and State::h are only accessed from - // this thread - Layer::State& editTemp(currentState()); - editTemp.w = editDraw.w; - editTemp.h = editDraw.h; - - // recompute visible region - recomputeVisibleRegions = true; - } + if ((front.w != front.requested_w) || + (front.h != front.requested_h)) + { + // Here we pretend the transaction happened by updating the + // current and drawing states. Drawing state is only accessed + // in this thread, no need to have it locked + Layer::State& editDraw(mDrawingState); + editDraw.w = editDraw.requested_w; + editDraw.h = editDraw.requested_h; + + // We also need to update the current state so that we don't + // end-up doing too much work during the next transaction. + // NOTE: We actually don't need hold the transaction lock here + // because State::w and State::h are only accessed from + // this thread + Layer::State& editTemp(currentState()); + editTemp.w = editDraw.w; + editTemp.h = editDraw.h; + + // recompute visible region + recomputeVisibleRegions = true; + } - // we now have the correct size, unfreeze the screen - mFreezeLock.clear(); + // we now have the correct size, unfreeze the screen + mFreezeLock.clear(); + } + } else { + // this should not happen unless we ran out of memory while + // allocating the buffer. we're hoping that things will get back + // to normal the next time the app tries to draw into this buffer. + // meanwhile, pretend the screen didn't update. + mPostedDirtyRegion.clear(); } if (lcblk->getQueuedCount()) { |