// 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; }
// 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); }
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; }
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)))); } }
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(); }
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()); }
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); }
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 } } }
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; }
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; }
// 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(); } }
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(); }
// 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()); }
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; }
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(); }
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); }
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(); }
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)); }
// 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()); }
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())); }