michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "SourceSurfaceD2D1.h" michael@0: #include "DrawTargetD2D1.h" michael@0: #include "Tools.h" michael@0: michael@0: namespace mozilla { michael@0: namespace gfx { michael@0: michael@0: SourceSurfaceD2D1::SourceSurfaceD2D1(ID2D1Image *aImage, ID2D1DeviceContext *aDC, michael@0: SurfaceFormat aFormat, const IntSize &aSize, michael@0: DrawTargetD2D1 *aDT) michael@0: : mImage(aImage) michael@0: , mDC(aDC) michael@0: , mDrawTarget(aDT) michael@0: { michael@0: aImage->QueryInterface((ID2D1Bitmap1**)byRef(mRealizedBitmap)); michael@0: michael@0: mFormat = aFormat; michael@0: mSize = aSize; michael@0: } michael@0: michael@0: SourceSurfaceD2D1::~SourceSurfaceD2D1() michael@0: { michael@0: } michael@0: michael@0: TemporaryRef michael@0: SourceSurfaceD2D1::GetDataSurface() michael@0: { michael@0: EnsureRealizedBitmap(); michael@0: michael@0: RefPtr softwareBitmap; michael@0: D2D1_BITMAP_PROPERTIES1 props; michael@0: props.dpiX = 96; michael@0: props.dpiY = 96; michael@0: props.pixelFormat = D2DPixelFormat(mFormat); michael@0: props.colorContext = nullptr; michael@0: props.bitmapOptions = D2D1_BITMAP_OPTIONS_CANNOT_DRAW | michael@0: D2D1_BITMAP_OPTIONS_CPU_READ; michael@0: mDC->CreateBitmap(D2DIntSize(mSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(softwareBitmap)); michael@0: michael@0: D2D1_POINT_2U point = D2D1::Point2U(0, 0); michael@0: D2D1_RECT_U rect = D2D1::RectU(0, 0, mSize.width, mSize.height); michael@0: softwareBitmap->CopyFromBitmap(&point, mRealizedBitmap, &rect); michael@0: return new DataSourceSurfaceD2D1(softwareBitmap, mFormat); michael@0: } michael@0: michael@0: void michael@0: SourceSurfaceD2D1::EnsureRealizedBitmap() michael@0: { michael@0: if (mRealizedBitmap) { michael@0: return; michael@0: } michael@0: michael@0: RefPtr dc; michael@0: Factory::GetD2D1Device()->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, byRef(dc)); michael@0: michael@0: D2D1_BITMAP_PROPERTIES1 props; michael@0: props.dpiX = 96; michael@0: props.dpiY = 96; michael@0: props.pixelFormat = D2DPixelFormat(mFormat); michael@0: props.colorContext = nullptr; michael@0: props.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET; michael@0: dc->CreateBitmap(D2DIntSize(mSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(mRealizedBitmap)); michael@0: michael@0: dc->SetTarget(mRealizedBitmap); michael@0: michael@0: dc->BeginDraw(); michael@0: dc->DrawImage(mImage); michael@0: dc->EndDraw(); michael@0: } michael@0: michael@0: void michael@0: SourceSurfaceD2D1::DrawTargetWillChange() michael@0: { michael@0: // At this point in time this should always be true here. michael@0: MOZ_ASSERT(mRealizedBitmap); michael@0: michael@0: RefPtr oldBitmap = mRealizedBitmap; michael@0: michael@0: D2D1_BITMAP_PROPERTIES1 props; michael@0: props.dpiX = 96; michael@0: props.dpiY = 96; michael@0: props.pixelFormat = D2DPixelFormat(mFormat); michael@0: props.colorContext = nullptr; michael@0: props.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET; michael@0: mDC->CreateBitmap(D2DIntSize(mSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(mRealizedBitmap)); michael@0: michael@0: D2D1_POINT_2U point = D2D1::Point2U(0, 0); michael@0: D2D1_RECT_U rect = D2D1::RectU(0, 0, mSize.width, mSize.height); michael@0: mRealizedBitmap->CopyFromBitmap(&point, oldBitmap, &rect); michael@0: mImage = mRealizedBitmap; michael@0: michael@0: DrawTargetD2D1::mVRAMUsageSS += mSize.width * mSize.height * BytesPerPixel(mFormat); michael@0: mDrawTarget = nullptr; michael@0: michael@0: // We now no longer depend on the source surface content remaining the same. michael@0: MarkIndependent(); michael@0: } michael@0: michael@0: void michael@0: SourceSurfaceD2D1::MarkIndependent() michael@0: { michael@0: if (mDrawTarget) { michael@0: MOZ_ASSERT(mDrawTarget->mSnapshot == this); michael@0: mDrawTarget->mSnapshot = nullptr; michael@0: mDrawTarget = nullptr; michael@0: } michael@0: } michael@0: michael@0: DataSourceSurfaceD2D1::DataSourceSurfaceD2D1(ID2D1Bitmap1 *aMappableBitmap, SurfaceFormat aFormat) michael@0: : mBitmap(aMappableBitmap) michael@0: , mFormat(aFormat) michael@0: , mMapped(false) michael@0: { michael@0: } michael@0: michael@0: DataSourceSurfaceD2D1::~DataSourceSurfaceD2D1() michael@0: { michael@0: if (mMapped) { michael@0: mBitmap->Unmap(); michael@0: } michael@0: } michael@0: michael@0: IntSize michael@0: DataSourceSurfaceD2D1::GetSize() const michael@0: { michael@0: D2D1_SIZE_F size = mBitmap->GetSize(); michael@0: michael@0: return IntSize(int32_t(size.width), int32_t(size.height)); michael@0: } michael@0: michael@0: uint8_t* michael@0: DataSourceSurfaceD2D1::GetData() michael@0: { michael@0: EnsureMapped(); michael@0: michael@0: return mMap.bits; michael@0: } michael@0: michael@0: bool michael@0: DataSourceSurfaceD2D1::Map(MapType aMapType, MappedSurface *aMappedSurface) michael@0: { michael@0: // DataSourceSurfaces used with the new Map API should not be used with GetData!! michael@0: MOZ_ASSERT(!mMapped); michael@0: MOZ_ASSERT(!mIsMapped); michael@0: michael@0: D2D1_MAP_OPTIONS options; michael@0: if (aMapType == MapType::READ) { michael@0: options = D2D1_MAP_OPTIONS_READ; michael@0: } else { michael@0: MOZ_CRASH("No support for Write maps on D2D1 DataSourceSurfaces yet!"); michael@0: } michael@0: michael@0: D2D1_MAPPED_RECT map; michael@0: mBitmap->Map(D2D1_MAP_OPTIONS_READ, &map); michael@0: aMappedSurface->mData = map.bits; michael@0: aMappedSurface->mStride = map.pitch; michael@0: michael@0: mIsMapped = true; michael@0: return true; michael@0: } michael@0: michael@0: void michael@0: DataSourceSurfaceD2D1::Unmap() michael@0: { michael@0: MOZ_ASSERT(mIsMapped); michael@0: michael@0: mIsMapped = false; michael@0: mBitmap->Unmap(); michael@0: } michael@0: michael@0: int32_t michael@0: DataSourceSurfaceD2D1::Stride() michael@0: { michael@0: EnsureMapped(); michael@0: michael@0: return mMap.pitch; michael@0: } michael@0: michael@0: void michael@0: DataSourceSurfaceD2D1::EnsureMapped() michael@0: { michael@0: // Do not use GetData() after having used Map! michael@0: MOZ_ASSERT(!mIsMapped); michael@0: if (mMapped) { michael@0: return; michael@0: } michael@0: mBitmap->Map(D2D1_MAP_OPTIONS_READ, &mMap); michael@0: mMapped = true; michael@0: } michael@0: michael@0: } michael@0: }