Ejemplo n.º 1
0
// See bug 1083071. On some drivers, Direct3D 11 CreateShaderResourceView fails
// with E_OUTOFMEMORY.
static bool
DoesTextureSharingWorkInternal(ID3D11Device *device, DXGI_FORMAT format, UINT bindflags)
{
  // CreateTexture2D is known to crash on lower feature levels, see bugs
  // 1170211 and 1089413.
  if (device->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0) {
    return false;
  }

  if (gfxPrefs::Direct2DForceEnabled() ||
      gfxConfig::IsForcedOnByUser(Feature::HW_COMPOSITING))
  {
    return true;
  }

  if (GetModuleHandleW(L"atidxx32.dll")) {
    nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
    if (gfxInfo) {
      nsString vendorID, vendorID2;
      gfxInfo->GetAdapterVendorID(vendorID);
      gfxInfo->GetAdapterVendorID2(vendorID2);
      if (vendorID.EqualsLiteral("0x8086") && vendorID2.IsEmpty()) {
        if (!gfxPrefs::LayersAMDSwitchableGfxEnabled()) {
          return false;
        }
        gfxCriticalError(CriticalLog::DefaultOptions(false)) << "PossiblyBrokenSurfaceSharing_UnexpectedAMDGPU";
      }
    }
  }

  RefPtr<ID3D11Texture2D> texture;
  D3D11_TEXTURE2D_DESC desc;
  const int texture_size = 32;
  desc.Width = texture_size;
  desc.Height = texture_size;
  desc.MipLevels = 1;
  desc.ArraySize = 1;
  desc.Format = format;
  desc.SampleDesc.Count = 1;
  desc.SampleDesc.Quality = 0;
  desc.Usage = D3D11_USAGE_DEFAULT;
  desc.CPUAccessFlags = 0;
  desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
  desc.BindFlags = bindflags;

  uint32_t color[texture_size * texture_size];
  for (size_t i = 0; i < sizeof(color)/sizeof(color[0]); i++) {
    color[i] = 0xff00ffff;
  }
  // XXX If we pass the data directly at texture creation time we
  //     get a crash on Intel 8.5.10.[18xx-1994] drivers.
  //     We can work around this issue by doing UpdateSubresource.
  if (!TryCreateTexture2D(device, &desc, nullptr, texture)) {
    gfxCriticalNote << "DoesD3D11TextureSharingWork_TryCreateTextureFailure";
    return false;
  }

  RefPtr<IDXGIKeyedMutex> sourceSharedMutex;
  texture->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)getter_AddRefs(sourceSharedMutex));
  if (FAILED(sourceSharedMutex->AcquireSync(0, 30*1000))) {
    gfxCriticalError() << "DoesD3D11TextureSharingWork_SourceMutexTimeout";
    // only wait for 30 seconds
    return false;
  }

  RefPtr<ID3D11DeviceContext> deviceContext;
  device->GetImmediateContext(getter_AddRefs(deviceContext));

  int stride = texture_size * 4;
  deviceContext->UpdateSubresource(texture, 0, nullptr, color, stride, stride * texture_size);

  if (FAILED(sourceSharedMutex->ReleaseSync(0))) {
    gfxCriticalError() << "DoesD3D11TextureSharingWork_SourceReleaseSyncTimeout";
    return false;
  }

  HANDLE shareHandle;
  RefPtr<IDXGIResource> otherResource;
  if (FAILED(texture->QueryInterface(__uuidof(IDXGIResource),
                                     getter_AddRefs(otherResource))))
  {
    gfxCriticalError() << "DoesD3D11TextureSharingWork_GetResourceFailure";
    return false;
  }

  if (FAILED(otherResource->GetSharedHandle(&shareHandle))) {
    gfxCriticalError() << "DoesD3D11TextureSharingWork_GetSharedTextureFailure";
    return false;
  }

  RefPtr<ID3D11Resource> sharedResource;
  RefPtr<ID3D11Texture2D> sharedTexture;
  if (FAILED(device->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource),
                                        getter_AddRefs(sharedResource))))
  {
    gfxCriticalError(CriticalLog::DefaultOptions(false)) << "OpenSharedResource failed for format " << format;
    return false;
  }

  if (FAILED(sharedResource->QueryInterface(__uuidof(ID3D11Texture2D),
                                            getter_AddRefs(sharedTexture))))
  {
    gfxCriticalError() << "DoesD3D11TextureSharingWork_GetSharedTextureFailure";
    return false;
  }

  // create a staging texture for readback
  RefPtr<ID3D11Texture2D> cpuTexture;
  desc.Usage = D3D11_USAGE_STAGING;
  desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  desc.MiscFlags = 0;
  desc.BindFlags = 0;
  if (FAILED(device->CreateTexture2D(&desc, nullptr, getter_AddRefs(cpuTexture)))) {
    gfxCriticalError() << "DoesD3D11TextureSharingWork_CreateTextureFailure";
    return false;
  }

  RefPtr<IDXGIKeyedMutex> sharedMutex;
  sharedResource->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)getter_AddRefs(sharedMutex));
  {
    HRESULT hr;
    AutoTextureLock lock(sharedMutex, hr, 30*1000);
    if (FAILED(hr)) {
      gfxCriticalError() << "DoesD3D11TextureSharingWork_AcquireSyncTimeout";
      // only wait for 30 seconds
      return false;
    }

    // Copy to the cpu texture so that we can readback
    deviceContext->CopyResource(cpuTexture, sharedTexture);

    // We only need to hold on to the mutex during the copy.
    sharedMutex->ReleaseSync(0);
  }

  D3D11_MAPPED_SUBRESOURCE mapped;
  uint32_t resultColor = 0;
  if (SUCCEEDED(deviceContext->Map(cpuTexture, 0, D3D11_MAP_READ, 0, &mapped))) {
    // read the texture
    resultColor = *(uint32_t*)mapped.pData;
    deviceContext->Unmap(cpuTexture, 0);
  } else {
    gfxCriticalError() << "DoesD3D11TextureSharingWork_MapFailed";
    return false;
  }

  // check that the color we put in is the color we get out
  if (resultColor != color[0]) {
    // Shared surfaces seem to be broken on dual AMD & Intel HW when using the
    // AMD GPU
    gfxCriticalNote << "DoesD3D11TextureSharingWork_ColorMismatch";
    return false;
  }

  RefPtr<ID3D11ShaderResourceView> sharedView;

  // This if(FAILED()) is the one that actually fails on systems affected by bug 1083071.
  if (FAILED(device->CreateShaderResourceView(sharedTexture, NULL, getter_AddRefs(sharedView)))) {
    gfxCriticalNote << "CreateShaderResourceView failed for format" << format;
    return false;
  }

  return true;
}
Ejemplo n.º 2
0
void
CanvasClientSharedSurface::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
{
  auto gl = aLayer->mGLContext;
  gl->MakeCurrent();

  RefPtr<TextureClient> newFront;

  if (aLayer->mGLFrontbuffer) {
    mShSurfClient = CloneSurface(aLayer->mGLFrontbuffer.get(), aLayer->mFactory.get());
    if (!mShSurfClient) {
      gfxCriticalError() << "Invalid canvas front buffer";
      return;
    }
  } else {
    mShSurfClient = gl->Screen()->Front();
    if (!mShSurfClient) {
      return;
    }
  }
  MOZ_ASSERT(mShSurfClient);

  newFront = mShSurfClient;

  SharedSurface* surf = mShSurfClient->Surf();

  // Readback if needed.
  mReadbackClient = nullptr;

  auto forwarder = GetForwarder();

  bool needsReadback = (surf->mType == SharedSurfaceType::Basic);
  if (needsReadback) {
    TextureFlags flags = aLayer->Flags() |
                         TextureFlags::IMMUTABLE;

    auto manager = aLayer->ClientManager();
    auto shadowForwarder = manager->AsShadowForwarder();
    auto layersBackend = shadowForwarder->GetCompositorBackendType();
    mReadbackClient = TexClientFromReadback(surf, forwarder, flags, layersBackend);

    newFront = mReadbackClient;
  } else {
    mReadbackClient = nullptr;
  }

  MOZ_ASSERT(newFront);
  if (!newFront) {
    // May happen in a release build in case of memory pressure.
    gfxCriticalError() << "Failed to allocate a TextureClient for SharedSurface Canvas. Size: " << aSize;
    return;
  }

  if (mFront) {
    if (mFront->GetFlags() & TextureFlags::RECYCLE) {
      mFront->WaitForCompositorRecycle();
    }
  }

  mFront = newFront;

  // Add the new TexClient.
  MOZ_ALWAYS_TRUE( AddTextureClient(mFront) );

  forwarder->UseTexture(this, mFront);
}
Ejemplo n.º 3
0
void
CanvasClientSharedSurface::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
{
  if (mFront) {
    mPrevFront = mFront;
    mFront = nullptr;
  }

  auto gl = aLayer->mGLContext;
  gl->MakeCurrent();

  if (aLayer->mGLFrontbuffer) {
    mFront = CloneSurface(aLayer->mGLFrontbuffer.get(), aLayer->mFactory.get());
    if (mFront)
      mFront->Surf()->Fence();
  } else {
    mFront = gl->Screen()->Front();
    if (!mFront)
      return;
  }
  MOZ_ASSERT(mFront);

  // Alright, now sort out the IPC goop.
  SharedSurface* surf = mFront->Surf();
  auto forwarder = GetForwarder();
  auto flags = GetTextureFlags() | TextureFlags::IMMUTABLE;

  // Get a TexClient from our surf.
  RefPtr<TextureClient> newTex = TexClientFromShSurf(GetForwarder(), surf, flags);
  if (!newTex) {
    auto manager = aLayer->ClientManager();
    auto shadowForwarder = manager->AsShadowForwarder();
    auto layersBackend = shadowForwarder->GetCompositorBackendType();

    newTex = TexClientFromReadback(surf, forwarder, flags, layersBackend);
  }
  MOZ_ASSERT(newTex);
  if (!newTex) {
    // May happen in a release build in case of memory pressure.
    gfxCriticalError() << "Failed to allocate a TextureClient for SharedSurface Canvas. size: " << aSize;
    return;
  }

  // Add the new TexClient.
  MOZ_ALWAYS_TRUE( AddTextureClient(newTex) );

  // Remove the old TexClient.
  if (mFrontTex) {
    // remove old buffer from CompositableHost
    RefPtr<AsyncTransactionTracker> tracker = new RemoveTextureFromCompositableTracker();
    // Hold TextureClient until transaction complete.
    tracker->SetTextureClient(mFrontTex);
    mFrontTex->SetRemoveFromCompositableTracker(tracker);
    // RemoveTextureFromCompositableAsync() expects CompositorChild's presence.
    GetForwarder()->RemoveTextureFromCompositableAsync(tracker, this, mFrontTex);

    mFrontTex = nullptr;
  }

  // Use the new TexClient.
  mFrontTex = newTex;

  forwarder->UseTexture(this, mFrontTex);
}
Ejemplo n.º 4
0
bool
D3D11YCbCrImage::SetData(KnowsCompositor* aAllocator,
                         ImageContainer* aContainer,
                         const PlanarYCbCrData& aData)
{
  mPictureRect = IntRect(
    aData.mPicX, aData.mPicY, aData.mPicSize.width, aData.mPicSize.height);
  mYSize = aData.mYSize;
  mCbCrSize = aData.mCbCrSize;
  mColorSpace = aData.mYUVColorSpace;

  D3D11YCbCrRecycleAllocator* allocator =
    aContainer->GetD3D11YCbCrRecycleAllocator(aAllocator);
  if (!allocator) {
    return false;
  }
  allocator->SetSizes(aData.mYSize, aData.mCbCrSize);

  mTextureClient = allocator->CreateOrRecycle(SurfaceFormat::A8,
                                              mYSize,
                                              BackendSelector::Content,
                                              TextureFlags::DEFAULT);
  if (!mTextureClient) {
    return false;
  }

  DXGIYCbCrTextureData *data =
    static_cast<DXGIYCbCrTextureData*>(mTextureClient->GetInternalData());

  ID3D11Texture2D* textureY = data->GetD3D11Texture(0);
  ID3D11Texture2D* textureCb = data->GetD3D11Texture(1);
  ID3D11Texture2D* textureCr = data->GetD3D11Texture(2);

  RefPtr<ID3D10Multithread> mt;
  HRESULT hr = allocator->GetDevice()->QueryInterface(
    (ID3D10Multithread**)getter_AddRefs(mt));

  if (FAILED(hr) || !mt) {
    gfxCriticalError() << "Multithread safety interface not supported. " << hr;
    return false;
  }

  if (!mt->GetMultithreadProtected()) {
    gfxCriticalError() << "Device used not marked as multithread-safe.";
    return false;
  }

  D3D11MTAutoEnter mtAutoEnter(mt.forget());

  RefPtr<ID3D11DeviceContext> ctx;
  allocator->GetDevice()->GetImmediateContext(getter_AddRefs(ctx));

  AutoLockD3D11Texture lockY(textureY);
  AutoLockD3D11Texture lockCb(textureCb);
  AutoLockD3D11Texture lockCr(textureCr);

  ctx->UpdateSubresource(textureY,
                         0,
                         nullptr,
                         aData.mYChannel,
                         aData.mYStride,
                         aData.mYStride * aData.mYSize.height);
  ctx->UpdateSubresource(textureCb,
                         0,
                         nullptr,
                         aData.mCbChannel,
                         aData.mCbCrStride,
                         aData.mCbCrStride * aData.mCbCrSize.height);
  ctx->UpdateSubresource(textureCr,
                         0,
                         nullptr,
                         aData.mCrChannel,
                         aData.mCbCrStride,
                         aData.mCbCrStride * aData.mCbCrSize.height);

  
  return true;
}
Ejemplo n.º 5
0
DIBTextureData*
ShmemDIBTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                            LayersIPCChannel* aAllocator)
{
  MOZ_ASSERT(aAllocator->GetParentPid() != base::ProcessId());

  DWORD mapSize = aSize.width * aSize.height * BytesPerPixel(aFormat);
  HANDLE fileMapping = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, mapSize, NULL);

  if (!fileMapping) {
    gfxCriticalError() << "Failed to create memory file mapping for " << mapSize << " bytes.";
    return nullptr;
  }

  BITMAPV4HEADER header;
  memset(&header, 0, sizeof(BITMAPV4HEADER));
  header.bV4Size          = sizeof(BITMAPV4HEADER);
  header.bV4Width         = aSize.width;
  header.bV4Height        = -LONG(aSize.height); // top-to-buttom DIB
  header.bV4Planes        = 1;
  header.bV4BitCount      = 32;
  header.bV4V4Compression = BI_BITFIELDS;
  header.bV4RedMask       = 0x00FF0000;
  header.bV4GreenMask     = 0x0000FF00;
  header.bV4BlueMask      = 0x000000FF;

  HDC nulldc = ::GetDC(NULL);

  HDC dc = ::CreateCompatibleDC(nulldc);

  ::ReleaseDC(nullptr, nulldc);

  if (!dc) {
    ::CloseHandle(fileMapping);
    gfxCriticalError() << "Failed to create DC for bitmap.";
    return nullptr;
  }

  void* bits;
  HBITMAP bitmap = ::CreateDIBSection(dc, (BITMAPINFO*)&header,
                                      DIB_RGB_COLORS, &bits,
                                      fileMapping, 0);

  if (!bitmap) {
    gfxCriticalError() << "Failed to create DIB section for a bitmap of size "
                       << aSize << " and mapSize " << mapSize;
    ::CloseHandle(fileMapping);
    ::DeleteDC(dc);
    return nullptr;
  }

  ::SelectObject(dc, bitmap);

  RefPtr<gfxWindowsSurface> surface = new gfxWindowsSurface(dc, 0);
  if (surface->CairoStatus())
  {
    ::DeleteObject(bitmap);
    ::DeleteDC(dc);
    ::CloseHandle(fileMapping);
    gfxCriticalError() << "Could not create surface, status: "
                       << surface->CairoStatus();
    return nullptr;
  }

  HANDLE hostHandle = NULL;

  if (!ipc::DuplicateHandle(fileMapping, aAllocator->GetParentPid(),
                            &hostHandle, 0, DUPLICATE_SAME_ACCESS)) {
    gfxCriticalError() << "Failed to duplicate handle to parent process for surface.";
    ::DeleteObject(bitmap);
    ::DeleteDC(dc);
    ::CloseHandle(fileMapping);
    return nullptr;
  }

  return new ShmemDIBTextureData(aSize, aFormat, surface,
                                 fileMapping, hostHandle,
                                 dc, bitmap);
}
Ejemplo n.º 6
0
void
D3D11LayersCrashGuard::LogCrashRecovery()
{
  RecordTelemetry(TelemetryState::RecoveredFromCrash);
  gfxCriticalError(CriticalLog::DefaultOptions(false)) << "D3D11 layers just crashed; D3D11 will be disabled.";
}
Ejemplo n.º 7
0
already_AddRefed<SourceSurface>
D3D11YCbCrImage::GetAsSourceSurface()
{
  if (!mTextureClient) {
    gfxWarning()
      << "GetAsSourceSurface() called on uninitialized D3D11YCbCrImage.";
    return nullptr;
  }

  gfx::IntSize size(mPictureRect.Size());
  gfx::SurfaceFormat format =
    gfx::ImageFormatToSurfaceFormat(gfxVars::OffscreenFormat());
  HRESULT hr;

  PlanarYCbCrData data;

  DXGIYCbCrTextureData *dxgiData =
    static_cast<DXGIYCbCrTextureData*>(mTextureClient->GetInternalData());

  if (!dxgiData) {
    gfxCriticalError() << "Failed to get texture client internal data.";
    return nullptr;
  }

  RefPtr<ID3D11Texture2D> texY = dxgiData->GetD3D11Texture(0);
  RefPtr<ID3D11Texture2D> texCb = dxgiData->GetD3D11Texture(1);
  RefPtr<ID3D11Texture2D> texCr = dxgiData->GetD3D11Texture(2);
  RefPtr<ID3D11Texture2D> softTexY, softTexCb, softTexCr;
  D3D11_TEXTURE2D_DESC desc;

  RefPtr<ID3D11Device> dev;
  texY->GetDevice(getter_AddRefs(dev));

  RefPtr<ID3D10Multithread> mt;
  hr = dev->QueryInterface((ID3D10Multithread**)getter_AddRefs(mt));

  if (FAILED(hr) || !mt) {
    gfxCriticalError() << "Multithread safety interface not supported.";
    return nullptr;
  }

  if (!mt->GetMultithreadProtected()) {
    gfxCriticalError() << "Device used not marked as multithread-safe.";
    return nullptr;
  }

  D3D11MTAutoEnter mtAutoEnter(mt.forget());

  texY->GetDesc(&desc);
  desc.BindFlags = 0;
  desc.MiscFlags = 0;
  desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  desc.Usage = D3D11_USAGE_STAGING;

  dev->CreateTexture2D(&desc, nullptr, getter_AddRefs(softTexY));

  texCb->GetDesc(&desc);
  desc.BindFlags = 0;
  desc.MiscFlags = 0;
  desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  desc.Usage = D3D11_USAGE_STAGING;

  dev->CreateTexture2D(&desc, nullptr, getter_AddRefs(softTexCb));
  dev->CreateTexture2D(&desc, nullptr, getter_AddRefs(softTexCr));

  RefPtr<ID3D11DeviceContext> ctx;
  dev->GetImmediateContext(getter_AddRefs(ctx));

  {
    AutoLockD3D11Texture lockY(texY);
    AutoLockD3D11Texture lockCb(texCb);
    AutoLockD3D11Texture lockCr(texCr);
    ctx->CopyResource(softTexY, texY);
    ctx->CopyResource(softTexCb, texCb);
    ctx->CopyResource(softTexCr, texCr);
  }

  D3D11_MAPPED_SUBRESOURCE mapY, mapCb, mapCr;
  RefPtr<gfx::DataSourceSurface> surface;
  mapY.pData = mapCb.pData = mapCr.pData = nullptr;

  hr = ctx->Map(softTexY, 0, D3D11_MAP_READ, 0, &mapY);
  if (FAILED(hr)) {
    gfxCriticalError() << "Failed to map Y plane (" << hr << ")";
    return nullptr;
  }
  hr = ctx->Map(softTexCb, 0, D3D11_MAP_READ, 0, &mapCb);
  if (FAILED(hr)) {
    gfxCriticalError() << "Failed to map Y plane (" << hr << ")";
    return nullptr;
  }
  hr = ctx->Map(softTexCr, 0, D3D11_MAP_READ, 0, &mapCr);
  if (FAILED(hr)) {
    gfxCriticalError() << "Failed to map Y plane (" << hr << ")";
    return nullptr;
  }

  MOZ_ASSERT(mapCb.RowPitch == mapCr.RowPitch);

  data.mPicX = mPictureRect.x;
  data.mPicY = mPictureRect.y;
  data.mPicSize = mPictureRect.Size();
  data.mStereoMode = StereoMode::MONO;
  data.mYUVColorSpace = mColorSpace;
  data.mYSkip = data.mCbSkip = data.mCrSkip = 0;
  data.mYSize = mYSize;
  data.mCbCrSize = mCbCrSize;
  data.mYChannel = static_cast<uint8_t*>(mapY.pData);
  data.mYStride = mapY.RowPitch;
  data.mCbChannel = static_cast<uint8_t*>(mapCb.pData);
  data.mCrChannel = static_cast<uint8_t*>(mapCr.pData);
  data.mCbCrStride = mapCb.RowPitch;

  gfx::GetYCbCrToRGBDestFormatAndSize(data, format, size);
  if (size.width > PlanarYCbCrImage::MAX_DIMENSION ||
      size.height > PlanarYCbCrImage::MAX_DIMENSION) {
    gfxCriticalError() << "Illegal image dest width or height";
    return nullptr;
  }

  surface = gfx::Factory::CreateDataSourceSurface(size, format);
  if (!surface) {
    gfxCriticalError() << "Failed to create DataSourceSurface for image: "
                       << size << " " << format;
    return nullptr;
  }

  DataSourceSurface::ScopedMap mapping(surface, DataSourceSurface::WRITE);
  if (!mapping.IsMapped()) {
    gfxCriticalError() << "Failed to map DataSourceSurface for D3D11YCbCrImage";
    return nullptr;
  }

  gfx::ConvertYCbCrToRGB(
    data, format, size, mapping.GetData(), mapping.GetStride());

  ctx->Unmap(softTexY, 0);
  ctx->Unmap(softTexCb, 0);
  ctx->Unmap(softTexCr, 0);

  return surface.forget();
}
Ejemplo n.º 8
0
CompositorChild::~CompositorChild()
{
  if (mCanSend) {
    gfxCriticalError() << "CompositorChild was not deinitialized";
  }
}
Ejemplo n.º 9
0
bool
FixedSizeSmallShmemSectionAllocator::AllocShmemSection(uint32_t aSize, ShmemSection* aShmemSection)
{
  // For now we only support sizes of 4. If we want to support different sizes
  // some more complicated bookkeeping should be added.
  MOZ_ASSERT(aSize == sSupportedBlockSize);
  MOZ_ASSERT(aShmemSection);

  if (!IPCOpen()) {
    gfxCriticalError() << "Attempt to allocate a ShmemSection after shutdown.";
    return false;
  }

  uint32_t allocationSize = (aSize + sizeof(ShmemSectionHeapAllocation));

  for (size_t i = 0; i < mUsedShmems.size(); i++) {
    ShmemSectionHeapHeader* header = mUsedShmems[i].get<ShmemSectionHeapHeader>();
    if ((header->mAllocatedBlocks + 1) * allocationSize + sizeof(ShmemSectionHeapHeader) < sShmemPageSize) {
      aShmemSection->shmem() = mUsedShmems[i];
      MOZ_ASSERT(mUsedShmems[i].IsWritable());
      break;
    }
  }

  if (!aShmemSection->shmem().IsWritable()) {
    ipc::Shmem tmp;
    if (!GetShmAllocator()->AllocUnsafeShmem(sShmemPageSize, OptimalShmemType(), &tmp)) {
      return false;
    }

    ShmemSectionHeapHeader* header = tmp.get<ShmemSectionHeapHeader>();
    header->mTotalBlocks = 0;
    header->mAllocatedBlocks = 0;

    mUsedShmems.push_back(tmp);
    aShmemSection->shmem() = tmp;
  }

  MOZ_ASSERT(aShmemSection->shmem().IsWritable());

  ShmemSectionHeapHeader* header = aShmemSection->shmem().get<ShmemSectionHeapHeader>();
  uint8_t* heap = aShmemSection->shmem().get<uint8_t>() + sizeof(ShmemSectionHeapHeader);

  ShmemSectionHeapAllocation* allocHeader = nullptr;

  if (header->mTotalBlocks > header->mAllocatedBlocks) {
    // Search for the first available block.
    for (size_t i = 0; i < header->mTotalBlocks; i++) {
      allocHeader = reinterpret_cast<ShmemSectionHeapAllocation*>(heap);

      if (allocHeader->mStatus == STATUS_FREED) {
        break;
      }
      heap += allocationSize;
    }
    MOZ_ASSERT(allocHeader && allocHeader->mStatus == STATUS_FREED);
    MOZ_ASSERT(allocHeader->mSize == sSupportedBlockSize);
  } else {
    heap += header->mTotalBlocks * allocationSize;

    header->mTotalBlocks++;
    allocHeader = reinterpret_cast<ShmemSectionHeapAllocation*>(heap);
    allocHeader->mSize = aSize;
  }

  MOZ_ASSERT(allocHeader);
  header->mAllocatedBlocks++;
  allocHeader->mStatus = STATUS_ALLOCATED;

  aShmemSection->size() = aSize;
  aShmemSection->offset() = (heap + sizeof(ShmemSectionHeapAllocation)) - aShmemSection->shmem().get<uint8_t>();
  ShrinkShmemSectionHeap();
  return true;
}
Ejemplo n.º 10
0
void
GLContextCrashGuard::LogCrashRecovery()
{
  gfxCriticalError(CriticalLog::DefaultOptions(false)) << "GLContext just crashed and is now disabled.";
}
Ejemplo n.º 11
0
void
GLContextCrashGuard::LogFeatureDisabled()
{
  gfxCriticalError(CriticalLog::DefaultOptions(false)) << "GLContext is disabled due to a previous crash.";
}
Ejemplo n.º 12
0
void
D3D9VideoCrashGuard::LogFeatureDisabled()
{
  gfxCriticalError(CriticalLog::DefaultOptions(false)) << "DXVA2D3D9 video decoding is disabled due to a previous crash.";
}
Ejemplo n.º 13
0
void
D3D9VideoCrashGuard::LogCrashRecovery()
{
  gfxCriticalError(CriticalLog::DefaultOptions(false)) << "DXVA2D3D9 just crashed; hardware video will be disabled.";
}
Ejemplo n.º 14
0
void
D3D11LayersCrashGuard::LogFeatureDisabled()
{
  RecordTelemetry(TelemetryState::FeatureDisabled);
  gfxCriticalError(CriticalLog::DefaultOptions(false)) << "D3D11 layers disabled due to a prior crash.";
}
Ejemplo n.º 15
0
void
CanvasClientSharedSurface::UpdateRenderer(gfx::IntSize aSize, Renderer& aRenderer)
{
  GLContext* gl = nullptr;
  ClientCanvasLayer* layer = nullptr;
  AsyncCanvasRenderer* asyncRenderer = nullptr;
  if (aRenderer.constructed<ClientCanvasLayer*>()) {
    layer = aRenderer.ref<ClientCanvasLayer*>();
    gl = layer->mGLContext;
  } else {
    asyncRenderer = aRenderer.ref<AsyncCanvasRenderer*>();
    gl = asyncRenderer->mGLContext;
  }
  gl->MakeCurrent();

  RefPtr<TextureClient> newFront;

  if (layer && layer->mGLFrontbuffer) {
    mShSurfClient = CloneSurface(layer->mGLFrontbuffer.get(), layer->mFactory.get());
    if (!mShSurfClient) {
      gfxCriticalError() << "Invalid canvas front buffer";
      return;
    }
  } else {
    mShSurfClient = gl->Screen()->Front();
    if (!mShSurfClient) {
      return;
    }
  }
  MOZ_ASSERT(mShSurfClient);

  newFront = mShSurfClient;

  SharedSurface* surf = mShSurfClient->Surf();

  // Readback if needed.
  mReadbackClient = nullptr;

  auto forwarder = GetForwarder();

  bool needsReadback = (surf->mType == SharedSurfaceType::Basic);
  if (needsReadback) {
    TextureFlags flags = TextureFlags::IMMUTABLE;

    CompositableForwarder* shadowForwarder = nullptr;
    if (layer) {
      flags |= layer->Flags();
      shadowForwarder = layer->ClientManager()->AsShadowForwarder();
    } else {
      MOZ_ASSERT(asyncRenderer);
      flags |= mTextureFlags;
      shadowForwarder = GetForwarder();
    }

    auto layersBackend = shadowForwarder->GetCompositorBackendType();
    mReadbackClient = TexClientFromReadback(surf, forwarder, flags, layersBackend);

    if (asyncRenderer) {
      // Above codes will readback the GLContext to mReadbackClient
      // in order to send frame to compositor. We copy from this
      // TextureClient directly by calling CopyFromTextureClient().
      // Therefore, if main-thread want the content of GLContext,
      // it don't have to readback it again.
      asyncRenderer->CopyFromTextureClient(mReadbackClient);
    }

    newFront = mReadbackClient;
  } else {
    mReadbackClient = nullptr;
  }

  MOZ_ASSERT(newFront);
  if (!newFront) {
    // May happen in a release build in case of memory pressure.
    gfxCriticalError() << "Failed to allocate a TextureClient for SharedSurface Canvas. Size: " << aSize;
    return;
  }

  mNewFront = newFront;
}
Ejemplo n.º 16
0
bool
WebGLTexture::EnsureInitializedImageData(TexImageTarget imageTarget,
                                         GLint level)
{
    const ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
    if (!imageInfo.HasUninitializedImageData())
        return true;

    mContext->MakeContextCurrent();

    // Try to clear with glClear.
    if (imageTarget == LOCAL_GL_TEXTURE_2D) {
        bool cleared = ClearWithTempFB(mContext, mGLName, imageTarget, level,
                                       imageInfo.mEffectiveInternalFormat,
                                       imageInfo.mHeight, imageInfo.mWidth);
        if (cleared) {
            SetImageDataStatus(imageTarget, level,
                               WebGLImageDataStatus::InitializedImageData);
            return true;
        }
    }

    // That didn't work. Try uploading zeros then.
    size_t bitspertexel = GetBitsPerTexel(imageInfo.mEffectiveInternalFormat);
    MOZ_ASSERT((bitspertexel % 8) == 0); // That would only happen for
                                         // compressed images, which cannot use
                                         // deferred initialization.
    size_t bytespertexel = bitspertexel / 8;
    CheckedUint32 checked_byteLength
        = WebGLContext::GetImageSize(
                        imageInfo.mHeight,
                        imageInfo.mWidth,
                        imageInfo.mDepth,
                        bytespertexel,
                        mContext->mPixelStoreUnpackAlignment);
    MOZ_ASSERT(checked_byteLength.isValid()); // Should have been checked
                                              // earlier.

    size_t byteCount = checked_byteLength.value();

    UniquePtr<uint8_t> zeros((uint8_t*)calloc(1, byteCount));
    if (zeros == nullptr) {
        // Failed to allocate memory. Lose the context. Return OOM error.
        mContext->ForceLoseContext(true);
        mContext->ErrorOutOfMemory("EnsureInitializedImageData: Failed to alloc %u "
                                   "bytes to clear image target `%s` level `%d`.",
                                   byteCount, mContext->EnumName(imageTarget.get()),
                                   level);
         return false;
    }

    gl::GLContext* gl = mContext->gl;
    gl::ScopedBindTexture autoBindTex(gl, mGLName, mTarget);

    GLenum driverInternalFormat = LOCAL_GL_NONE;
    GLenum driverFormat = LOCAL_GL_NONE;
    GLenum driverType = LOCAL_GL_NONE;
    DriverFormatsFromEffectiveInternalFormat(gl,
                                             imageInfo.mEffectiveInternalFormat,
                                             &driverInternalFormat,
                                             &driverFormat, &driverType);

    mContext->GetAndFlushUnderlyingGLErrors();
    if (imageTarget == LOCAL_GL_TEXTURE_3D) {
        MOZ_ASSERT(mImmutable,
                   "Shouldn't be possible to have non-immutable-format 3D"
                   " textures in WebGL");
        gl->fTexSubImage3D(imageTarget.get(), level, 0, 0, 0, imageInfo.mWidth,
                           imageInfo.mHeight, imageInfo.mDepth, driverFormat,
                           driverType, zeros.get());
    } else {
        if (mImmutable) {
            gl->fTexSubImage2D(imageTarget.get(), level, 0, 0, imageInfo.mWidth,
                               imageInfo.mHeight, driverFormat, driverType,
                               zeros.get());
        } else {
            gl->fTexImage2D(imageTarget.get(), level, driverInternalFormat,
                            imageInfo.mWidth, imageInfo.mHeight, 0,
                            driverFormat, driverType, zeros.get());
        }
    }
    GLenum error = mContext->GetAndFlushUnderlyingGLErrors();
    if (error) {
        // Should only be OUT_OF_MEMORY. Anyway, there's no good way to recover
        // from this here.
        gfxCriticalError() << "GL context GetAndFlushUnderlyingGLErrors " << gfx::hexa(error);
        printf_stderr("Error: 0x%4x\n", error);
        if (error != LOCAL_GL_OUT_OF_MEMORY) {
            // Errors on texture upload have been related to video
            // memory exposure in the past, which is a security issue.
            // Force loss of context.
            mContext->ForceLoseContext(true);
            return false;
        }

        // Out-of-memory uploading pixels to GL. Lose context and report OOM.
        mContext->ForceLoseContext(true);
        mContext->ErrorOutOfMemory("EnsureNoUninitializedImageData: Failed to "
                                   "upload texture of width: %u, height: %u, "
                                   "depth: %u to target %s level %d.",
                                   imageInfo.mWidth, imageInfo.mHeight, imageInfo.mDepth,
                                   mContext->EnumName(imageTarget.get()), level);
        return false;
    }

    SetImageDataStatus(imageTarget, level, WebGLImageDataStatus::InitializedImageData);

    return true;
}
Ejemplo n.º 17
0
bool
TextureImageTextureSourceOGL::Update(gfx::DataSourceSurface* aSurface,
                                     nsIntRegion* aDestRegion,
                                     gfx::IntPoint* aSrcOffset)
{
  GLContext *gl = mCompositor->gl();
  MOZ_ASSERT(gl);
  if (!gl) {
    NS_WARNING("trying to update TextureImageTextureSourceOGL without a GLContext");
    return false;
  }
  if (!aSurface) {
    gfxCriticalError() << "Invalid surface for OGL update";
    return false;
  }
  MOZ_ASSERT(aSurface);

  IntSize size = aSurface->GetSize();
  if (!mTexImage ||
      (mTexImage->GetSize() != size && !aSrcOffset) ||
      mTexImage->GetContentType() != gfx::ContentForFormat(aSurface->GetFormat())) {
    if (mFlags & TextureFlags::DISALLOW_BIGIMAGE) {
      GLint maxTextureSize;
      gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &maxTextureSize);
      if (size.width > maxTextureSize || size.height > maxTextureSize) {
        NS_WARNING("Texture exceeds maximum texture size, refusing upload");
        return false;
      }
      // Explicitly use CreateBasicTextureImage instead of CreateTextureImage,
      // because CreateTextureImage might still choose to create a tiled
      // texture image.
      mTexImage = CreateBasicTextureImage(gl, size,
                                          gfx::ContentForFormat(aSurface->GetFormat()),
                                          LOCAL_GL_CLAMP_TO_EDGE,
                                          FlagsToGLFlags(mFlags),
                                          SurfaceFormatToImageFormat(aSurface->GetFormat()));
    } else {
      // XXX - clarify which size we want to use. IncrementalContentHost will
      // require the size of the destination surface to be different from
      // the size of aSurface.
      // See bug 893300 (tracks the implementation of ContentHost for new textures).
      mTexImage = CreateTextureImage(gl,
                                     size,
                                     gfx::ContentForFormat(aSurface->GetFormat()),
                                     LOCAL_GL_CLAMP_TO_EDGE,
                                     FlagsToGLFlags(mFlags),
                                     SurfaceFormatToImageFormat(aSurface->GetFormat()));
    }
    ClearCachedFilter();

    if (aDestRegion &&
        !aSrcOffset &&
        !aDestRegion->IsEqual(gfx::IntRect(0, 0, size.width, size.height))) {
      // UpdateFromDataSource will ignore our specified aDestRegion since the texture
      // hasn't been allocated with glTexImage2D yet. Call Resize() to force the
      // allocation (full size, but no upload), and then we'll only upload the pixels
      // we care about below.
      mTexImage->Resize(size);
    }
  }

  mTexImage->UpdateFromDataSource(aSurface, aDestRegion, aSrcOffset);

  if (mTexImage->InUpdate()) {
    mTexImage->EndUpdate();
  }
  return true;
}
Ejemplo n.º 18
0
WebGLContext::FakeBlackTexture::FakeBlackTexture(gl::GLContext* gl, TexTarget target,
                                                 FakeBlackType type)
    : mGL(gl)
    , mGLName(CreateGLTexture(gl))
{
    GLenum texFormat;
    switch (type) {
    case FakeBlackType::RGBA0000:
        texFormat = LOCAL_GL_RGBA;
        break;

    case FakeBlackType::RGBA0001:
        texFormat = LOCAL_GL_RGB;
        break;

    default:
        MOZ_CRASH("bad type");
    }

    gl::ScopedBindTexture scopedBind(mGL, mGLName, target.get());

    mGL->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
    mGL->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);

    // We allocate our zeros on the heap, and we overallocate (16 bytes instead of 4) to
    // minimize the risk of running into a driver bug in texImage2D, as it is a bit
    // unusual maybe to create 1x1 textures, and the stack may not have the alignment that
    // TexImage2D expects.

    const webgl::DriverUnpackInfo dui = {texFormat, texFormat, LOCAL_GL_UNSIGNED_BYTE};
    UniqueBuffer zeros = moz_xcalloc(1, 16); // Infallible allocation.

    MOZ_ASSERT(gl->IsCurrent());
    if (target == LOCAL_GL_TEXTURE_CUBE_MAP) {
        for (int i = 0; i < 6; ++i) {
            const TexImageTarget curTarget = LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
            const GLenum error = DoTexImage(mGL, curTarget.get(), 0, &dui, 1, 1, 1,
                                            zeros.get());
            if (error) {
                const nsPrintfCString text("DoTexImage failed with `error`: 0x%04x, "
                                           "for `curTarget`: 0x%04x, "
                                           "`dui`: {0x%04x, 0x%04x, 0x%04x}.",
                                           error, curTarget.get(), dui.internalFormat,
                                           dui.unpackFormat, dui.unpackType);
                gfxCriticalError() << text.BeginReading();
                MOZ_CRASH("Unexpected error during cube map FakeBlack creation.");
            }
        }
    } else {
        const GLenum error = DoTexImage(mGL, target.get(), 0, &dui, 1, 1, 1,
                                        zeros.get());
        if (error) {
            const nsPrintfCString text("DoTexImage failed with `error`: 0x%04x, "
                                       "for `target`: 0x%04x, "
                                       "`dui`: {0x%04x, 0x%04x, 0x%04x}.",
                                       error, target.get(), dui.internalFormat,
                                       dui.unpackFormat, dui.unpackType);
            gfxCriticalError() << text.BeginReading();
            MOZ_CRASH("Unexpected error during FakeBlack creation.");
        }
    }
}