Loading libs/surfaceflinger/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ LOCAL_SRC_FILES:= \ LayerDim.cpp \ MessageQueue.cpp \ SurfaceFlinger.cpp \ TextureManager.cpp \ Tokenizer.cpp \ Transform.cpp Loading libs/surfaceflinger/Layer.cpp +156 −81 Original line number Diff line number Diff line Loading @@ -48,41 +48,49 @@ template <typename T> inline T min(T a, T b) { // --------------------------------------------------------------------------- Layer::Layer(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& c, int32_t i) : LayerBaseClient(flinger, display, c, i), const sp<Client>& client, int32_t i) : LayerBaseClient(flinger, display, client, i), lcblk(NULL), mSecure(false), mNeedsBlending(true), mNeedsDithering(false) mNeedsDithering(false), mTextureManager(mFlags), mBufferManager(mTextureManager) { // no OpenGL operation is possible here, since we might not be // in the OpenGL thread. mFrontBufferIndex = lcblk->getFrontBuffer(); lcblk = new SharedBufferServer( client->ctrlblk, i, mBufferManager.getBufferCount(), getIdentity()); mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() ); } Layer::~Layer() { destroy(); // the actual buffers will be destroyed here delete lcblk; } void Layer::destroy() // called with SurfaceFlinger::mStateLock as soon as the layer is entered // in the purgatory list void Layer::onRemoved() { for (size_t i=0 ; i<NUM_BUFFERS ; i++) { if (mTextures[i].name != -1U) { glDeleteTextures(1, &mTextures[i].name); mTextures[i].name = -1U; // wake up the condition lcblk->setStatus(NO_INIT); } if (mTextures[i].image != EGL_NO_IMAGE_KHR) { void Layer::destroy() { EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); eglDestroyImageKHR(dpy, mTextures[i].image); mTextures[i].image = EGL_NO_IMAGE_KHR; } mBufferManager.destroy(dpy); mSurface.clear(); Mutex::Autolock _l(mLock); mBuffers[i].clear(); mWidth = mHeight = 0; } mSurface.clear(); } sp<LayerBaseClient::Surface> Layer::createSurface() const { Loading Loading @@ -131,17 +139,13 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED); mNeedsDithering = layerRedsize > displayRedSize; for (size_t i=0 ; i<NUM_BUFFERS ; i++) { mBuffers[i] = new GraphicBuffer(); } mSurface = new SurfaceLayer(mFlinger, clientIndex(), this); return NO_ERROR; } void Layer::reloadTexture(const Region& dirty) { Mutex::Autolock _l(mLock); sp<GraphicBuffer> buffer(getFrontBufferLocked()); 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 Loading @@ -149,37 +153,24 @@ void Layer::reloadTexture(const Region& dirty) return; } const int index = mFrontBufferIndex; // create the new texture name if needed if (UNLIKELY(mTextures[index].name == -1U)) { mTextures[index].name = createTexture(); mTextures[index].width = 0; mTextures[index].height = 0; } #ifdef EGL_ANDROID_image_native_buffer if (mFlags & DisplayHardware::DIRECT_TEXTURE) { if (mTextures[index].dirty) { if (initializeEglImage(buffer, &mTextures[index]) != NO_ERROR) { EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); if (mBufferManager.initEglImage(dpy, buffer) != NO_ERROR) { // not sure what we can do here... mFlags &= ~DisplayHardware::DIRECT_TEXTURE; goto slowpath; } } } else #endif { slowpath: for (size_t i=0 ; i<NUM_BUFFERS ; i++) { mTextures[i].image = EGL_NO_IMAGE_KHR; } GGLSurface t; status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN); LOGE_IF(res, "error %d (%s) locking buffer %p", res, strerror(res), buffer.get()); if (res == NO_ERROR) { loadTexture(&mTextures[0], dirty, t); mBufferManager.loadTexture(dirty, t); buffer->unlock(); } } Loading @@ -187,11 +178,8 @@ slowpath: void Layer::onDraw(const Region& clip) const { int index = mFrontBufferIndex; if (mTextures[index].image == EGL_NO_IMAGE_KHR) index = 0; GLuint textureName = mTextures[index].name; if (UNLIKELY(textureName == -1LU)) { Texture tex(mBufferManager.getActiveTexture()); if (tex.name == -1LU) { // the texture has not been created yet, this Layer has // in fact never been drawn into. This happens frequently with // SurfaceView because the WindowManager can't know when the client Loading @@ -217,7 +205,7 @@ void Layer::onDraw(const Region& clip) const } return; } drawWithOpenGL(clip, mTextures[index]); drawWithOpenGL(clip, tex); } sp<GraphicBuffer> Layer::requestBuffer(int index, int usage) Loading Loading @@ -254,15 +242,7 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, int usage) Mutex::Autolock _l(mLock); w = mWidth; h = mHeight; buffer = mBuffers[index]; // destroy() could have been called before we get here, we log it // because it's uncommon, and the code below should handle it LOGW_IF(buffer==0, "mBuffers[%d] is null (mWidth=%d, mHeight=%d)", index, w, h); mBuffers[index].clear(); buffer = mBufferManager.detachBuffer(index); } const uint32_t effectiveUsage = getEffectiveUsage(usage); Loading Loading @@ -290,10 +270,7 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, int usage) if (err == NO_ERROR && buffer->handle != 0) { Mutex::Autolock _l(mLock); if (mWidth && mHeight) { // and we have new buffer mBuffers[index] = buffer; // texture is now dirty... mTextures[index].dirty = true; mBufferManager.attachBuffer(index, buffer); } else { // oops we got killed while we were allocating the buffer buffer.clear(); Loading Loading @@ -338,13 +315,10 @@ uint32_t Layer::doTransaction(uint32_t flags) (front.requested_h != temp.requested_h)) { // the size changed, we need to ask our client to request a new buffer LOGD_IF(DEBUG_RESIZE, "resize (layer=%p), requested (%dx%d), " "drawing (%d,%d), (%dx%d), (%dx%d)", "resize (layer=%p), requested (%dx%d), drawing (%d,%d)", this, int(temp.requested_w), int(temp.requested_h), int(front.requested_w), int(front.requested_h), int(mBuffers[0]->getWidth()), int(mBuffers[0]->getHeight()), int(mBuffers[1]->getWidth()), int(mBuffers[1]->getHeight())); int(front.requested_w), int(front.requested_h)); // we're being resized and there is a freeze display request, // acquire a freeze lock, so that the screen stays put Loading Loading @@ -396,22 +370,25 @@ void Layer::setDrawingSize(uint32_t w, uint32_t h) { void Layer::lockPageFlip(bool& recomputeVisibleRegions) { ssize_t buf = lcblk->retireAndLock(); if (buf < NO_ERROR) { //LOGW("nothing to retire (%s)", strerror(-buf)); // NOTE: here the buffer is locked because we will used if (buf == NOT_ENOUGH_DATA) { // NOTE: This is not an error, it simply means there is nothing to // retire. The buffer is locked because we will use it // for composition later in the loop return; } // ouch, this really should never happen if (uint32_t(buf)>=NUM_BUFFERS) { if (buf < NO_ERROR) { LOGE("retireAndLock() buffer index (%d) out of range", buf); mPostedDirtyRegion.clear(); return; } // we retired a buffer, which becomes the new front buffer mFrontBufferIndex = buf; if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) { LOGE("retireAndLock() buffer index (%d) out of range", buf); mPostedDirtyRegion.clear(); return; } // get the dirty region sp<GraphicBuffer> newFrontBuffer(getBuffer(buf)); Loading Loading @@ -503,10 +480,9 @@ void Layer::unlockPageFlip( void Layer::finishPageFlip() { status_t err = lcblk->unlock( mFrontBufferIndex ); LOGE_IF(err!=NO_ERROR, "layer %p, buffer=%d wasn't locked!", this, mFrontBufferIndex); int buf = mBufferManager.getActiveBufferIndex(); status_t err = lcblk->unlock( buf ); LOGE_IF(err!=NO_ERROR, "layer %p, buffer=%d wasn't locked!", this, buf); } Loading Loading @@ -543,6 +519,109 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const // --------------------------------------------------------------------------- Layer::BufferManager::BufferManager(TextureManager& tm) : mTextureManager(tm), mActiveBuffer(0), mFailover(false) { } size_t Layer::BufferManager::getBufferCount() const { return NUM_BUFFERS; } // only for debugging sp<GraphicBuffer> Layer::BufferManager::getBuffer(size_t index) const { return mBufferData[index].buffer; } status_t Layer::BufferManager::setActiveBufferIndex(size_t index) { // TODO: need to validate 'index' mActiveBuffer = index; return NO_ERROR; } size_t Layer::BufferManager::getActiveBufferIndex() const { return mActiveBuffer; } Texture Layer::BufferManager::getActiveTexture() const { return mFailover ? mFailoverTexture : mBufferData[mActiveBuffer].texture; } sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const { Mutex::Autolock _l(mLock); return mBufferData[mActiveBuffer].buffer; } sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index) { sp<GraphicBuffer> buffer; Mutex::Autolock _l(mLock); buffer = mBufferData[index].buffer; mBufferData[index].buffer = 0; return buffer; } status_t Layer::BufferManager::attachBuffer(size_t index, const sp<GraphicBuffer>& buffer) { Mutex::Autolock _l(mLock); mBufferData[index].buffer = buffer; mBufferData[index].texture.dirty = true; return NO_ERROR; } status_t Layer::BufferManager::destroyTexture(Texture* tex, EGLDisplay dpy) { if (tex->name != -1U) { glDeleteTextures(1, &tex->name); tex->name = -1U; } if (tex->image != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(dpy, tex->image); tex->image = EGL_NO_IMAGE_KHR; } return NO_ERROR; } status_t Layer::BufferManager::destroy(EGLDisplay dpy) { Mutex::Autolock _l(mLock); for (size_t i=0 ; i<NUM_BUFFERS ; i++) { destroyTexture(&mBufferData[i].texture, dpy); mBufferData[i].buffer = 0; } destroyTexture(&mFailoverTexture, dpy); return NO_ERROR; } status_t Layer::BufferManager::initEglImage(EGLDisplay dpy, const sp<GraphicBuffer>& buffer) { size_t index = mActiveBuffer; Texture& texture(mBufferData[index].texture); status_t err = mTextureManager.initEglImage(&texture, dpy, buffer); // if EGLImage fails, we switch to regular texture mode, and we // free all resources associated with using EGLImages. if (err == NO_ERROR) { mFailover = false; destroyTexture(&mFailoverTexture, dpy); } else { mFailover = true; for (size_t i=0 ; i<NUM_BUFFERS ; i++) { destroyTexture(&mBufferData[i].texture, dpy); } } return err; } status_t Layer::BufferManager::loadTexture( const Region& dirty, const GGLSurface& t) { return mTextureManager.loadTexture(&mFailoverTexture, dirty, t); } // --------------------------------------------------------------------------- Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger, SurfaceID id, const sp<Layer>& owner) : Surface(flinger, id, owner->getIdentity(), owner) Loading @@ -558,12 +637,8 @@ sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage) sp<GraphicBuffer> buffer; sp<Layer> owner(getOwner()); if (owner != 0) { LOGE_IF(uint32_t(index)>=NUM_BUFFERS, "getBuffer() index (%d) out of range", index); if (uint32_t(index) < NUM_BUFFERS) { buffer = owner->requestBuffer(index, usage); } } return buffer; } Loading libs/surfaceflinger/Layer.h +66 −18 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include "LayerBase.h" #include "Transform.h" #include "TextureManager.h" namespace android { Loading @@ -41,11 +42,13 @@ class FreezeLock; // --------------------------------------------------------------------------- const size_t NUM_BUFFERS = 2; class Layer : public LayerBaseClient { public: // lcblk is (almost) only accessed from the main SF thread, in the places // where it's not, a reference to Client must be held SharedBufferServer* lcblk; Layer(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& client, int32_t i); Loading @@ -66,15 +69,14 @@ public: virtual bool isSecure() const { return mSecure; } virtual sp<Surface> createSurface() const; virtual status_t ditch(); virtual void onRemoved(); // only for debugging inline sp<GraphicBuffer> getBuffer(int i) const { return mBuffers[i]; } inline sp<GraphicBuffer> getBuffer(int i) const { return mBufferManager.getBuffer(i); } // only for debugging inline const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; } // only for debugging inline PixelFormat pixelFormat() const { return mFormat; } // only for debugging inline int getFrontBufferIndex() const { return mFrontBufferIndex; } virtual const char* getTypeId() const { return "Layer"; } Loading @@ -82,10 +84,6 @@ protected: virtual void dump(String8& result, char* scratch, size_t size) const; private: inline sp<GraphicBuffer> getFrontBufferLocked() { return mBuffers[mFrontBufferIndex]; } void reloadTexture(const Region& dirty); uint32_t getEffectiveUsage(uint32_t usage) const; Loading Loading @@ -116,13 +114,63 @@ private: sp<FreezeLock> mFreezeLock; PixelFormat mFormat; // protected by mLock sp<GraphicBuffer> mBuffers[NUM_BUFFERS]; Texture mTextures[NUM_BUFFERS]; uint32_t mWidth; uint32_t mHeight; class BufferManager { static const size_t NUM_BUFFERS = 2; struct BufferData { sp<GraphicBuffer> buffer; Texture texture; }; mutable Mutex mLock; BufferData mBufferData[NUM_BUFFERS]; Texture mFailoverTexture; TextureManager& mTextureManager; ssize_t mActiveBuffer; bool mFailover; static status_t destroyTexture(Texture* tex, EGLDisplay dpy); public: BufferManager(TextureManager& tm); size_t getBufferCount() const; // detach/attach buffer from/to given index sp<GraphicBuffer> detachBuffer(size_t index); status_t attachBuffer(size_t index, const sp<GraphicBuffer>& buffer); // ---------------------------------------------- // must be called from GL thread // set/get active buffer index status_t setActiveBufferIndex(size_t index); size_t getActiveBufferIndex() const; // return the active buffer sp<GraphicBuffer> getActiveBuffer() const; // return the active texture (or fail-over) Texture getActiveTexture() const; // frees resources associated with all buffers status_t destroy(EGLDisplay dpy); // load bitmap data into the active buffer status_t loadTexture(const Region& dirty, const GGLSurface& t); // make active buffer an EGLImage if needed status_t initEglImage(EGLDisplay dpy, const sp<GraphicBuffer>& buffer); // ---------------------------------------------- // only for debugging sp<GraphicBuffer> getBuffer(size_t index) const; }; TextureManager mTextureManager; BufferManager mBufferManager; mutable Mutex mLock; uint32_t mWidth; uint32_t mHeight; }; // --------------------------------------------------------------------------- Loading libs/surfaceflinger/LayerBase.cpp +2 −206 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include "LayerBase.h" #include "SurfaceFlinger.h" #include "DisplayHardware/DisplayHardware.h" #include "TextureManager.h" namespace android { Loading Loading @@ -340,18 +341,6 @@ void LayerBase::draw(const Region& inClip) const */ } GLuint LayerBase::createTexture() const { GLuint textureName = -1; glGenTextures(1, &textureName); glBindTexture(GL_TEXTURE_2D, textureName); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); return textureName; } void LayerBase::clearWithOpenGL(const Region& clip, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) const Loading Loading @@ -492,187 +481,6 @@ void LayerBase::validateTexture(GLint textureName) const } } bool LayerBase::isSupportedYuvFormat(int format) const { switch (format) { case HAL_PIXEL_FORMAT_YCbCr_422_SP: case HAL_PIXEL_FORMAT_YCbCr_420_SP: case HAL_PIXEL_FORMAT_YCbCr_422_P: case HAL_PIXEL_FORMAT_YCbCr_420_P: case HAL_PIXEL_FORMAT_YCbCr_422_I: case HAL_PIXEL_FORMAT_YCbCr_420_I: case HAL_PIXEL_FORMAT_YCrCb_420_SP: return true; } return false; } void LayerBase::loadTexture(Texture* texture, const Region& dirty, const GGLSurface& t) const { if (texture->name == -1U) { // uh? return; } glBindTexture(GL_TEXTURE_2D, texture->name); /* * In OpenGL ES we can't specify a stride with glTexImage2D (however, * GL_UNPACK_ALIGNMENT is a limited form of stride). * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we * need to do something reasonable (here creating a bigger texture). * * extra pixels = (((stride - width) * pixelsize) / GL_UNPACK_ALIGNMENT); * * This situation doesn't happen often, but some h/w have a limitation * for their framebuffer (eg: must be multiple of 8 pixels), and * we need to take that into account when using these buffers as * textures. * * This should never be a problem with POT textures */ int unpack = __builtin_ctz(t.stride * bytesPerPixel(t.format)); unpack = 1 << ((unpack > 3) ? 3 : unpack); glPixelStorei(GL_UNPACK_ALIGNMENT, unpack); /* * round to POT if needed */ if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) { texture->NPOTAdjust = true; } if (texture->NPOTAdjust) { // find the smallest power-of-two that will accommodate our surface texture->potWidth = 1 << (31 - clz(t.width)); texture->potHeight = 1 << (31 - clz(t.height)); if (texture->potWidth < t.width) texture->potWidth <<= 1; if (texture->potHeight < t.height) texture->potHeight <<= 1; texture->wScale = float(t.width) / texture->potWidth; texture->hScale = float(t.height) / texture->potHeight; } else { texture->potWidth = t.width; texture->potHeight = t.height; } Rect bounds(dirty.bounds()); GLvoid* data = 0; if (texture->width != t.width || texture->height != t.height) { texture->width = t.width; texture->height = t.height; // texture size changed, we need to create a new one bounds.set(Rect(t.width, t.height)); if (t.width == texture->potWidth && t.height == texture->potHeight) { // we can do it one pass data = t.data; } if (t.format == HAL_PIXEL_FORMAT_RGB_565) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture->potWidth, texture->potHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->potWidth, texture->potHeight, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 || t.format == HAL_PIXEL_FORMAT_RGBX_8888) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->potWidth, texture->potHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); } else if (isSupportedYuvFormat(t.format)) { // just show the Y plane of YUV buffers glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, texture->potWidth, texture->potHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); } else { // 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); } } if (!data) { if (t.format == HAL_PIXEL_FORMAT_RGB_565) { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.top, t.width, bounds.height(), GL_RGB, GL_UNSIGNED_SHORT_5_6_5, t.data + bounds.top*t.stride*2); } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.top, t.width, bounds.height(), GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, t.data + bounds.top*t.stride*2); } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 || t.format == HAL_PIXEL_FORMAT_RGBX_8888) { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.top, t.width, bounds.height(), GL_RGBA, GL_UNSIGNED_BYTE, t.data + bounds.top*t.stride*4); } else if (isSupportedYuvFormat(t.format)) { // just show the Y plane of YUV buffers glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.top, t.width, bounds.height(), GL_LUMINANCE, GL_UNSIGNED_BYTE, t.data + bounds.top*t.stride); } } } status_t LayerBase::initializeEglImage( const sp<GraphicBuffer>& buffer, Texture* texture) { status_t err = NO_ERROR; // we need to recreate the texture EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); // free the previous image if (texture->image != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(dpy, texture->image); texture->image = EGL_NO_IMAGE_KHR; } // construct an EGL_NATIVE_BUFFER_ANDROID android_native_buffer_t* clientBuf = buffer->getNativeBuffer(); // create the new EGLImageKHR const EGLint attrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE }; texture->image = eglCreateImageKHR( dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)clientBuf, attrs); if (texture->image != EGL_NO_IMAGE_KHR) { glBindTexture(GL_TEXTURE_2D, texture->name); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)texture->image); GLint error = glGetError(); if (UNLIKELY(error != GL_NO_ERROR)) { LOGE("layer=%p, glEGLImageTargetTexture2DOES(%p) " "failed err=0x%04x", this, texture->image, error); err = INVALID_OPERATION; } else { // Everything went okay! texture->NPOTAdjust = false; texture->dirty = false; texture->width = clientBuf->width; texture->height = clientBuf->height; } } else { LOGE("layer=%p, eglCreateImageKHR() failed. err=0x%4x", this, eglGetError()); err = INVALID_OPERATION; } return err; } void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const { const Layer::State& s(drawingState()); Loading @@ -696,12 +504,9 @@ int32_t LayerBaseClient::sIdentity = 0; LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& client, int32_t i) : LayerBase(flinger, display), lcblk(NULL), client(client), mIndex(i), : LayerBase(flinger, display), client(client), mIndex(i), mIdentity(uint32_t(android_atomic_inc(&sIdentity))) { lcblk = new SharedBufferServer( client->ctrlblk, i, NUM_BUFFERS, mIdentity); } void LayerBaseClient::onFirstRef() Loading @@ -718,7 +523,6 @@ LayerBaseClient::~LayerBaseClient() if (client != 0) { client->free(mIndex); } delete lcblk; } ssize_t LayerBaseClient::serverIndex() const Loading Loading @@ -748,14 +552,6 @@ sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const const_cast<LayerBaseClient *>(this)); } // called with SurfaceFlinger::mStateLock as soon as the layer is entered // in the purgatory list void LayerBaseClient::onRemoved() { // wake up the condition lcblk->setStatus(NO_INIT); } void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const { LayerBase::dump(result, buffer, SIZE); Loading libs/surfaceflinger/LayerBase.h +1 −30 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
libs/surfaceflinger/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ LOCAL_SRC_FILES:= \ LayerDim.cpp \ MessageQueue.cpp \ SurfaceFlinger.cpp \ TextureManager.cpp \ Tokenizer.cpp \ Transform.cpp Loading
libs/surfaceflinger/Layer.cpp +156 −81 Original line number Diff line number Diff line Loading @@ -48,41 +48,49 @@ template <typename T> inline T min(T a, T b) { // --------------------------------------------------------------------------- Layer::Layer(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& c, int32_t i) : LayerBaseClient(flinger, display, c, i), const sp<Client>& client, int32_t i) : LayerBaseClient(flinger, display, client, i), lcblk(NULL), mSecure(false), mNeedsBlending(true), mNeedsDithering(false) mNeedsDithering(false), mTextureManager(mFlags), mBufferManager(mTextureManager) { // no OpenGL operation is possible here, since we might not be // in the OpenGL thread. mFrontBufferIndex = lcblk->getFrontBuffer(); lcblk = new SharedBufferServer( client->ctrlblk, i, mBufferManager.getBufferCount(), getIdentity()); mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() ); } Layer::~Layer() { destroy(); // the actual buffers will be destroyed here delete lcblk; } void Layer::destroy() // called with SurfaceFlinger::mStateLock as soon as the layer is entered // in the purgatory list void Layer::onRemoved() { for (size_t i=0 ; i<NUM_BUFFERS ; i++) { if (mTextures[i].name != -1U) { glDeleteTextures(1, &mTextures[i].name); mTextures[i].name = -1U; // wake up the condition lcblk->setStatus(NO_INIT); } if (mTextures[i].image != EGL_NO_IMAGE_KHR) { void Layer::destroy() { EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); eglDestroyImageKHR(dpy, mTextures[i].image); mTextures[i].image = EGL_NO_IMAGE_KHR; } mBufferManager.destroy(dpy); mSurface.clear(); Mutex::Autolock _l(mLock); mBuffers[i].clear(); mWidth = mHeight = 0; } mSurface.clear(); } sp<LayerBaseClient::Surface> Layer::createSurface() const { Loading Loading @@ -131,17 +139,13 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED); mNeedsDithering = layerRedsize > displayRedSize; for (size_t i=0 ; i<NUM_BUFFERS ; i++) { mBuffers[i] = new GraphicBuffer(); } mSurface = new SurfaceLayer(mFlinger, clientIndex(), this); return NO_ERROR; } void Layer::reloadTexture(const Region& dirty) { Mutex::Autolock _l(mLock); sp<GraphicBuffer> buffer(getFrontBufferLocked()); 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 Loading @@ -149,37 +153,24 @@ void Layer::reloadTexture(const Region& dirty) return; } const int index = mFrontBufferIndex; // create the new texture name if needed if (UNLIKELY(mTextures[index].name == -1U)) { mTextures[index].name = createTexture(); mTextures[index].width = 0; mTextures[index].height = 0; } #ifdef EGL_ANDROID_image_native_buffer if (mFlags & DisplayHardware::DIRECT_TEXTURE) { if (mTextures[index].dirty) { if (initializeEglImage(buffer, &mTextures[index]) != NO_ERROR) { EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); if (mBufferManager.initEglImage(dpy, buffer) != NO_ERROR) { // not sure what we can do here... mFlags &= ~DisplayHardware::DIRECT_TEXTURE; goto slowpath; } } } else #endif { slowpath: for (size_t i=0 ; i<NUM_BUFFERS ; i++) { mTextures[i].image = EGL_NO_IMAGE_KHR; } GGLSurface t; status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN); LOGE_IF(res, "error %d (%s) locking buffer %p", res, strerror(res), buffer.get()); if (res == NO_ERROR) { loadTexture(&mTextures[0], dirty, t); mBufferManager.loadTexture(dirty, t); buffer->unlock(); } } Loading @@ -187,11 +178,8 @@ slowpath: void Layer::onDraw(const Region& clip) const { int index = mFrontBufferIndex; if (mTextures[index].image == EGL_NO_IMAGE_KHR) index = 0; GLuint textureName = mTextures[index].name; if (UNLIKELY(textureName == -1LU)) { Texture tex(mBufferManager.getActiveTexture()); if (tex.name == -1LU) { // the texture has not been created yet, this Layer has // in fact never been drawn into. This happens frequently with // SurfaceView because the WindowManager can't know when the client Loading @@ -217,7 +205,7 @@ void Layer::onDraw(const Region& clip) const } return; } drawWithOpenGL(clip, mTextures[index]); drawWithOpenGL(clip, tex); } sp<GraphicBuffer> Layer::requestBuffer(int index, int usage) Loading Loading @@ -254,15 +242,7 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, int usage) Mutex::Autolock _l(mLock); w = mWidth; h = mHeight; buffer = mBuffers[index]; // destroy() could have been called before we get here, we log it // because it's uncommon, and the code below should handle it LOGW_IF(buffer==0, "mBuffers[%d] is null (mWidth=%d, mHeight=%d)", index, w, h); mBuffers[index].clear(); buffer = mBufferManager.detachBuffer(index); } const uint32_t effectiveUsage = getEffectiveUsage(usage); Loading Loading @@ -290,10 +270,7 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, int usage) if (err == NO_ERROR && buffer->handle != 0) { Mutex::Autolock _l(mLock); if (mWidth && mHeight) { // and we have new buffer mBuffers[index] = buffer; // texture is now dirty... mTextures[index].dirty = true; mBufferManager.attachBuffer(index, buffer); } else { // oops we got killed while we were allocating the buffer buffer.clear(); Loading Loading @@ -338,13 +315,10 @@ uint32_t Layer::doTransaction(uint32_t flags) (front.requested_h != temp.requested_h)) { // the size changed, we need to ask our client to request a new buffer LOGD_IF(DEBUG_RESIZE, "resize (layer=%p), requested (%dx%d), " "drawing (%d,%d), (%dx%d), (%dx%d)", "resize (layer=%p), requested (%dx%d), drawing (%d,%d)", this, int(temp.requested_w), int(temp.requested_h), int(front.requested_w), int(front.requested_h), int(mBuffers[0]->getWidth()), int(mBuffers[0]->getHeight()), int(mBuffers[1]->getWidth()), int(mBuffers[1]->getHeight())); int(front.requested_w), int(front.requested_h)); // we're being resized and there is a freeze display request, // acquire a freeze lock, so that the screen stays put Loading Loading @@ -396,22 +370,25 @@ void Layer::setDrawingSize(uint32_t w, uint32_t h) { void Layer::lockPageFlip(bool& recomputeVisibleRegions) { ssize_t buf = lcblk->retireAndLock(); if (buf < NO_ERROR) { //LOGW("nothing to retire (%s)", strerror(-buf)); // NOTE: here the buffer is locked because we will used if (buf == NOT_ENOUGH_DATA) { // NOTE: This is not an error, it simply means there is nothing to // retire. The buffer is locked because we will use it // for composition later in the loop return; } // ouch, this really should never happen if (uint32_t(buf)>=NUM_BUFFERS) { if (buf < NO_ERROR) { LOGE("retireAndLock() buffer index (%d) out of range", buf); mPostedDirtyRegion.clear(); return; } // we retired a buffer, which becomes the new front buffer mFrontBufferIndex = buf; if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) { LOGE("retireAndLock() buffer index (%d) out of range", buf); mPostedDirtyRegion.clear(); return; } // get the dirty region sp<GraphicBuffer> newFrontBuffer(getBuffer(buf)); Loading Loading @@ -503,10 +480,9 @@ void Layer::unlockPageFlip( void Layer::finishPageFlip() { status_t err = lcblk->unlock( mFrontBufferIndex ); LOGE_IF(err!=NO_ERROR, "layer %p, buffer=%d wasn't locked!", this, mFrontBufferIndex); int buf = mBufferManager.getActiveBufferIndex(); status_t err = lcblk->unlock( buf ); LOGE_IF(err!=NO_ERROR, "layer %p, buffer=%d wasn't locked!", this, buf); } Loading Loading @@ -543,6 +519,109 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const // --------------------------------------------------------------------------- Layer::BufferManager::BufferManager(TextureManager& tm) : mTextureManager(tm), mActiveBuffer(0), mFailover(false) { } size_t Layer::BufferManager::getBufferCount() const { return NUM_BUFFERS; } // only for debugging sp<GraphicBuffer> Layer::BufferManager::getBuffer(size_t index) const { return mBufferData[index].buffer; } status_t Layer::BufferManager::setActiveBufferIndex(size_t index) { // TODO: need to validate 'index' mActiveBuffer = index; return NO_ERROR; } size_t Layer::BufferManager::getActiveBufferIndex() const { return mActiveBuffer; } Texture Layer::BufferManager::getActiveTexture() const { return mFailover ? mFailoverTexture : mBufferData[mActiveBuffer].texture; } sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const { Mutex::Autolock _l(mLock); return mBufferData[mActiveBuffer].buffer; } sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index) { sp<GraphicBuffer> buffer; Mutex::Autolock _l(mLock); buffer = mBufferData[index].buffer; mBufferData[index].buffer = 0; return buffer; } status_t Layer::BufferManager::attachBuffer(size_t index, const sp<GraphicBuffer>& buffer) { Mutex::Autolock _l(mLock); mBufferData[index].buffer = buffer; mBufferData[index].texture.dirty = true; return NO_ERROR; } status_t Layer::BufferManager::destroyTexture(Texture* tex, EGLDisplay dpy) { if (tex->name != -1U) { glDeleteTextures(1, &tex->name); tex->name = -1U; } if (tex->image != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(dpy, tex->image); tex->image = EGL_NO_IMAGE_KHR; } return NO_ERROR; } status_t Layer::BufferManager::destroy(EGLDisplay dpy) { Mutex::Autolock _l(mLock); for (size_t i=0 ; i<NUM_BUFFERS ; i++) { destroyTexture(&mBufferData[i].texture, dpy); mBufferData[i].buffer = 0; } destroyTexture(&mFailoverTexture, dpy); return NO_ERROR; } status_t Layer::BufferManager::initEglImage(EGLDisplay dpy, const sp<GraphicBuffer>& buffer) { size_t index = mActiveBuffer; Texture& texture(mBufferData[index].texture); status_t err = mTextureManager.initEglImage(&texture, dpy, buffer); // if EGLImage fails, we switch to regular texture mode, and we // free all resources associated with using EGLImages. if (err == NO_ERROR) { mFailover = false; destroyTexture(&mFailoverTexture, dpy); } else { mFailover = true; for (size_t i=0 ; i<NUM_BUFFERS ; i++) { destroyTexture(&mBufferData[i].texture, dpy); } } return err; } status_t Layer::BufferManager::loadTexture( const Region& dirty, const GGLSurface& t) { return mTextureManager.loadTexture(&mFailoverTexture, dirty, t); } // --------------------------------------------------------------------------- Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger, SurfaceID id, const sp<Layer>& owner) : Surface(flinger, id, owner->getIdentity(), owner) Loading @@ -558,12 +637,8 @@ sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage) sp<GraphicBuffer> buffer; sp<Layer> owner(getOwner()); if (owner != 0) { LOGE_IF(uint32_t(index)>=NUM_BUFFERS, "getBuffer() index (%d) out of range", index); if (uint32_t(index) < NUM_BUFFERS) { buffer = owner->requestBuffer(index, usage); } } return buffer; } Loading
libs/surfaceflinger/Layer.h +66 −18 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include "LayerBase.h" #include "Transform.h" #include "TextureManager.h" namespace android { Loading @@ -41,11 +42,13 @@ class FreezeLock; // --------------------------------------------------------------------------- const size_t NUM_BUFFERS = 2; class Layer : public LayerBaseClient { public: // lcblk is (almost) only accessed from the main SF thread, in the places // where it's not, a reference to Client must be held SharedBufferServer* lcblk; Layer(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& client, int32_t i); Loading @@ -66,15 +69,14 @@ public: virtual bool isSecure() const { return mSecure; } virtual sp<Surface> createSurface() const; virtual status_t ditch(); virtual void onRemoved(); // only for debugging inline sp<GraphicBuffer> getBuffer(int i) const { return mBuffers[i]; } inline sp<GraphicBuffer> getBuffer(int i) const { return mBufferManager.getBuffer(i); } // only for debugging inline const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; } // only for debugging inline PixelFormat pixelFormat() const { return mFormat; } // only for debugging inline int getFrontBufferIndex() const { return mFrontBufferIndex; } virtual const char* getTypeId() const { return "Layer"; } Loading @@ -82,10 +84,6 @@ protected: virtual void dump(String8& result, char* scratch, size_t size) const; private: inline sp<GraphicBuffer> getFrontBufferLocked() { return mBuffers[mFrontBufferIndex]; } void reloadTexture(const Region& dirty); uint32_t getEffectiveUsage(uint32_t usage) const; Loading Loading @@ -116,13 +114,63 @@ private: sp<FreezeLock> mFreezeLock; PixelFormat mFormat; // protected by mLock sp<GraphicBuffer> mBuffers[NUM_BUFFERS]; Texture mTextures[NUM_BUFFERS]; uint32_t mWidth; uint32_t mHeight; class BufferManager { static const size_t NUM_BUFFERS = 2; struct BufferData { sp<GraphicBuffer> buffer; Texture texture; }; mutable Mutex mLock; BufferData mBufferData[NUM_BUFFERS]; Texture mFailoverTexture; TextureManager& mTextureManager; ssize_t mActiveBuffer; bool mFailover; static status_t destroyTexture(Texture* tex, EGLDisplay dpy); public: BufferManager(TextureManager& tm); size_t getBufferCount() const; // detach/attach buffer from/to given index sp<GraphicBuffer> detachBuffer(size_t index); status_t attachBuffer(size_t index, const sp<GraphicBuffer>& buffer); // ---------------------------------------------- // must be called from GL thread // set/get active buffer index status_t setActiveBufferIndex(size_t index); size_t getActiveBufferIndex() const; // return the active buffer sp<GraphicBuffer> getActiveBuffer() const; // return the active texture (or fail-over) Texture getActiveTexture() const; // frees resources associated with all buffers status_t destroy(EGLDisplay dpy); // load bitmap data into the active buffer status_t loadTexture(const Region& dirty, const GGLSurface& t); // make active buffer an EGLImage if needed status_t initEglImage(EGLDisplay dpy, const sp<GraphicBuffer>& buffer); // ---------------------------------------------- // only for debugging sp<GraphicBuffer> getBuffer(size_t index) const; }; TextureManager mTextureManager; BufferManager mBufferManager; mutable Mutex mLock; uint32_t mWidth; uint32_t mHeight; }; // --------------------------------------------------------------------------- Loading
libs/surfaceflinger/LayerBase.cpp +2 −206 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include "LayerBase.h" #include "SurfaceFlinger.h" #include "DisplayHardware/DisplayHardware.h" #include "TextureManager.h" namespace android { Loading Loading @@ -340,18 +341,6 @@ void LayerBase::draw(const Region& inClip) const */ } GLuint LayerBase::createTexture() const { GLuint textureName = -1; glGenTextures(1, &textureName); glBindTexture(GL_TEXTURE_2D, textureName); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); return textureName; } void LayerBase::clearWithOpenGL(const Region& clip, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) const Loading Loading @@ -492,187 +481,6 @@ void LayerBase::validateTexture(GLint textureName) const } } bool LayerBase::isSupportedYuvFormat(int format) const { switch (format) { case HAL_PIXEL_FORMAT_YCbCr_422_SP: case HAL_PIXEL_FORMAT_YCbCr_420_SP: case HAL_PIXEL_FORMAT_YCbCr_422_P: case HAL_PIXEL_FORMAT_YCbCr_420_P: case HAL_PIXEL_FORMAT_YCbCr_422_I: case HAL_PIXEL_FORMAT_YCbCr_420_I: case HAL_PIXEL_FORMAT_YCrCb_420_SP: return true; } return false; } void LayerBase::loadTexture(Texture* texture, const Region& dirty, const GGLSurface& t) const { if (texture->name == -1U) { // uh? return; } glBindTexture(GL_TEXTURE_2D, texture->name); /* * In OpenGL ES we can't specify a stride with glTexImage2D (however, * GL_UNPACK_ALIGNMENT is a limited form of stride). * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we * need to do something reasonable (here creating a bigger texture). * * extra pixels = (((stride - width) * pixelsize) / GL_UNPACK_ALIGNMENT); * * This situation doesn't happen often, but some h/w have a limitation * for their framebuffer (eg: must be multiple of 8 pixels), and * we need to take that into account when using these buffers as * textures. * * This should never be a problem with POT textures */ int unpack = __builtin_ctz(t.stride * bytesPerPixel(t.format)); unpack = 1 << ((unpack > 3) ? 3 : unpack); glPixelStorei(GL_UNPACK_ALIGNMENT, unpack); /* * round to POT if needed */ if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) { texture->NPOTAdjust = true; } if (texture->NPOTAdjust) { // find the smallest power-of-two that will accommodate our surface texture->potWidth = 1 << (31 - clz(t.width)); texture->potHeight = 1 << (31 - clz(t.height)); if (texture->potWidth < t.width) texture->potWidth <<= 1; if (texture->potHeight < t.height) texture->potHeight <<= 1; texture->wScale = float(t.width) / texture->potWidth; texture->hScale = float(t.height) / texture->potHeight; } else { texture->potWidth = t.width; texture->potHeight = t.height; } Rect bounds(dirty.bounds()); GLvoid* data = 0; if (texture->width != t.width || texture->height != t.height) { texture->width = t.width; texture->height = t.height; // texture size changed, we need to create a new one bounds.set(Rect(t.width, t.height)); if (t.width == texture->potWidth && t.height == texture->potHeight) { // we can do it one pass data = t.data; } if (t.format == HAL_PIXEL_FORMAT_RGB_565) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture->potWidth, texture->potHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->potWidth, texture->potHeight, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 || t.format == HAL_PIXEL_FORMAT_RGBX_8888) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->potWidth, texture->potHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); } else if (isSupportedYuvFormat(t.format)) { // just show the Y plane of YUV buffers glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, texture->potWidth, texture->potHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); } else { // 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); } } if (!data) { if (t.format == HAL_PIXEL_FORMAT_RGB_565) { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.top, t.width, bounds.height(), GL_RGB, GL_UNSIGNED_SHORT_5_6_5, t.data + bounds.top*t.stride*2); } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.top, t.width, bounds.height(), GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, t.data + bounds.top*t.stride*2); } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 || t.format == HAL_PIXEL_FORMAT_RGBX_8888) { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.top, t.width, bounds.height(), GL_RGBA, GL_UNSIGNED_BYTE, t.data + bounds.top*t.stride*4); } else if (isSupportedYuvFormat(t.format)) { // just show the Y plane of YUV buffers glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.top, t.width, bounds.height(), GL_LUMINANCE, GL_UNSIGNED_BYTE, t.data + bounds.top*t.stride); } } } status_t LayerBase::initializeEglImage( const sp<GraphicBuffer>& buffer, Texture* texture) { status_t err = NO_ERROR; // we need to recreate the texture EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); // free the previous image if (texture->image != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(dpy, texture->image); texture->image = EGL_NO_IMAGE_KHR; } // construct an EGL_NATIVE_BUFFER_ANDROID android_native_buffer_t* clientBuf = buffer->getNativeBuffer(); // create the new EGLImageKHR const EGLint attrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE }; texture->image = eglCreateImageKHR( dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)clientBuf, attrs); if (texture->image != EGL_NO_IMAGE_KHR) { glBindTexture(GL_TEXTURE_2D, texture->name); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)texture->image); GLint error = glGetError(); if (UNLIKELY(error != GL_NO_ERROR)) { LOGE("layer=%p, glEGLImageTargetTexture2DOES(%p) " "failed err=0x%04x", this, texture->image, error); err = INVALID_OPERATION; } else { // Everything went okay! texture->NPOTAdjust = false; texture->dirty = false; texture->width = clientBuf->width; texture->height = clientBuf->height; } } else { LOGE("layer=%p, eglCreateImageKHR() failed. err=0x%4x", this, eglGetError()); err = INVALID_OPERATION; } return err; } void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const { const Layer::State& s(drawingState()); Loading @@ -696,12 +504,9 @@ int32_t LayerBaseClient::sIdentity = 0; LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& client, int32_t i) : LayerBase(flinger, display), lcblk(NULL), client(client), mIndex(i), : LayerBase(flinger, display), client(client), mIndex(i), mIdentity(uint32_t(android_atomic_inc(&sIdentity))) { lcblk = new SharedBufferServer( client->ctrlblk, i, NUM_BUFFERS, mIdentity); } void LayerBaseClient::onFirstRef() Loading @@ -718,7 +523,6 @@ LayerBaseClient::~LayerBaseClient() if (client != 0) { client->free(mIndex); } delete lcblk; } ssize_t LayerBaseClient::serverIndex() const Loading Loading @@ -748,14 +552,6 @@ sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const const_cast<LayerBaseClient *>(this)); } // called with SurfaceFlinger::mStateLock as soon as the layer is entered // in the purgatory list void LayerBaseClient::onRemoved() { // wake up the condition lcblk->setStatus(NO_INIT); } void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const { LayerBase::dump(result, buffer, SIZE); Loading
libs/surfaceflinger/LayerBase.h +1 −30 File changed.Preview size limit exceeded, changes collapsed. Show changes