Example #1
0
// Same as above, for YCbCr surfaces
void TestTextureClientYCbCr(TextureClient* client, PlanarYCbCrData& ycbcrData) {

  // client allocation
  ASSERT_TRUE(client->AsTextureClientYCbCr() != nullptr);
  TextureClientYCbCr* texture = client->AsTextureClientYCbCr();
  texture->AllocateForYCbCr(ToIntSize(ycbcrData.mYSize),
                            ToIntSize(ycbcrData.mCbCrSize),
                            ycbcrData.mStereoMode);
  ASSERT_TRUE(client->IsAllocated());

  // client painting
  texture->UpdateYCbCr(ycbcrData);

  ASSERT_TRUE(client->Lock(OPEN_READ_ONLY));
  client->Unlock();

  // client serialization
  SurfaceDescriptor descriptor;
  ASSERT_TRUE(client->ToSurfaceDescriptor(descriptor));

  ASSERT_NE(descriptor.type(), SurfaceDescriptor::Tnull_t);

  // host deserialization
  RefPtr<TextureHost> textureHost = CreateBackendIndependentTextureHost(descriptor, nullptr,
                                                                        client->GetFlags());

  RefPtr<BufferTextureHost> host = static_cast<BufferTextureHost*>(textureHost.get());

  ASSERT_TRUE(host.get() != nullptr);
  ASSERT_EQ(host->GetFlags(), client->GetFlags());

  // This will work iff the compositor is not BasicCompositor
  ASSERT_EQ(host->GetFormat(), mozilla::gfx::FORMAT_YUV);

  // host read
  ASSERT_TRUE(host->Lock());

  ASSERT_TRUE(host->GetFormat() == mozilla::gfx::FORMAT_YUV);

  YCbCrImageDataDeserializer yuvDeserializer(host->GetBuffer());
  ASSERT_TRUE(yuvDeserializer.IsValid());
  PlanarYCbCrData data;
  data.mYChannel = yuvDeserializer.GetYData();
  data.mCbChannel = yuvDeserializer.GetCbData();
  data.mCrChannel = yuvDeserializer.GetCrData();
  data.mYStride = yuvDeserializer.GetYStride();
  data.mCbCrStride = yuvDeserializer.GetCbCrStride();
  data.mStereoMode = yuvDeserializer.GetStereoMode();
  data.mYSize = yuvDeserializer.GetYSize();
  data.mCbCrSize = yuvDeserializer.GetCbCrSize();
  data.mYSkip = 0;
  data.mCbSkip = 0;
  data.mCrSkip = 0;
  data.mPicSize = data.mYSize;
  data.mPicX = 0;
  data.mPicY = 0;

  AssertYCbCrSurfacesEqual(&ycbcrData, &data);
  host->Unlock();
}
already_AddRefed<DataSourceSurface>
ImageBitmapRenderingContext::MatchWithIntrinsicSize()
{
  RefPtr<SourceSurface> surface = mImage->GetAsSourceSurface();
  RefPtr<DataSourceSurface> temp =
    Factory::CreateDataSourceSurface(IntSize(mWidth, mHeight), surface->GetFormat());
  if (!temp) {
    return nullptr;
  }

  DataSourceSurface::ScopedMap map(temp, DataSourceSurface::READ_WRITE);
  if (!map.IsMapped()) {
    return nullptr;
  }

  RefPtr<DrawTarget> dt =
    Factory::CreateDrawTargetForData(BackendType::CAIRO,
                                     map.GetData(),
                                     temp->GetSize(),
                                     map.GetStride(),
                                     temp->GetFormat());
  if (!dt) {
    return nullptr;
  }


  dt->ClearRect(Rect(0, 0, mWidth, mHeight));
  dt->CopySurface(surface,
                  IntRect(0, 0, surface->GetSize().width,
                                surface->GetSize().height),
                  IntPoint(0, 0));

  return temp.forget();
}
void
TextureImageEGL::EndUpdate()
{
    NS_ASSERTION(!!mUpdateDrawTarget, "EndUpdate() without BeginUpdate()?");

    //printf_stderr("EndUpdate: slow path");

    // This is the slower path -- we didn't have any way to set up
    // a fast mapping between our cairo target surface and the GL
    // texture, so we have to upload data.

    RefPtr<gfx::SourceSurface> updateSurface = nullptr;
    RefPtr<gfx::DataSourceSurface> uploadImage = nullptr;
    gfx::IntSize updateSize(mUpdateRect.width, mUpdateRect.height);

    NS_ASSERTION(mUpdateDrawTarget->GetSize() == updateSize,
                  "Upload image is the wrong size!");

    updateSurface = mUpdateDrawTarget->Snapshot();
    uploadImage = updateSurface->GetDataSurface();

    if (!uploadImage) {
        return;
    }

    mGLContext->MakeCurrent();
    mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);

    if (mTextureState != Valid) {
        NS_ASSERTION(mUpdateRect.x == 0 && mUpdateRect.y == 0 &&
                      mUpdateRect.Size() == mSize,
                      "Bad initial update on non-created texture!");

        mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
                                0,
                                GLFormatForImage(mUpdateFormat),
                                mUpdateRect.width,
                                mUpdateRect.height,
                                0,
                                GLFormatForImage(uploadImage->GetFormat()),
                                GLTypeForImage(uploadImage->GetFormat()),
                                uploadImage->GetData());
    } else {
        mGLContext->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
                                    0,
                                    mUpdateRect.x,
                                    mUpdateRect.y,
                                    mUpdateRect.width,
                                    mUpdateRect.height,
                                    GLFormatForImage(uploadImage->GetFormat()),
                                    GLTypeForImage(uploadImage->GetFormat()),
                                    uploadImage->GetData());
    }

    mUpdateDrawTarget = nullptr;
    mTextureState = Valid;
    return;         // mTexture is bound
}
static nsresult
ConvertSourceSurfaceToNV12(const RefPtr<SourceSurface>& aSurface, uint8_t* aDestination)
{
  if (!aSurface) {
    CODEC_ERROR("Getting surface from image failed");
    return NS_ERROR_FAILURE;
  }

  uint32_t width = aSurface->GetSize().width;
  uint32_t height = aSurface->GetSize().height;

  uint8_t* y = aDestination;
  int yStride = width;

  uint8_t* uv = y + (yStride * height);
  int uvStride = width / 2;

  RefPtr<DataSourceSurface> data = aSurface->GetDataSurface();
  if (!data) {
    CODEC_ERROR("Getting data surface from %s image with %s surface failed",
                Stringify(aSurface->GetFormat()).c_str(),
                Stringify(aSurface->GetType()).c_str());
    return NS_ERROR_FAILURE;
  }

  DataSourceSurface::ScopedMap map(data, DataSourceSurface::READ);
  if (!map.IsMapped()) {
    CODEC_ERROR("Reading DataSourceSurface from %s image with %s surface failed",
                Stringify(aSurface->GetFormat()).c_str(),
                Stringify(aSurface->GetType()).c_str());
    return NS_ERROR_FAILURE;
  }

  int rv;
  switch (aSurface->GetFormat()) {
    case SurfaceFormat::B8G8R8A8:
    case SurfaceFormat::B8G8R8X8:
      rv = libyuv::ARGBToNV12(static_cast<uint8*>(map.GetData()),
                              map.GetStride(),
                              y, yStride,
                              uv, uvStride,
                              width, height);
      break;
    default:
      CODEC_ERROR("Unsupported SourceSurface format %s",
                  Stringify(aSurface->GetFormat()).c_str());
      NS_ASSERTION(false, "Unsupported SourceSurface format");
      return NS_ERROR_NOT_IMPLEMENTED;
  }

  if (rv != 0) {
    CODEC_ERROR("%s to I420 conversion failed",
                Stringify(aSurface->GetFormat()).c_str());
    return NS_ERROR_FAILURE;
  }

  return NS_OK;
}
bool
BufferTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
{
  if (mDescriptor.type() != BufferDescriptor::TRGBDescriptor) {
    return false;
  }
  const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();

  uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
  RefPtr<gfx::DataSourceSurface> surface =
    gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(), stride,
                                                  rgb.size(), rgb.format());

  if (!surface) {
    gfxCriticalError() << "Failed to get serializer as surface!";
    return false;
  }

  RefPtr<gfx::DataSourceSurface> srcSurf = aSurface->GetDataSurface();

  if (!srcSurf) {
    gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface (BT).";
    return false;
  }

  if (surface->GetSize() != srcSurf->GetSize() || surface->GetFormat() != srcSurf->GetFormat()) {
    gfxCriticalError() << "Attempt to update texture client from a surface with a different size or format (BT)! This: " << surface->GetSize() << " " << surface->GetFormat() << " Other: " << aSurface->GetSize() << " " << aSurface->GetFormat();
    return false;
  }

  gfx::DataSourceSurface::MappedSurface sourceMap;
  gfx::DataSourceSurface::MappedSurface destMap;
  if (!srcSurf->Map(gfx::DataSourceSurface::READ, &sourceMap)) {
    gfxCriticalError() << "Failed to map source surface for UpdateFromSurface (BT).";
    return false;
  }

  if (!surface->Map(gfx::DataSourceSurface::WRITE, &destMap)) {
    srcSurf->Unmap();
    gfxCriticalError() << "Failed to map destination surface for UpdateFromSurface.";
    return false;
  }


  for (int y = 0; y < srcSurf->GetSize().height; y++) {
    memcpy(destMap.mData + destMap.mStride * y,
           sourceMap.mData + sourceMap.mStride * y,
           srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
  }

  srcSurf->Unmap();
  surface->Unmap();

  return true;
}
Example #6
0
// Same as above, for YCbCr surfaces
void TestTextureClientYCbCr(TextureClient* client, PlanarYCbCrData& ycbcrData) {
  client->Lock(OpenMode::OPEN_READ_WRITE);
  UpdateYCbCrTextureClient(client, ycbcrData);
  client->Unlock();

  // client serialization
  SurfaceDescriptor descriptor;
  ASSERT_TRUE(client->ToSurfaceDescriptor(descriptor));

  ASSERT_EQ(descriptor.type(), SurfaceDescriptor::TSurfaceDescriptorBuffer);
  auto bufferDesc = descriptor.get_SurfaceDescriptorBuffer();
  ASSERT_EQ(bufferDesc.desc().type(), BufferDescriptor::TYCbCrDescriptor);
  auto ycbcrDesc = bufferDesc.desc().get_YCbCrDescriptor();
  ASSERT_EQ(ycbcrDesc.ySize(), ycbcrData.mYSize);
  ASSERT_EQ(ycbcrDesc.cbCrSize(), ycbcrData.mCbCrSize);
  ASSERT_EQ(ycbcrDesc.stereoMode(), ycbcrData.mStereoMode);

  // host deserialization
  RefPtr<TextureHost> textureHost = CreateBackendIndependentTextureHost(descriptor, nullptr,
                                                                        client->GetFlags());

  RefPtr<BufferTextureHost> host = static_cast<BufferTextureHost*>(textureHost.get());

  ASSERT_TRUE(host.get() != nullptr);
  ASSERT_EQ(host->GetFlags(), client->GetFlags());

  // host read

  if (host->Lock()) {
    // This will work iff the compositor is not BasicCompositor
    ASSERT_EQ(host->GetFormat(), mozilla::gfx::SurfaceFormat::YUV);
    host->Unlock();
  }
}
void
ImageLayerComposite::RenderLayer(const nsIntRect& aClipRect)
{
  if (!mImageHost || !mImageHost->IsAttached()) {
    return;
  }

#ifdef MOZ_DUMP_PAINTING
  if (gfxUtils::sDumpPainting) {
    RefPtr<gfx::DataSourceSurface> dSurf = mImageHost->GetAsSurface();
    gfxPlatform *platform = gfxPlatform::GetPlatform();
    RefPtr<gfx::DrawTarget> dt = platform->CreateDrawTargetForData(dSurf->GetData(),
                                                                   dSurf->GetSize(),
                                                                   dSurf->Stride(),
                                                                   dSurf->GetFormat());
    nsRefPtr<gfxASurface> surf = platform->GetThebesSurfaceForDrawTarget(dt);
    WriteSnapshotToDumpFile(this, surf);
  }
#endif

  mCompositor->MakeCurrent();

  EffectChain effectChain;
  LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(mMaskLayer, effectChain);

  gfx::Matrix4x4 transform;
  ToMatrix4x4(GetEffectiveTransform(), transform);
  gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
  mImageHost->SetCompositor(mCompositor);
  mImageHost->Composite(effectChain,
                        GetEffectiveOpacity(),
                        transform,
                        gfx::ToFilter(mFilter),
                        clipRect);
}
Example #8
0
bool
MemoryDIBTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
{
  RefPtr<gfxImageSurface> imgSurf = mSurface->GetAsImageSurface();

  RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();

  if (!srcSurf) {
    gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface (DIB).";
    return false;
  }

  DataSourceSurface::MappedSurface sourceMap;
  if (!srcSurf->Map(gfx::DataSourceSurface::READ, &sourceMap)) {
    gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
    return false;
  }

  for (int y = 0; y < srcSurf->GetSize().height; y++) {
    memcpy(imgSurf->Data() + imgSurf->Stride() * y,
           sourceMap.mData + sourceMap.mStride * y,
           srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
  }

  srcSurf->Unmap();
  return true;
}
Example #9
0
static void
SetAntialiasingFlags(Layer* aLayer, gfxContext* aTarget)
{
  if (!aTarget->IsCairo()) {
    RefPtr<DrawTarget> dt = aTarget->GetDrawTarget();

    if (dt->GetFormat() != FORMAT_B8G8R8A8) {
      return;
    }

    const nsIntRect& bounds = aLayer->GetVisibleRegion().GetBounds();
    gfx::Rect transformedBounds = dt->GetTransform().TransformBounds(gfx::Rect(Float(bounds.x), Float(bounds.y),
                                                                     Float(bounds.width), Float(bounds.height)));
    transformedBounds.RoundOut();
    IntRect intTransformedBounds;
    transformedBounds.ToIntRect(&intTransformedBounds);
    dt->SetPermitSubpixelAA(!(aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) ||
                            dt->GetOpaqueRect().Contains(intTransformedBounds));
  } else {
    nsRefPtr<gfxASurface> surface = aTarget->CurrentSurface();
    if (surface->GetContentType() != gfxASurface::CONTENT_COLOR_ALPHA) {
      // Destination doesn't have alpha channel; no need to set any special flags
      return;
    }

    const nsIntRect& bounds = aLayer->GetVisibleRegion().GetBounds();
    surface->SetSubpixelAntialiasingEnabled(
        !(aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) ||
        surface->GetOpaqueRect().Contains(
          aTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height))));
  }
}
Example #10
0
TemporaryRef<SourceSurface>
DrawTargetSkia::OptimizeSourceSurface(SourceSurface *aSurface) const
{
  if (aSurface->GetType() == SurfaceType::SKIA) {
    return aSurface;
  }

  if (!UsingSkiaGPU()) {
    // If we're not using skia-gl then drawing doesn't require any
    // uploading, so any data surface is fine. Call GetDataSurface
    // to trigger any required readback so that it only happens
    // once.
    return aSurface->GetDataSurface();
  }

  // If we are using skia-gl then we want to copy into a surface that
  // will cache the uploaded gl texture.
  RefPtr<DataSourceSurface> dataSurf = aSurface->GetDataSurface();
  DataSourceSurface::MappedSurface map;
  if (!dataSurf->Map(DataSourceSurface::READ, &map)) {
    return nullptr;
  }

  RefPtr<SourceSurface> result = CreateSourceSurfaceFromData(map.mData,
                                                             dataSurf->GetSize(),
                                                             map.mStride,
                                                             dataSurf->GetFormat());
  dataSurf->Unmap();
  return result.forget();
}
static TemporaryRef<DataSourceSurface> YInvertImageSurface(DataSourceSurface* aSurf)
{
  RefPtr<DataSourceSurface> temp =
    Factory::CreateDataSourceSurfaceWithStride(aSurf->GetSize(),
                                               aSurf->GetFormat(),
                                               aSurf->Stride());
  RefPtr<DrawTarget> dt =
    Factory::CreateDrawTargetForData(BackendType::CAIRO,
                                     temp->GetData(),
                                     temp->GetSize(),
                                     temp->Stride(),
                                     temp->GetFormat());
  nsRefPtr<gfxContext> ctx = new gfxContext(dt);
  ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
  ctx->Scale(1.0, -1.0);
  ctx->Translate(-gfxPoint(0.0, aSurf->GetSize().height));

  nsRefPtr<gfxImageSurface> thebesSurf =
    new gfxImageSurface(aSurf->GetData(),
                        ThebesIntSize(aSurf->GetSize()),
                        aSurf->Stride(),
                        SurfaceFormatToImageFormat(aSurf->GetFormat()));
  ctx->SetSource(thebesSurf);
  ctx->Paint();
  return temp.forget();
}
Example #12
0
TemporaryRef<SourceSurface>
DrawTargetD2D1::OptimizeSourceSurface(SourceSurface* aSurface) const
{
  if (aSurface->GetType() == SurfaceType::D2D1_1_IMAGE) {
    return aSurface;
  }

  RefPtr<DataSourceSurface> data = aSurface->GetDataSurface();

  DataSourceSurface::MappedSurface map;
  if (!data->Map(DataSourceSurface::MapType::READ, &map)) {
    return nullptr;
  }

  RefPtr<ID2D1Bitmap1> bitmap;
  HRESULT hr = mDC->CreateBitmap(D2DIntSize(data->GetSize()), map.mData, map.mStride,
                                 D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_NONE, D2DPixelFormat(data->GetFormat())),
                                 byRef(bitmap));

  data->Unmap();

  if (!bitmap) {
    return data;
  }

  return new SourceSurfaceD2D1(bitmap.get(), mDC, data->GetFormat(), data->GetSize());
}
Example #13
0
NS_IMETHODIMP
imgTools::EncodeImage(imgIContainer* aContainer,
                      const nsACString& aMimeType,
                      const nsAString& aOutputOptions,
                      nsIInputStream** aStream)
{
  // Use frame 0 from the image container.
  RefPtr<SourceSurface> frame =
    aContainer->GetFrame(imgIContainer::FRAME_FIRST,
                         imgIContainer::FLAG_SYNC_DECODE);
  NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);

  RefPtr<DataSourceSurface> dataSurface;

  if (frame->GetFormat() == SurfaceFormat::B8G8R8A8) {
    dataSurface = frame->GetDataSurface();
  } else {
    // Convert format to SurfaceFormat::B8G8R8A8
    dataSurface = gfxUtils::
      CopySurfaceToDataSourceSurfaceWithFormat(frame,
                                               SurfaceFormat::B8G8R8A8);
  }

  NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);

  return EncodeImageData(dataSurface, aMimeType, aOutputOptions, aStream);
}
Example #14
0
GdkPixbuf*
nsImageToPixbuf::SourceSurfaceToPixbuf(SourceSurface* aSurface,
                                       int32_t aWidth,
                                       int32_t aHeight)
{
    MOZ_ASSERT(aWidth <= aSurface->GetSize().width &&
               aHeight <= aSurface->GetSize().height,
               "Requested rect is bigger than the supplied surface");

    GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
                                       aWidth, aHeight);
    if (!pixbuf)
        return nullptr;

    uint32_t destStride = gdk_pixbuf_get_rowstride (pixbuf);
    guchar* destPixels = gdk_pixbuf_get_pixels (pixbuf);

    RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
    DataSourceSurface::MappedSurface map;
    if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map))
        return nullptr;

    uint8_t* srcData = map.mData;
    int32_t srcStride = map.mStride;

    SurfaceFormat format = dataSurface->GetFormat();

    for (int32_t row = 0; row < aHeight; ++row) {
        for (int32_t col = 0; col < aWidth; ++col) {
            guchar* destPixel = destPixels + row * destStride + 4 * col;

            uint32_t* srcPixel =
                reinterpret_cast<uint32_t*>((srcData + row * srcStride + 4 * col));

            if (format == SurfaceFormat::B8G8R8A8) {
                const uint8_t a = (*srcPixel >> 24) & 0xFF;
                const uint8_t r = unpremultiply((*srcPixel >> 16) & 0xFF, a);
                const uint8_t g = unpremultiply((*srcPixel >>  8) & 0xFF, a);
                const uint8_t b = unpremultiply((*srcPixel >>  0) & 0xFF, a);

                *destPixel++ = r;
                *destPixel++ = g;
                *destPixel++ = b;
                *destPixel++ = a;
            } else {
                MOZ_ASSERT(format == SurfaceFormat::B8G8R8X8);

                const uint8_t r = (*srcPixel >> 16) & 0xFF;
                const uint8_t g = (*srcPixel >>  8) & 0xFF;
                const uint8_t b = (*srcPixel >>  0) & 0xFF;

                *destPixel++ = r;
                *destPixel++ = g;
                *destPixel++ = b;
                *destPixel++ = 0xFF; // A
            }
        }
    }
Example #15
0
void
TextureClientD3D11::UpdateFromSurface(gfx::SourceSurface* aSurface)
{
  RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();

  if (!srcSurf) {
    gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
    return;
  }

  if (mDrawTarget) {
    // Ensure unflushed work from our outstanding drawtarget won't override this
    // update later.
    mDrawTarget->Flush();
  }

  if (mSize != srcSurf->GetSize() || mFormat != srcSurf->GetFormat()) {
    gfxCriticalError() << "Attempt to update texture client from a surface with a different size or format!";
    return;
  }

  DataSourceSurface::MappedSurface sourceMap;
  if (!srcSurf->Map(DataSourceSurface::READ, &sourceMap)) {
    gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
    return;
  }

  if (mTexture) {
    RefPtr<ID3D11Device> device;
    mTexture->GetDevice(getter_AddRefs(device));
    RefPtr<ID3D11DeviceContext> ctx;
    device->GetImmediateContext(getter_AddRefs(ctx));

    D3D11_BOX box;
    box.front = 0;
    box.back = 1;
    box.top = box.left = 0;
    box.right = aSurface->GetSize().width;
    box.bottom = aSurface->GetSize().height;

    ctx->UpdateSubresource(mTexture, 0, &box, sourceMap.mData, sourceMap.mStride, 0);
  } else {
    RefPtr<ID3D10Device> device;
    mTexture10->GetDevice(getter_AddRefs(device));

    D3D10_BOX box;
    box.front = 0;
    box.back = 1;
    box.top = box.left = 0;
    box.right = aSurface->GetSize().width;
    box.bottom = aSurface->GetSize().height;

    device->UpdateSubresource(mTexture10, 0, &box, sourceMap.mData, sourceMap.mStride, 0);
  }
  srcSurf->Unmap();
}
bool
GrallocTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
{
  MOZ_ASSERT(mMappedBuffer, "Calling TextureClient::BorrowDrawTarget without locking :(");

  if (!mMappedBuffer) {
    return false;
  }

  RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();

  if (!srcSurf) {
    gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface (GTC).";
    return false;
  }

  gfx::SurfaceFormat format = SurfaceFormatForPixelFormat(mGraphicBuffer->getPixelFormat());
  if (mSize != srcSurf->GetSize() || mFormat != srcSurf->GetFormat()) {
    gfxCriticalError() << "Attempt to update texture client from a surface with a different size or format! This: " << mSize << " " << format << " Other: " << srcSurf->GetSize() << " " << srcSurf->GetFormat();
    return false;
  }

  long pixelStride = mGraphicBuffer->getStride();
  long byteStride = pixelStride * BytesPerPixel(format);

  DataSourceSurface::MappedSurface sourceMap;

  if (!srcSurf->Map(DataSourceSurface::READ, &sourceMap)) {
    gfxCriticalError() << "Failed to map source surface for UpdateFromSurface (GTC).";
    return false;
  }

  for (int y = 0; y < srcSurf->GetSize().height; y++) {
    memcpy(mMappedBuffer + byteStride * y,
           sourceMap.mData + sourceMap.mStride * y,
           srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
  }

  srcSurf->Unmap();

  return true;
}
nsresult
nsDragServiceProxy::InvokeDragSessionImpl(nsIArray* aArrayTransferables,
                                          nsIScriptableRegion* aRegion,
                                          uint32_t aActionType)
{
  nsCOMPtr<nsIDocument> doc = do_QueryInterface(mSourceDocument);
  NS_ENSURE_STATE(doc->GetDocShell());
  TabChild* child = TabChild::GetFrom(doc->GetDocShell());
  NS_ENSURE_STATE(child);
  nsTArray<mozilla::dom::IPCDataTransfer> dataTransfers;
  nsContentUtils::TransferablesToIPCTransferables(aArrayTransferables,
                                                  dataTransfers,
                                                  false,
                                                  child->Manager(),
                                                  nullptr);

  LayoutDeviceIntRect dragRect;
  if (mHasImage || mSelection) {
    nsPresContext* pc;
    RefPtr<mozilla::gfx::SourceSurface> surface;
    DrawDrag(mSourceNode, aRegion, mScreenPosition, &dragRect, &surface, &pc);

    if (surface) {
      RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
        surface->GetDataSurface();
      if (dataSurface) {
        size_t length;
        int32_t stride;
        Shmem surfaceData;
        nsContentUtils::GetSurfaceData(dataSurface, &length, &stride, child,
                                       &surfaceData);
        // Save the surface data to shared memory.
        if (!surfaceData.IsReadable() || !surfaceData.get<char>()) {
          NS_WARNING("Failed to create shared memory for drag session.");
          return NS_ERROR_FAILURE;
        }

        mozilla::Unused <<
          child->SendInvokeDragSession(dataTransfers, aActionType, surfaceData,
                                       stride, static_cast<uint8_t>(dataSurface->GetFormat()),
                                       dragRect);
        StartDragSession();
        return NS_OK;
      }
    }
  }

  mozilla::Unused << child->SendInvokeDragSession(dataTransfers, aActionType,
                                                  mozilla::void_t(), 0, 0, dragRect);
  StartDragSession();
  return NS_OK;
}
Example #18
0
NS_IMETHODIMP
PuppetWidget::SetCursor(imgIContainer* aCursor,
                        uint32_t aHotspotX, uint32_t aHotspotY)
{
  if (!aCursor || !mTabChild) {
    return NS_OK;
  }

#if !defined(XP_WIN)
  if (mCustomCursor == aCursor &&
      mCursorHotspotX == aHotspotX &&
      mCursorHotspotY == aHotspotY &&
      !mUpdateCursor) {
    return NS_OK;
  }
#endif

  RefPtr<mozilla::gfx::SourceSurface> surface =
    aCursor->GetFrame(imgIContainer::FRAME_CURRENT,
                      imgIContainer::FLAG_SYNC_DECODE);
  if (!surface) {
    return NS_ERROR_FAILURE;
  }

  RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
    surface->GetDataSurface();
  if (!dataSurface) {
    return NS_ERROR_FAILURE;
  }

  size_t length;
  int32_t stride;
  mozilla::UniquePtr<char[]> surfaceData =
    nsContentUtils::GetSurfaceData(WrapNotNull(dataSurface), &length, &stride);

  nsDependentCString cursorData(surfaceData.get(), length);
  mozilla::gfx::IntSize size = dataSurface->GetSize();
  if (!mTabChild->SendSetCustomCursor(cursorData, size.width, size.height, stride,
                                      static_cast<uint8_t>(dataSurface->GetFormat()),
                                      aHotspotX, aHotspotY, mUpdateCursor)) {
    return NS_ERROR_FAILURE;
  }

  mCursor = nsCursor(-1);
  mCustomCursor = aCursor;
  mCursorHotspotX = aHotspotX;
  mCursorHotspotY = aHotspotY;
  mUpdateCursor = false;

  return NS_OK;
}
nsresult
nsDragServiceProxy::InvokeDragSessionImpl(nsISupportsArray* aArrayTransferables,
                                          nsIScriptableRegion* aRegion,
                                          uint32_t aActionType)
{
  nsCOMPtr<nsIDocument> doc = do_QueryInterface(mSourceDocument);
  NS_ENSURE_STATE(doc->GetDocShell());
  mozilla::dom::TabChild* child =
    mozilla::dom::TabChild::GetFrom(doc->GetDocShell());
  NS_ENSURE_STATE(child);
  nsTArray<mozilla::dom::IPCDataTransfer> dataTransfers;
  nsContentUtils::TransferablesToIPCTransferables(aArrayTransferables,
                                                  dataTransfers,
                                                  false,
                                                  child->Manager(),
                                                  nullptr);

  if (mHasImage || mSelection) {
    nsIntRect dragRect;
    nsPresContext* pc;
    RefPtr<mozilla::gfx::SourceSurface> surface;
    DrawDrag(mSourceNode, aRegion, mScreenX, mScreenY,
             &dragRect, &surface, &pc);

    if (surface) {
      RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
        surface->GetDataSurface();
      mozilla::gfx::IntSize size = dataSurface->GetSize();

      size_t length;
      int32_t stride;
      mozilla::UniquePtr<char[]> surfaceData =
        nsContentUtils::GetSurfaceData(dataSurface, &length, &stride);
      nsDependentCString dragImage(surfaceData.get(), length);

      mozilla::unused <<
        child->SendInvokeDragSession(dataTransfers, aActionType, dragImage,
                                     size.width, size.height, stride,
                                     static_cast<uint8_t>(dataSurface->GetFormat()),
                                     dragRect.x, dragRect.y);
      StartDragSession();
      return NS_OK;
    }
  }

  mozilla::unused << child->SendInvokeDragSession(dataTransfers, aActionType,
                                                  nsCString(),
                                                  0, 0, 0, 0, 0, 0);
  StartDragSession();
  return NS_OK;
}
Example #20
0
// Run the test for a texture client and a surface
void TestTextureClientSurface(TextureClient* texture, gfxImageSurface* surface) {

  // client allocation
  ASSERT_TRUE(texture->CanExposeDrawTarget());

  ASSERT_TRUE(texture->Lock(OpenMode::OPEN_READ_WRITE));
  // client painting
  RefPtr<DrawTarget> dt = texture->BorrowDrawTarget();
  RefPtr<SourceSurface> source =
    gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, surface);
  dt->CopySurface(source, IntRect(IntPoint(), source->GetSize()), IntPoint());

  RefPtr<SourceSurface> snapshot = dt->Snapshot();

  AssertSurfacesEqual(snapshot, source);

  dt = nullptr; // drop reference before calling Unlock()
  texture->Unlock();

  // client serialization
  SurfaceDescriptor descriptor;
  ASSERT_TRUE(texture->ToSurfaceDescriptor(descriptor));

  ASSERT_NE(descriptor.type(), SurfaceDescriptor::Tnull_t);

  // host deserialization
  RefPtr<TextureHost> host = CreateBackendIndependentTextureHost(descriptor, nullptr,
                                                                 texture->GetFlags());

  ASSERT_TRUE(host.get() != nullptr);
  ASSERT_EQ(host->GetFlags(), texture->GetFlags());

  // host read

  // XXX - this can fail because lock tries to upload the texture but it needs a
  // Compositor to do that. We could add a DummyComposior for testing but I am
  // not sure it'll be worth it. Maybe always test against a BasicCompositor,
  // but the latter needs a widget...
  if (host->Lock()) {
    RefPtr<mozilla::gfx::DataSourceSurface> hostDataSurface = host->GetAsSurface();

    RefPtr<gfxImageSurface> hostSurface =
      new gfxImageSurface(hostDataSurface->GetData(),
                          hostDataSurface->GetSize(),
                          hostDataSurface->Stride(),
                          SurfaceFormatToImageFormat(hostDataSurface->GetFormat()));
    AssertSurfacesEqual(surface, hostSurface.get());
    host->Unlock();
  }
}
Example #21
0
already_AddRefed<gfxASurface>
gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
{
  // If we have already created a thebes surface, we can just return it.
  void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
  if (surface) {
    nsRefPtr<gfxASurface> surf = static_cast<gfxASurface*>(surface);
    return surf.forget();
  }

  nsRefPtr<gfxASurface> surf;
  if (aTarget->GetType() == BACKEND_CAIRO) {
    cairo_surface_t* csurf =
      static_cast<cairo_surface_t*>(aTarget->GetNativeSurface(NATIVE_SURFACE_CAIRO_SURFACE));
    surf = gfxASurface::Wrap(csurf);
  } else {
    // The semantics of this part of the function are sort of weird. If we
    // don't have direct support for the backend, we snapshot the first time
    // and then return the snapshotted surface for the lifetime of the draw
    // target. Sometimes it seems like this works out, but it seems like it
    // might result in no updates ever.
    RefPtr<SourceSurface> source = aTarget->Snapshot();
    RefPtr<DataSourceSurface> data = source->GetDataSurface();

    if (!data) {
      return NULL;
    }

    IntSize size = data->GetSize();
    gfxASurface::gfxImageFormat format = OptimalFormatForContent(ContentForFormat(data->GetFormat()));

    // We need to make a copy here because data might change its data under us
    nsRefPtr<gfxImageSurface> imageSurf = new gfxImageSurface(gfxIntSize(size.width, size.height), format, false);
 
    bool resultOfCopy = imageSurf->CopyFrom(source);
    NS_ASSERTION(resultOfCopy, "Failed to copy surface.");
    surf = imageSurf;
  }

  // add a reference to be held by the drawTarget
  // careful, the reference graph is getting complicated here
  surf->AddRef();
  aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);

  return surf.forget();
}
Example #22
0
// Run the test for a texture client and a surface
void TestTextureClientSurface(TextureClient* texture, gfxImageSurface* surface) {

    // client allocation
    ASSERT_TRUE(texture->CanExposeDrawTarget());
    texture->AllocateForSurface(ToIntSize(surface->GetSize()));
    ASSERT_TRUE(texture->IsAllocated());

    ASSERT_TRUE(texture->Lock(OPEN_READ_WRITE));
    // client painting
    RefPtr<DrawTarget> dt = texture->GetAsDrawTarget();
    RefPtr<SourceSurface> source =
        gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, surface);
    dt->CopySurface(source, IntRect(IntPoint(), source->GetSize()), IntPoint());

    RefPtr<SourceSurface> snapshot = dt->Snapshot();

    AssertSurfacesEqual(snapshot, source);

    dt = nullptr; // drop reference before calling Unlock()
    texture->Unlock();

    // client serialization
    SurfaceDescriptor descriptor;
    ASSERT_TRUE(texture->ToSurfaceDescriptor(descriptor));

    ASSERT_NE(descriptor.type(), SurfaceDescriptor::Tnull_t);

    // host deserialization
    RefPtr<TextureHost> host = CreateBackendIndependentTextureHost(descriptor, nullptr,
                               texture->GetFlags());

    ASSERT_TRUE(host.get() != nullptr);
    ASSERT_EQ(host->GetFlags(), texture->GetFlags());

    // host read
    ASSERT_TRUE(host->Lock());
    RefPtr<mozilla::gfx::DataSourceSurface> hostDataSurface = host->GetAsSurface();
    host->Unlock();

    nsRefPtr<gfxImageSurface> hostSurface =
        new gfxImageSurface(hostDataSurface->GetData(),
                            ThebesIntSize(hostDataSurface->GetSize()),
                            hostDataSurface->Stride(),
                            SurfaceFormatToImageFormat(hostDataSurface->GetFormat()));
    AssertSurfacesEqual(surface, hostSurface.get());
}
Example #23
0
TextureClient*
CairoImage::GetTextureClient(CompositableClient *aClient)
{
  if (!aClient) {
    return nullptr;
  }

  CompositableForwarder* forwarder = aClient->GetForwarder();
  RefPtr<TextureClient> textureClient = mTextureClients.Get(forwarder->GetSerial());
  if (textureClient) {
    return textureClient;
  }

  RefPtr<SourceSurface> surface = GetAsSourceSurface();
  MOZ_ASSERT(surface);
  if (!surface) {
    return nullptr;
  }

  // gfx::BackendType::NONE means default to content backend
  textureClient = aClient->CreateTextureClientForDrawing(surface->GetFormat(),
                                                         surface->GetSize(),
                                                         gfx::BackendType::NONE,
                                                         TextureFlags::DEFAULT);
  if (!textureClient) {
    return nullptr;
  }
  MOZ_ASSERT(textureClient->CanExposeDrawTarget());
  if (!textureClient->Lock(OpenMode::OPEN_WRITE_ONLY)) {
    return nullptr;
  }

  TextureClientAutoUnlock autoUnolck(textureClient);
  {
    // We must not keep a reference to the DrawTarget after it has been unlocked.
    DrawTarget* dt = textureClient->BorrowDrawTarget();
    if (!dt) {
      return nullptr;
    }
    dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint());
  }

  mTextureClients.Put(forwarder->GetSerial(), textureClient);
  return textureClient;
}
Example #24
0
TemporaryRef<SourceSurface>
DrawTargetSkia::OptimizeSourceSurface(SourceSurface *aSurface) const
{
  if (aSurface->GetType() == SurfaceType::SKIA) {
    return aSurface;
  }

  if (aSurface->GetType() != SurfaceType::DATA) {
    return nullptr;
  }

  RefPtr<DataSourceSurface> data = aSurface->GetDataSurface();
  RefPtr<SourceSurface> surface = CreateSourceSurfaceFromData(data->GetData(),
                                                              data->GetSize(),
                                                              data->Stride(),
                                                              data->GetFormat());
  return data.forget();
}
Example #25
0
void
CompositableHost::DumpTextureHost(FILE* aFile, TextureHost* aTexture)
{
  if (!aTexture) {
    return;
  }
  RefPtr<gfx::DataSourceSurface> dSurf = aTexture->GetAsSurface();
  gfxPlatform *platform = gfxPlatform::GetPlatform();
  RefPtr<gfx::DrawTarget> dt = platform->CreateDrawTargetForData(dSurf->GetData(),
                                                                 dSurf->GetSize(),
                                                                 dSurf->Stride(),
                                                                 dSurf->GetFormat());
  nsRefPtr<gfxASurface> surf = platform->GetThebesSurfaceForDrawTarget(dt);
  if (!surf) {
    return;
  }
  surf->DumpAsDataURL(aFile ? aFile : stderr);
}
Example #26
0
static already_AddRefed<IDirect3DTexture9>
SurfaceToTexture(IDirect3DDevice9 *aDevice,
                 SourceSurface *aSurface,
                 const IntSize &aSize)
{
  RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
  if (!dataSurface) {
    return nullptr;
  }
  DataSourceSurface::MappedSurface map;
  if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map)) {
    return nullptr;
  }
  nsRefPtr<IDirect3DTexture9> texture =
    DataToTexture(aDevice, map.mData, map.mStride, aSize,
                  D3dFormatForSurfaceFormat(dataSurface->GetFormat()));
  dataSurface->Unmap();
  return texture.forget();
}
Example #27
0
static void
CheckDecoderResults(const ImageTestCase& aTestCase, Decoder* aDecoder)
{
  EXPECT_TRUE(aDecoder->GetDecodeDone());
  EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR),
            aDecoder->HasError());
  EXPECT_TRUE(!aDecoder->WasAborted());

  // Verify that the decoder made the expected progress.
  Progress progress = aDecoder->TakeProgress();
  EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR),
            bool(progress & FLAG_HAS_ERROR));

  if (aTestCase.mFlags & TEST_CASE_HAS_ERROR) {
    return;  // That's all we can check for bad images.
  }

  EXPECT_TRUE(bool(progress & FLAG_SIZE_AVAILABLE));
  EXPECT_TRUE(bool(progress & FLAG_DECODE_COMPLETE));
  EXPECT_TRUE(bool(progress & FLAG_FRAME_COMPLETE));
  EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT),
            bool(progress & FLAG_HAS_TRANSPARENCY));
  EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_ANIMATED),
            bool(progress & FLAG_IS_ANIMATED));

  // The decoder should get the correct size.
  IntSize size = aDecoder->GetSize();
  EXPECT_EQ(aTestCase.mSize.width, size.width);
  EXPECT_EQ(aTestCase.mSize.height, size.height);

  // Get the current frame, which is always the first frame of the image
  // because CreateAnonymousDecoder() forces a first-frame-only decode.
  RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
  RefPtr<SourceSurface> surface = currentFrame->GetSurface();

  // Verify that the resulting surfaces matches our expectations.
  EXPECT_EQ(SurfaceType::DATA, surface->GetType());
  EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::B8G8R8X8 ||
              surface->GetFormat() == SurfaceFormat::B8G8R8A8);
  EXPECT_EQ(aTestCase.mSize, surface->GetSize());
  EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green(),
                           aTestCase.mFlags & TEST_CASE_IS_FUZZY));
}
Example #28
0
// Run the test for a texture client and a surface
void TestTextureClientSurface(TextureClient* texture, gfxImageSurface* surface) {

  // client allocation
  ASSERT_TRUE(texture->AsTextureClientSurface() != nullptr);
  TextureClientSurface* client = texture->AsTextureClientSurface();
  client->AllocateForSurface(ToIntSize(surface->GetSize()));
  ASSERT_TRUE(texture->IsAllocated());

  ASSERT_TRUE(texture->Lock(OPEN_READ_WRITE));
  // client painting
  client->UpdateSurface(surface);

  nsRefPtr<gfxASurface> aSurface = client->GetAsSurface();
  nsRefPtr<gfxImageSurface> clientSurface = aSurface->GetAsImageSurface();

  AssertSurfacesEqual(surface, clientSurface);
  texture->Unlock();

  // client serialization
  SurfaceDescriptor descriptor;
  ASSERT_TRUE(texture->ToSurfaceDescriptor(descriptor));

  ASSERT_NE(descriptor.type(), SurfaceDescriptor::Tnull_t);

  // host deserialization
  RefPtr<TextureHost> host = CreateBackendIndependentTextureHost(descriptor, nullptr,
                                                                 texture->GetFlags());

  ASSERT_TRUE(host.get() != nullptr);
  ASSERT_EQ(host->GetFlags(), texture->GetFlags());

  // host read
  ASSERT_TRUE(host->Lock());
  RefPtr<mozilla::gfx::DataSourceSurface> hostDataSurface = host->GetAsSurface();
  host->Unlock();

  nsRefPtr<gfxImageSurface> hostSurface =
    new gfxImageSurface(hostDataSurface->GetData(),
                        ThebesIntSize(hostDataSurface->GetSize()),
                        hostDataSurface->Stride(),
                        SurfaceFormatToImageFormat(hostDataSurface->GetFormat()));
  AssertSurfacesEqual(surface, hostSurface.get());
}
Example #29
0
static already_AddRefed<SourceSurface>
CheckDecoderState(const ImageTestCase& aTestCase, Decoder* aDecoder)
{
  EXPECT_TRUE(aDecoder->GetDecodeDone());
  EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR),
            aDecoder->HasError());

  // Verify that the decoder made the expected progress.
  Progress progress = aDecoder->TakeProgress();
  EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR),
            bool(progress & FLAG_HAS_ERROR));

  if (aTestCase.mFlags & TEST_CASE_HAS_ERROR) {
    return nullptr;  // That's all we can check for bad images.
  }

  EXPECT_TRUE(bool(progress & FLAG_SIZE_AVAILABLE));
  EXPECT_TRUE(bool(progress & FLAG_DECODE_COMPLETE));
  EXPECT_TRUE(bool(progress & FLAG_FRAME_COMPLETE));
  EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT),
            bool(progress & FLAG_HAS_TRANSPARENCY));
  EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_ANIMATED),
            bool(progress & FLAG_IS_ANIMATED));

  // The decoder should get the correct size.
  IntSize size = aDecoder->Size();
  EXPECT_EQ(aTestCase.mSize.width, size.width);
  EXPECT_EQ(aTestCase.mSize.height, size.height);

  // Get the current frame, which is always the first frame of the image
  // because CreateAnonymousDecoder() forces a first-frame-only decode.
  RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
  RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface();

  // Verify that the resulting surfaces matches our expectations.
  EXPECT_TRUE(surface->IsDataSourceSurface());
  EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::B8G8R8X8 ||
              surface->GetFormat() == SurfaceFormat::B8G8R8A8);
  EXPECT_EQ(aTestCase.mOutputSize, surface->GetSize());

  return surface.forget();
}
void DrawEventRecorderPrivate::StoreSourceSurfaceRecording(
    SourceSurface *aSurface, const char *aReason) {
  RefPtr<DataSourceSurface> dataSurf = aSurface->GetDataSurface();
  if (dataSurf) {
    DataSourceSurface::ScopedMap map(dataSurf, DataSourceSurface::READ);
    RecordEvent(RecordedSourceSurfaceCreation(
        aSurface, map.GetData(), map.GetStride(), dataSurf->GetSize(),
        dataSurf->GetFormat()));
    return;
  }

  gfxWarning() << "Recording failed to record SourceSurface for " << aReason;
  // Insert a bogus source surface.
  int32_t stride =
      aSurface->GetSize().width * BytesPerPixel(aSurface->GetFormat());
  UniquePtr<uint8_t[]> sourceData(
      new uint8_t[stride * aSurface->GetSize().height]());
  RecordEvent(RecordedSourceSurfaceCreation(aSurface, sourceData.get(), stride,
                                            aSurface->GetSize(),
                                            aSurface->GetFormat()));
}