summaryrefslogtreecommitdiffstats
path: root/libs/surfaceflinger/Layer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/surfaceflinger/Layer.cpp')
-rw-r--r--libs/surfaceflinger/Layer.cpp133
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()) {