Beispiel #1
0
void
nsShmImage::Put(const mozilla::LayoutDeviceIntRegion& aRegion)
{
  AutoTArray<xcb_rectangle_t, 32> xrects;
  xrects.SetCapacity(aRegion.GetNumRects());

  for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
    const mozilla::LayoutDeviceIntRect &r = iter.Get();
    xcb_rectangle_t xrect = { (short)r.x, (short)r.y, (unsigned short)r.width, (unsigned short)r.height };
    xrects.AppendElement(xrect);
  }

  if (!mGC) {
    mGC = xcb_generate_id(mConnection);
    xcb_create_gc(mConnection, mGC, mWindow, 0, nullptr);
  }

  xcb_set_clip_rectangles(mConnection, XCB_CLIP_ORDERING_YX_BANDED, mGC, 0, 0,
                          xrects.Length(), xrects.Elements());

  if (mPixmap != XCB_NONE) {
    mLastRequest = xcb_copy_area_checked(mConnection, mPixmap, mWindow, mGC,
                                         0, 0, 0, 0, mSize.width, mSize.height);
  } else {
    mLastRequest = xcb_shm_put_image_checked(mConnection, mWindow, mGC,
                                             mSize.width, mSize.height,
                                             0, 0, mSize.width, mSize.height,
                                             0, 0, mDepth,
                                             XCB_IMAGE_FORMAT_Z_PIXMAP, 0,
                                             mShmSeg, 0);
  }

  xcb_flush(mConnection);
}
Beispiel #2
0
already_AddRefed<DrawTarget>
nsShmImage::CreateDrawTarget(const mozilla::LayoutDeviceIntRegion& aRegion)
{
  // Wait for any in-flight requests to complete.
  // Typically X clients would wait for a XShmCompletionEvent to be received,
  // but this works as it's sent immediately after the request is processed.
  xcb_generic_error_t* error;
  if (mLastRequest.sequence != XCB_NONE &&
      (error = xcb_request_check(mConnection, mLastRequest)))
  {
    gShmAvailable = false;
    free(error);
    return nullptr;
  }

  // Due to bug 1205045, we must avoid making GTK calls off the main thread to query window size.
  // Instead we just track the largest offset within the image we are drawing to and grow the image
  // to accomodate it. Since usually the entire window is invalidated on the first paint to it,
  // this should grow the image to the necessary size quickly without many intermediate reallocations.
  IntRect bounds = aRegion.GetBounds().ToUnknownRect();
  IntSize size(bounds.XMost(), bounds.YMost());
  if (size.width > mSize.width || size.height > mSize.height) {
    DestroyImage();
    if (!CreateImage(size)) {
      return nullptr;
    }
  }

  return gfxPlatform::GetPlatform()->CreateDrawTargetForData(
    reinterpret_cast<unsigned char*>(mShmAddr)
      + BytesPerPixel(mFormat) * (bounds.y * mSize.width + bounds.x),
    bounds.Size(),
    BytesPerPixel(mFormat) * mSize.width,
    mFormat);
}
Beispiel #3
0
void
nsShmImage::Put(const mozilla::LayoutDeviceIntRegion& aRegion)
{
  AutoTArray<xcb_rectangle_t, 32> xrects;
  xrects.SetCapacity(aRegion.GetNumRects());

  for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
    const mozilla::LayoutDeviceIntRect &r = iter.Get();
    xcb_rectangle_t xrect = { (short)r.x, (short)r.y, (unsigned short)r.width, (unsigned short)r.height };
    xrects.AppendElement(xrect);
  }

  if (!mGC) {
    mGC = xcb_generate_id(mConnection);
    xcb_create_gc(mConnection, mGC, mWindow, 0, nullptr);
  }

  xcb_set_clip_rectangles(mConnection, XCB_CLIP_ORDERING_YX_BANDED, mGC, 0, 0,
                          xrects.Length(), xrects.Elements());

  if (mPixmap != XCB_NONE) {
    mPutRequest = xcb_copy_area_checked(mConnection, mPixmap, mWindow, mGC,
                                        0, 0, 0, 0, mSize.width, mSize.height);
  } else {
    mPutRequest = xcb_shm_put_image_checked(mConnection, mWindow, mGC,
                                            mSize.width, mSize.height,
                                            0, 0, mSize.width, mSize.height,
                                            0, 0, mDepth,
                                            XCB_IMAGE_FORMAT_Z_PIXMAP, 0,
                                            mShmSeg, 0);
  }

  // Send a request that returns a response so that we don't have to start a
  // sync in nsShmImage::CreateDrawTarget to retrieve the result of mPutRequest.
  mSyncRequest = xcb_get_input_focus(mConnection);
  mRequestPending = true;

  xcb_flush(mConnection);
}