Example #1
0
/*static*/void
gfxPlatform::InitOffMainThreadCompositing()
{
  static bool inited;
  if (inited) {
    return;
  }
  inited = true;

  bool useOffMainThreadCompositing = false;
#ifdef MOZ_X11
  // On X11 platforms only use OMTC if firefox was initalized with thread-safe 
  // X11 (else it would crash).
  useOffMainThreadCompositing = (PR_GetEnv("MOZ_USE_OMTC") != NULL);
#else
  useOffMainThreadCompositing = Preferences::GetBool(
    "layers.offmainthreadcomposition.enabled", 
    false);
#endif

  printf_stderr("Are we using off-main-thread compositing? %s\n",
                useOffMainThreadCompositing ? "yes" : "NO");

  if (useOffMainThreadCompositing) {
    CompositorParent::CreateCompositorMap();
    CompositorParent::CreateThread();

    ImageBridgeChild::Create(new base::Thread("ImageBridgeChild"));
    ImageBridgeChild* imageBridgeChild = ImageBridgeChild::GetSingleton();
    ImageBridgeParent* imageBridgeParent = new ImageBridgeParent(
      CompositorParent::CompositorLoop());
    imageBridgeChild->ConnectAsync(imageBridgeParent);
  }
}
void GonkNativeWindow::freeBufferLocked(int i)
{
    ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
    if (mSlots[i].mGraphicBuffer != NULL) {
        // Don't destroy the gralloc buffer if it is still in the
        // video stream awaiting rendering.
        if (mSlots[i].mBufferState != BufferSlot::RENDERING) {
            ibc->DeallocSurfaceDescriptorGralloc(mSlots[i].mSurfaceDescriptor);
        }
        mSlots[i].mGraphicBuffer = NULL;
        mSlots[i].mBufferState = BufferSlot::FREE;
        mSlots[i].mFrameNumber = 0;
    }
}
Example #3
0
void GonkNativeWindow::releaseBufferFreeListUnlocked(nsTArray<SurfaceDescriptor>& freeList)
{
    // This function MUST ONLY be called with mMutex unlocked; else there
    // is a risk of deadlock with the ImageBridge thread.

    CNW_LOGD("releaseBufferFreeListUnlocked: E");
    ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();

    for (uint32_t i = 0; i < freeList.Length(); ++i) {
        ibc->DeallocSurfaceDescriptorGralloc(freeList[i]);
    }

    freeList.Clear();
    CNW_LOGD("releaseBufferFreeListUnlocked: X");
}
void CameraGraphicBuffer::Unlock() {
    if (mLocked) {
        android::sp<android::Fence> fence;
        fence = mReleaseFenceHandle.IsValid() ? mReleaseFenceHandle.mFence : Fence::NO_FENCE;
        // The window might have been destroyed. The buffer is no longer
        // valid at that point.
        sp<GonkNativeWindow> window = mNativeWindow.promote();
        if (window.get() && window->returnBuffer(mIndex, mGeneration, fence)) {
            mLocked = false;
        } else {
            // If the window doesn't exist any more, release the buffer
            // directly.
            ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
            ibc->DeallocSurfaceDescriptorGralloc(mSurfaceDescriptor);
        }
    }
}
Example #5
0
status_t GonkNativeWindow::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
        uint32_t format, uint32_t usage)
{
    if ((w && !h) || (!w && h)) {
        CNW_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
        return BAD_VALUE;
    }

    status_t returnFlags(OK);
    bool updateFormat = false;
    uint32_t generation;
    bool alloc = false;
    int buf = INVALID_BUFFER_SLOT;
    SurfaceDescriptor descOld;

    {
        Mutex::Autolock lock(mMutex);
        generation = mGeneration;

        int found = -1;
        int dequeuedCount = 0;
        int renderingCount = 0;
        bool tryAgain = true;

        CNW_LOGD("dequeueBuffer: E");
        while (tryAgain) {
            if (mAbandoned) {
                CNW_LOGE("dequeueBuffer: GonkNativeWindow has been abandoned!");
                return NO_INIT;
            }
            // look for a free buffer to give to the client
            found = INVALID_BUFFER_SLOT;
            dequeuedCount = 0;
            renderingCount = 0;
            for (int i = 0; i < mBufferCount; i++) {
                const int state = mSlots[i].mBufferState;
                if (state == BufferSlot::DEQUEUED) {
                    dequeuedCount++;
                }
                else if (state == BufferSlot::RENDERING) {
                    renderingCount++;
                }
                else if (state == BufferSlot::FREE) {
                    /* We return the oldest of the free buffers to avoid
                     * stalling the producer if possible.  This is because
                     * the consumer may still have pending reads of the
                     * buffers in flight.
                     */
                    if (found < 0 ||
                        mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
                        found = i;
                    }
                }
            }

            // See whether a buffer has been in RENDERING state since the last
            // setBufferCount so we know whether to perform the
            // MIN_UNDEQUEUED_BUFFERS check below.
            if (renderingCount > 0) {
                // make sure the client is not trying to dequeue more buffers
                // than allowed.
                const int avail = mBufferCount - (dequeuedCount + 1);
                if (avail < MIN_UNDEQUEUED_BUFFERS) {
                    CNW_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded "
                            "(dequeued=%d)",
                            MIN_UNDEQUEUED_BUFFERS,
                            dequeuedCount);
                    return -EBUSY;
                }
            }

            // we're in synchronous mode and didn't find a buffer, we need to
            // wait for some buffers to be consumed
            tryAgain = (found == INVALID_BUFFER_SLOT);
            if (tryAgain) {
                CNW_LOGD("dequeueBuffer: Try again");
                mDequeueCondition.wait(mMutex);
                CNW_LOGD("dequeueBuffer: Now");
            }
        }

        if (found == INVALID_BUFFER_SLOT) {
            // This should not happen.
            CNW_LOGE("dequeueBuffer: no available buffer slots");
            return -EBUSY;
        }

        buf = found;
        *outBuf = found;

        const bool useDefaultSize = !w && !h;
        if (useDefaultSize) {
            // use the default size
            w = mDefaultWidth;
            h = mDefaultHeight;
        }

        updateFormat = (format != 0);
        if (!updateFormat) {
            // keep the current (or default) format
            format = mPixelFormat;
        }

        mSlots[buf].mBufferState = BufferSlot::DEQUEUED;

        const sp<GraphicBuffer>& gbuf(mSlots[buf].mGraphicBuffer);
        alloc = (gbuf == NULL);
        if ((gbuf!=NULL) &&
           ((uint32_t(gbuf->width)  != w) ||
            (uint32_t(gbuf->height) != h) ||
            (uint32_t(gbuf->format) != format) ||
            ((uint32_t(gbuf->usage) & usage) != usage))) {
            alloc = true;
            descOld = mSlots[buf].mSurfaceDescriptor;
        }
    }
    
    // At this point, the buffer is now marked DEQUEUED, and no one else
    // should touch it, except for freeAllBuffersLocked(); we handle that
    // after trying to create the surface descriptor below.
    //
    // So we don't need mMutex locked, which would otherwise run the risk
    // of a deadlock on calling AllocSurfaceDescriptorGralloc().    

    SurfaceDescriptor desc;
    ImageBridgeChild* ibc;
    sp<GraphicBuffer> graphicBuffer;
    if (alloc) {
        usage |= GraphicBuffer::USAGE_HW_TEXTURE;
        status_t error;
        ibc = ImageBridgeChild::GetSingleton();
        CNW_LOGD("dequeueBuffer: about to alloc surface descriptor");
        ibc->AllocSurfaceDescriptorGralloc(IntSize(w, h),
                                           format,
                                           usage,
                                           &desc);
        // We can only use a gralloc buffer here.  If we didn't get
        // one back, something went wrong.
        CNW_LOGD("dequeueBuffer: got surface descriptor");
        if (SurfaceDescriptor::TSurfaceDescriptorGralloc != desc.type()) {
            MOZ_ASSERT(SurfaceDescriptor::T__None == desc.type());
            CNW_LOGE("dequeueBuffer: failed to alloc gralloc buffer");
            return -ENOMEM;
        }
        graphicBuffer = GrallocBufferActor::GetFrom(desc.get_SurfaceDescriptorGralloc());
        error = graphicBuffer->initCheck();
        if (error != NO_ERROR) {
            CNW_LOGE("dequeueBuffer: createGraphicBuffer failed with error %d", error);
            return error;
        }
    }

    bool tooOld = false;
    {
        Mutex::Autolock lock(mMutex);
        if (generation == mGeneration) {
            if (updateFormat) {
                mPixelFormat = format;
            }
            if (alloc) {
                mSlots[buf].mGraphicBuffer = graphicBuffer;
                mSlots[buf].mSurfaceDescriptor = desc;
                mSlots[buf].mSurfaceDescriptor.get_SurfaceDescriptorGralloc().external() = true;
                mSlots[buf].mRequestBufferCalled = false;

                returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
            }
            CNW_LOGD("dequeueBuffer: returning slot=%d buf=%p ", buf,
                    mSlots[buf].mGraphicBuffer->handle);
        } else {
            tooOld = true;
        }
    }

    if (alloc && IsSurfaceDescriptorValid(descOld)) {
        ibc->DeallocSurfaceDescriptorGralloc(descOld);
    }

    if (alloc && tooOld) {
        ibc->DeallocSurfaceDescriptorGralloc(desc);
    }

    CNW_LOGD("dequeueBuffer: returning slot=%d buf=%p ", buf,
            mSlots[buf].mGraphicBuffer->handle );

    CNW_LOGD("dequeueBuffer: X");
    return returnFlags;
}
void
GrallocPlanarYCbCrImage::SetData(const Data& aData)
{
  NS_PRECONDITION(aData.mYSize.width % 2 == 0, "Image should have even width");
  NS_PRECONDITION(aData.mYSize.height % 2 == 0, "Image should have even height");
  NS_PRECONDITION(aData.mYStride % 16 == 0, "Image should have stride of multiple of 16 pixels");

  mData = aData;
  mSize = aData.mPicSize;

  if (mSurfaceDescriptor.type() == SurfaceDescriptor::T__None) {
    ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
    ibc->AllocSurfaceDescriptorGralloc(aData.mYSize,
                                       HAL_PIXEL_FORMAT_YV12,
                                       GraphicBuffer::USAGE_SW_READ_OFTEN |
                                       GraphicBuffer::USAGE_SW_WRITE_OFTEN |
                                       GraphicBuffer::USAGE_HW_TEXTURE,
                                       &mSurfaceDescriptor);
  }
  sp<GraphicBuffer> graphicBuffer =
    GrallocBufferActor::GetFrom(mSurfaceDescriptor.get_SurfaceDescriptorGralloc());
  if (!graphicBuffer.get()) {
    return;
  }

  if (graphicBuffer->initCheck() != NO_ERROR) {
    return;
  }

  void* vaddr;
  if (graphicBuffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
                          &vaddr) != OK) {
    return;
  }

  uint8_t* yChannel = static_cast<uint8_t*>(vaddr);
  gfxIntSize ySize = gfxIntSize(aData.mYSize.width,
                                aData.mYSize.height);
  int32_t yStride = graphicBuffer->getStride();

  uint8_t* vChannel = yChannel + (yStride * ySize.height);
  gfxIntSize uvSize = gfxIntSize(ySize.width / 2,
                                 ySize.height / 2);
  // Align to 16 bytes boundary
  int32_t uvStride = ((yStride / 2) + 15) & ~0x0F;
  uint8_t* uChannel = vChannel + (uvStride * uvSize.height);

  // Memory outside of the image width may not writable. If the stride
  // equals to the image width then we can use only one copy.
  if (yStride == mData.mYStride &&
      yStride == ySize.width) {
    memcpy(yChannel, mData.mYChannel, yStride * ySize.height);
  } else {
    for (int i = 0; i < ySize.height; i++) {
      memcpy(yChannel + i * yStride,
             mData.mYChannel + i * mData.mYStride,
             ySize.width);
    }
  }
  if (uvStride == mData.mCbCrStride &&
      uvStride == uvSize.width) {
    memcpy(uChannel, mData.mCbChannel, uvStride * uvSize.height);
    memcpy(vChannel, mData.mCrChannel, uvStride * uvSize.height);
  } else {
    for (int i = 0; i < uvSize.height; i++) {
      memcpy(uChannel + i * uvStride,
             mData.mCbChannel + i * mData.mCbCrStride,
             uvSize.width);
      memcpy(vChannel + i * uvStride,
             mData.mCrChannel + i * mData.mCbCrStride,
             uvSize.width);
    }
  }
  graphicBuffer->unlock();
}
GrallocPlanarYCbCrImage::~GrallocPlanarYCbCrImage()
{
  ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
  ibc->DeallocSurfaceDescriptorGralloc(mSurfaceDescriptor);
}
int GonkNativeWindow::dequeueBuffer(android_native_buffer_t** buffer)
{
    Mutex::Autolock lock(mMutex);

    int found = -1;
    int dequeuedCount = 0;
    bool tryAgain = true;

    CNW_LOGD("dequeueBuffer: E");
    while (tryAgain) {
        // look for a free buffer to give to the client
        found = INVALID_BUFFER_SLOT;
        dequeuedCount = 0;
        for (int i = 0; i < mBufferCount; i++) {
            const int state = mSlots[i].mBufferState;
            if (state == BufferSlot::DEQUEUED) {
                dequeuedCount++;
            }
            else if (state == BufferSlot::FREE) {
                /* We return the oldest of the free buffers to avoid
                 * stalling the producer if possible.  This is because
                 * the consumer may still have pending reads of the
                 * buffers in flight.
                 */
                bool isOlder = mSlots[i].mFrameNumber < mSlots[found].mFrameNumber;
                if (found < 0 || isOlder) {
                    found = i;
                }
            }
        }

        // we're in synchronous mode and didn't find a buffer, we need to
        // wait for some buffers to be consumed
        tryAgain = (found == INVALID_BUFFER_SLOT);
        if (tryAgain) {
            CNW_LOGD("dequeueBuffer: Try again");
            mDequeueCondition.wait(mMutex);
            CNW_LOGD("dequeueBuffer: Now");
        }
    }

    if (found == INVALID_BUFFER_SLOT) {
        // This should not happen.
        CNW_LOGE("dequeueBuffer: no available buffer slots");
        return -EBUSY;
    }

    const int buf = found;

    // buffer is now in DEQUEUED
    mSlots[buf].mBufferState = BufferSlot::DEQUEUED;

    const sp<GraphicBuffer>& gbuf(mSlots[buf].mGraphicBuffer);

    if (gbuf == NULL) {
        status_t error;
        SurfaceDescriptor buffer;
        ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
        ibc->AllocSurfaceDescriptorGralloc(gfxIntSize(mDefaultWidth, mDefaultHeight),
                                           mPixelFormat,
                                           mUsage,
                                           &buffer);
        sp<GraphicBuffer> graphicBuffer =
          GrallocBufferActor::GetFrom(buffer.get_SurfaceDescriptorGralloc());
        if (!graphicBuffer.get()) {
            return -ENOMEM;
        }
        error = graphicBuffer->initCheck();
        if (error != NO_ERROR) {
            CNW_LOGE("dequeueBuffer: createGraphicBuffer failed with error %d",error);
            return error;
        }
        mSlots[buf].mGraphicBuffer = graphicBuffer;
        mSlots[buf].mSurfaceDescriptor = buffer;
        mSlots[buf].mSurfaceDescriptor.get_SurfaceDescriptorGralloc().external() = true;
    }
    *buffer = mSlots[buf].mGraphicBuffer.get();

    CNW_LOGD("dequeueBuffer: returning slot=%d buf=%p ", buf,
            mSlots[buf].mGraphicBuffer->handle );

    CNW_LOGD("dequeueBuffer: X");
    return NO_ERROR;
}