예제 #1
0
void Mask::CreateBoundaryImageInRegion(const itk::ImageRegion<2>& region, BoundaryImageType* const boundaryImage,
                                       const HoleMaskPixelTypeEnum& whichSideOfBoundary) const
{
  // Create a binary image of the mask
  unsigned char holeColor = 255;
  unsigned char validColor = 0;
  UnsignedCharImageType::Pointer fullBinaryImage = UnsignedCharImageType::New();
  CreateBinaryImageInRegion(region, fullBinaryImage, holeColor, validColor);

  // Extract the relevant region from the binary image
  UnsignedCharImageType::Pointer binaryImage = UnsignedCharImageType::New();
  binaryImage->SetRegions(region);
  binaryImage->Allocate();
  CopyRegion(fullBinaryImage.GetPointer(), binaryImage.GetPointer(), region, region);

  // Extract the relevant region from the mask
  Mask::Pointer extractedRegionMask = Mask::New();
  extractedRegionMask->SetRegions(region);
  extractedRegionMask->Allocate();
  CopyRegion(this, extractedRegionMask.GetPointer(), region, region);

  // Since the hole is white (we have specified this at the beginning of this function),
  // we want the foreground value of the contour filter to be black.
  // This means that the boundary will be detected in the black pixel region,
  // which is on the outside edge of the hole like we want. However,
  // The BinaryContourImageFilter will change all non-boundary pixels to the background color,
  // so the resulting output will be inverted - the boundary pixels will be black and the
  // non-boundary pixels will be white.

  // Find the boundary
  typedef itk::BinaryContourImageFilter<UnsignedCharImageType, UnsignedCharImageType> binaryContourImageFilterType;
  binaryContourImageFilterType::Pointer binaryContourFilter = binaryContourImageFilterType::New();
  binaryContourFilter->SetInput(binaryImage);
  binaryContourFilter->SetFullyConnected(true);

  if(whichSideOfBoundary == HoleMaskPixelTypeEnum::VALID)
  {
    // we want the boundary pixels to be in the valid region.
      binaryContourFilter->SetForegroundValue(validColor);
      binaryContourFilter->SetBackgroundValue(holeColor);
  }
  else if(whichSideOfBoundary == HoleMaskPixelTypeEnum::HOLE)
  {
    // we want the boundary pixels to be in the hole region.
      binaryContourFilter->SetForegroundValue(holeColor);
      binaryContourFilter->SetBackgroundValue(validColor);
  }
  else
  {
    throw std::runtime_error("An invalid side of the boundary was requested.");
  }

  binaryContourFilter->Update();

  DeepCopy(binaryContourFilter->GetOutput(), boundaryImage);
}
Result GraphicsInterfaceD3D11::writeTexture2D(void *dst_tex_, int width, int height, TextureFormat format, const void *src, size_t write_size)
{
    if (write_size == 0) { return Result::OK; }
    if (!dst_tex_ || !src) { return Result::InvalidParameter; }

    auto *dst_tex = (ID3D11Texture2D*)dst_tex_;

    auto proc_write = [this](ID3D11Texture2D *tex, int width, int height, TextureFormat format, const void *src, size_t write_size) -> HRESULT {
        D3D11_MAPPED_SUBRESOURCE mapped = { 0 };
        auto hr = m_context->Map(tex, 0, D3D11_MAP_WRITE, 0, &mapped);
        if (FAILED(hr)) { return hr; }

        auto *dst_pixels = (char*)mapped.pData;
        auto *src_pixels = (const char*)src;
        int dst_pitch = mapped.RowPitch;
        int src_pitch = width * GetTexelSize(format);
        int num_rows = std::min<int>(height, (int)ceildiv<size_t>(write_size, src_pitch));
        CopyRegion(dst_pixels, dst_pitch, src_pixels, src_pitch, num_rows);

        m_context->Unmap(tex, 0);
        return S_OK;
    };


    // try direct access
    auto hr = proc_write(dst_tex, width, height, format, src, write_size);
    if (SUCCEEDED(hr)) { return Result::OK; }


    // try copy-via-staging
    auto staging = createStagingTexture(width, height, format, StagingFlag::Upload);
    hr = proc_write(staging.Get(), width, height, format, src, write_size);
    m_context->CopyResource(dst_tex, staging.Get());

    return TranslateReturnCode(hr);
}
Result GraphicsInterfaceD3D11::readTexture2D(void *dst, size_t read_size, void *src_tex_, int width, int height, TextureFormat format)
{
    if (read_size == 0) { return Result::OK; }
    if (!dst || !src_tex_) { return Result::InvalidParameter; }

    auto *src_tex = (ID3D11Texture2D*)src_tex_;

    auto proc_read = [this](void *dst, size_t dst_size, ID3D11Texture2D *tex, int width, int height, TextureFormat format) -> HRESULT {
        D3D11_MAPPED_SUBRESOURCE mapped = { 0 };
        auto hr = m_context->Map(tex, 0, D3D11_MAP_READ, 0, &mapped);
        if (FAILED(hr)) { return hr; }

        auto *dst_pixels = (char*)dst;
        auto *src_pixels = (const char*)mapped.pData;
        int dst_pitch = width * GetTexelSize(format);
        int src_pitch = mapped.RowPitch;
        int num_rows = std::min<int>(height, (int)ceildiv<size_t>(dst_size, dst_pitch));
        CopyRegion(dst_pixels, dst_pitch, src_pixels, src_pitch, num_rows);

        m_context->Unmap(tex, 0);
        return S_OK;
    };

    // try direct access
    auto hr = proc_read(dst, read_size, src_tex, width, height, format);
    if (SUCCEEDED(hr)) { return Result::OK; }


    // try copy-via-staging
    auto staging = createStagingTexture(width, height, format, StagingFlag::Readback);
    m_context->CopyResource(staging.Get(), src_tex);
    sync(); // Map() doesn't wait completion of above CopyResource(). manual synchronization is required.
    hr = proc_read(dst, read_size, staging.Get(), width, height, format);

    return TranslateReturnCode(hr);
}
예제 #4
0
void
ThebesLayerD3D10::Validate(ReadbackProcessor *aReadback)
{
  if (mVisibleRegion.IsEmpty()) {
    return;
  }

  nsIntRect newTextureRect = mVisibleRegion.GetBounds();

  SurfaceMode mode = GetSurfaceMode();
  if (mode == SURFACE_COMPONENT_ALPHA &&
      (!mParent || !mParent->SupportsComponentAlphaChildren())) {
    mode = SURFACE_SINGLE_CHANNEL_ALPHA;
  }
  // If we have a transform that requires resampling of our texture, then
  // we need to make sure we don't sample pixels that haven't been drawn.
  // We clamp sample coordinates to the texture rect, but when the visible region
  // doesn't fill the entire texture rect we need to make sure we draw all the
  // pixels in the texture rect anyway in case they get sampled.
  nsIntRegion neededRegion = mVisibleRegion;
  if (!neededRegion.GetBounds().IsEqualInterior(newTextureRect) ||
      neededRegion.GetNumRects() > 1) {
    gfxMatrix transform2d;
    if (!GetEffectiveTransform().Is2D(&transform2d) ||
        transform2d.HasNonIntegerTranslation()) {
      neededRegion = newTextureRect;
      if (mode == SURFACE_OPAQUE) {
        // We're going to paint outside the visible region, but layout hasn't
        // promised that it will paint opaquely there, so we'll have to
        // treat this layer as transparent.
        mode = SURFACE_SINGLE_CHANNEL_ALPHA;
      }
    }
  }
  mCurrentSurfaceMode = mode;

  VerifyContentType(mode);

  nsTArray<ReadbackProcessor::Update> readbackUpdates;
  nsIntRegion readbackRegion;
  if (aReadback && UsedForReadback()) {
    aReadback->GetThebesLayerUpdates(this, &readbackUpdates, &readbackRegion);
  }

  if (mTexture) {
    if (!mTextureRect.IsEqualInterior(newTextureRect)) {
      nsRefPtr<ID3D10Texture2D> oldTexture = mTexture;
      mTexture = nullptr;
      nsRefPtr<ID3D10Texture2D> oldTextureOnWhite = mTextureOnWhite;
      mTextureOnWhite = nullptr;

      nsIntRegion retainRegion = mTextureRect;
      // Old visible region will become the region that is covered by both the
      // old and the new visible region.
      retainRegion.And(retainRegion, mVisibleRegion);
      // No point in retaining parts which were not valid.
      retainRegion.And(retainRegion, mValidRegion);

      CreateNewTextures(gfxIntSize(newTextureRect.width, newTextureRect.height), mode);

      nsIntRect largeRect = retainRegion.GetLargestRectangle();

      // If we had no hardware texture before, or have no retained area larger than
      // the retention threshold, we're not retaining and are done here.
      // If our texture creation failed this can mean a device reset is pending
      // and we should silently ignore the failure. In the future when device
      // failures are properly handled we should test for the type of failure
      // and gracefully handle different failures. See bug 569081.
      if (!oldTexture || !mTexture ||
          largeRect.width * largeRect.height < RETENTION_THRESHOLD) {
        mValidRegion.SetEmpty();
      } else {
        CopyRegion(oldTexture, mTextureRect.TopLeft(),
                   mTexture, newTextureRect.TopLeft(),
                   retainRegion, &mValidRegion);
        if (oldTextureOnWhite) {
          CopyRegion(oldTextureOnWhite, mTextureRect.TopLeft(),
                     mTextureOnWhite, newTextureRect.TopLeft(),
                     retainRegion, &mValidRegion);
        }
      }
    }
  }
  mTextureRect = newTextureRect;

  if (!mTexture || (mode == SURFACE_COMPONENT_ALPHA && !mTextureOnWhite)) {
    CreateNewTextures(gfxIntSize(newTextureRect.width, newTextureRect.height), mode);
    mValidRegion.SetEmpty();
  }

  nsIntRegion drawRegion;
  drawRegion.Sub(neededRegion, mValidRegion);

  if (!drawRegion.IsEmpty()) {
    LayerManagerD3D10::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
    if (!cbInfo.Callback) {
      NS_ERROR("D3D10 should never need to update ThebesLayers in an empty transaction");
      return;
    }

    DrawRegion(drawRegion, mode);

    if (readbackUpdates.Length() > 0) {
      CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
                                 newTextureRect.width, newTextureRect.height,
                                 1, 1, 0, D3D10_USAGE_STAGING,
                                 D3D10_CPU_ACCESS_READ);

      nsRefPtr<ID3D10Texture2D> readbackTexture;
      HRESULT hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(readbackTexture));
      if (FAILED(hr)) {
        LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("ThebesLayerD3D10::Validate(): Failed to create texture"),
                                         hr);
        return;
      }

      device()->CopyResource(readbackTexture, mTexture);

      for (uint32_t i = 0; i < readbackUpdates.Length(); i++) {
        mD3DManager->readbackManager()->PostTask(readbackTexture,
                                                 &readbackUpdates[i],
                                                 gfxPoint(newTextureRect.x, newTextureRect.y));
      }
    }

    mValidRegion = neededRegion;
  }
}