diff options
Diffstat (limited to 'libs/gui/SurfaceTexture.cpp')
| -rw-r--r-- | libs/gui/SurfaceTexture.cpp | 177 | 
1 files changed, 102 insertions, 75 deletions
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index ee5deb3b20..a7bfc613aa 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -97,11 +97,6 @@ static float mtxRot270[16] = {  static void mtxMul(float out[16], const float a[16], const float b[16]); -// Get an ID that's unique within this process. -static int32_t createProcessUniqueId() { -    static volatile int32_t globalCounter = 0; -    return android_atomic_inc(&globalCounter); -}  SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,          GLenum texTarget, bool useFenceSync) : @@ -114,13 +109,8 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,  #else      mUseFenceSync(false),  #endif -    mTexTarget(texTarget), -    mAbandoned(false), -    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT) +    mTexTarget(texTarget)  { -    // Choose a name using the PID and a process-unique ID. -    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); -    BufferQueue::setConsumerName(mName);      ST_LOGV("SurfaceTexture");      memcpy(mCurrentTransformMatrix, mtxIdentity, @@ -129,18 +119,28 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,  SurfaceTexture::~SurfaceTexture() {      ST_LOGV("~SurfaceTexture"); -    abandon(); +    freeAllBuffersLocked();  }  status_t SurfaceTexture::setBufferCountServer(int bufferCount) {      Mutex::Autolock lock(mMutex); -    return BufferQueue::setBufferCountServer(bufferCount); +    return setBufferCountServerLocked(bufferCount);  }  status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)  { -    return BufferQueue::setDefaultBufferSize(w, h); +    ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h); +    if (!w || !h) { +        ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", +                w, h); +        return BAD_VALUE; +    } + +    Mutex::Autolock lock(mMutex); +    mDefaultWidth = w; +    mDefaultHeight = h; +    return OK;  }  status_t SurfaceTexture::updateTexImage() { @@ -152,35 +152,23 @@ status_t SurfaceTexture::updateTexImage() {          return NO_INIT;      } -    BufferItem item; -      // In asynchronous mode the list is guaranteed to be one buffer      // deep, while in synchronous mode we use the oldest buffer. -    if (acquire(&item) == NO_ERROR) { -        int buf = item.mBuf; -        // This buffer was newly allocated, so we need to clean up on our side -        if (item.mGraphicBuffer != NULL) { -            mEGLSlots[buf].mGraphicBuffer = 0; -            if (mEGLSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) { -                eglDestroyImageKHR(mEGLSlots[buf].mEglDisplay, -                        mEGLSlots[buf].mEglImage); -                mEGLSlots[buf].mEglImage = EGL_NO_IMAGE_KHR; -                mEGLSlots[buf].mEglDisplay = EGL_NO_DISPLAY; -            } -            mEGLSlots[buf].mGraphicBuffer = item.mGraphicBuffer; -        } +    if (!mQueue.empty()) { +        Fifo::iterator front(mQueue.begin()); +        int buf = *front;          // Update the GL texture object. -        EGLImageKHR image = mEGLSlots[buf].mEglImage; +        EGLImageKHR image = mSlots[buf].mEglImage;          EGLDisplay dpy = eglGetCurrentDisplay();          if (image == EGL_NO_IMAGE_KHR) { -            if (item.mGraphicBuffer == 0) { +            if (mSlots[buf].mGraphicBuffer == 0) {                  ST_LOGE("buffer at slot %d is null", buf);                  return BAD_VALUE;              } -            image = createImage(dpy, item.mGraphicBuffer); -            mEGLSlots[buf].mEglImage = image; -            mEGLSlots[buf].mEglDisplay = dpy; +            image = createImage(dpy, mSlots[buf].mGraphicBuffer); +            mSlots[buf].mEglImage = image; +            mSlots[buf].mEglDisplay = dpy;              if (image == EGL_NO_IMAGE_KHR) {                  // NOTE: if dpy was invalid, createImage() is guaranteed to                  // fail. so we'd end up here. @@ -203,8 +191,6 @@ status_t SurfaceTexture::updateTexImage() {              failed = true;          }          if (failed) { -            releaseBuffer(buf, mEGLSlots[buf].mEglDisplay, -                    mEGLSlots[buf].mFence);              return -EINVAL;          } @@ -215,37 +201,40 @@ status_t SurfaceTexture::updateTexImage() {                  if (fence == EGL_NO_SYNC_KHR) {                      ALOGE("updateTexImage: error creating fence: %#x",                              eglGetError()); -                    releaseBuffer(buf, mEGLSlots[buf].mEglDisplay, -                            mEGLSlots[buf].mFence);                      return -EINVAL;                  }                  glFlush(); -                mEGLSlots[mCurrentTexture].mFence = fence; +                mSlots[mCurrentTexture].mFence = fence;              }          }          ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)",                  mCurrentTexture,                  mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0, -                buf, item.mGraphicBuffer->handle); +                buf, mSlots[buf].mGraphicBuffer->handle); -        // release old buffer -        releaseBuffer(mCurrentTexture, -                mEGLSlots[mCurrentTexture].mEglDisplay, -                mEGLSlots[mCurrentTexture].mFence); +        if (mCurrentTexture != INVALID_BUFFER_SLOT) { +            // The current buffer becomes FREE if it was still in the queued +            // state. If it has already been given to the client +            // (synchronous mode), then it stays in DEQUEUED state. +            if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED) { +                mSlots[mCurrentTexture].mBufferState = BufferSlot::FREE; +            } +        }          // Update the SurfaceTexture state.          mCurrentTexture = buf; -        mCurrentTextureBuf = mEGLSlots[buf].mGraphicBuffer; -        mCurrentCrop = item.mCrop; -        mCurrentTransform = item.mTransform; -        mCurrentScalingMode = item.mScalingMode; -        mCurrentTimestamp = item.mTimestamp; +        mCurrentTextureBuf = mSlots[buf].mGraphicBuffer; +        mCurrentCrop = mSlots[buf].mCrop; +        mCurrentTransform = mSlots[buf].mTransform; +        mCurrentScalingMode = mSlots[buf].mScalingMode; +        mCurrentTimestamp = mSlots[buf].mTimestamp;          computeCurrentTransformMatrix();          // Now that we've passed the point at which failures can happen,          // it's safe to remove the buffer from the front of the queue. - +        mQueue.erase(front); +        mDequeueCondition.signal();      } else {          // We always bind the texture even if we don't update its contents.          glBindTexture(mTexTarget, mTexName); @@ -311,7 +300,7 @@ void SurfaceTexture::computeCurrentTransformMatrix() {          }      } -    sp<GraphicBuffer>& buf(mCurrentTextureBuf); +    sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer);      float tx, ty, sx, sy;      if (!mCurrentCrop.isEmpty()) {          // In order to prevent bilinear sampling at the of the crop rectangle we @@ -383,7 +372,7 @@ void SurfaceTexture::setFrameAvailableListener(          const sp<FrameAvailableListener>& listener) {      ST_LOGV("setFrameAvailableListener");      Mutex::Autolock lock(mMutex); -    BufferQueue::setFrameAvailableListener(listener); +    mFrameAvailableListener = listener;  }  EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy, @@ -424,33 +413,22 @@ uint32_t SurfaceTexture::getCurrentScalingMode() const {  bool SurfaceTexture::isSynchronousMode() const {      Mutex::Autolock lock(mMutex); -    return BufferQueue::isSynchronousMode(); +    return mSynchronousMode;  } + +  void SurfaceTexture::abandon() {      Mutex::Autolock lock(mMutex); +    mQueue.clear();      mAbandoned = true;      mCurrentTextureBuf.clear(); - -    // destroy all egl buffers -    for (int i =0; i < NUM_BUFFER_SLOTS; i++) { -        mEGLSlots[i].mGraphicBuffer = 0; -        if (mEGLSlots[i].mEglImage != EGL_NO_IMAGE_KHR) { -            eglDestroyImageKHR(mEGLSlots[i].mEglDisplay, -                    mEGLSlots[i].mEglImage); -            mEGLSlots[i].mEglImage = EGL_NO_IMAGE_KHR; -            mEGLSlots[i].mEglDisplay = EGL_NO_DISPLAY; -        } -    } - -    // disconnect from the BufferQueue -    BufferQueue::consumerDisconnect(); +    freeAllBuffersLocked(); +    mDequeueCondition.signal();  }  void SurfaceTexture::setName(const String8& name) { -    Mutex::Autolock _l(mMutex);      mName = name; -    BufferQueue::setConsumerName(name);  }  void SurfaceTexture::dump(String8& result) const @@ -463,19 +441,68 @@ void SurfaceTexture::dump(String8& result, const char* prefix,          char* buffer, size_t SIZE) const  {      Mutex::Autolock _l(mMutex); -    snprintf(buffer, SIZE, "%smTexName=%d\n", prefix, mTexName); +    snprintf(buffer, SIZE, +            "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " +            "mPixelFormat=%d, mTexName=%d\n", +            prefix, mBufferCount, mSynchronousMode, mDefaultWidth, +            mDefaultHeight, mPixelFormat, mTexName);      result.append(buffer); +    String8 fifo; +    int fifoSize = 0; +    Fifo::const_iterator i(mQueue.begin()); +    while (i != mQueue.end()) { +        snprintf(buffer, SIZE, "%02d ", *i++); +        fifoSize++; +        fifo.append(buffer); +    } +      snprintf(buffer, SIZE, -            "%snext   : {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n" -            ,prefix, mCurrentCrop.left, +            "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n" +            "%snext   : {crop=[%d,%d,%d,%d], transform=0x%02x, FIFO(%d)={%s}}\n" +            , +            prefix, mCurrentCrop.left,              mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom, -            mCurrentTransform, mCurrentTexture +            mCurrentTransform, mCurrentTexture, +            prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, +            mNextCrop.bottom, mNextTransform, fifoSize, fifo.string()      );      result.append(buffer); - -    BufferQueue::dump(result, prefix, buffer, SIZE); +    struct { +        const char * operator()(int state) const { +            switch (state) { +                case BufferSlot::DEQUEUED: return "DEQUEUED"; +                case BufferSlot::QUEUED: return "QUEUED"; +                case BufferSlot::FREE: return "FREE"; +                default: return "Unknown"; +            } +        } +    } stateName; + +    for (int i=0 ; i<mBufferCount ; i++) { +        const BufferSlot& slot(mSlots[i]); +        snprintf(buffer, SIZE, +                "%s%s[%02d] " +                "state=%-8s, crop=[%d,%d,%d,%d], " +                "transform=0x%02x, timestamp=%lld", +                prefix, (i==mCurrentTexture)?">":" ", i, +                stateName(slot.mBufferState), +                slot.mCrop.left, slot.mCrop.top, slot.mCrop.right, +                slot.mCrop.bottom, slot.mTransform, slot.mTimestamp +        ); +        result.append(buffer); + +        const sp<GraphicBuffer>& buf(slot.mGraphicBuffer); +        if (buf != NULL) { +            snprintf(buffer, SIZE, +                    ", %p [%4ux%4u:%4u,%3X]", +                    buf->handle, buf->width, buf->height, buf->stride, +                    buf->format); +            result.append(buffer); +        } +        result.append("\n"); +    }  }  static void mtxMul(float out[16], const float a[16], const float b[16]) {  |