gfx/2d/SourceSurfaceD2D.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/2d/SourceSurfaceD2D.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,303 @@
     1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "SourceSurfaceD2D.h"
    1.10 +#include "DrawTargetD2D.h"
    1.11 +#include "Logging.h"
    1.12 +#include "Tools.h"
    1.13 +
    1.14 +namespace mozilla {
    1.15 +namespace gfx {
    1.16 +
    1.17 +SourceSurfaceD2D::SourceSurfaceD2D()
    1.18 +{
    1.19 +}
    1.20 +
    1.21 +SourceSurfaceD2D::~SourceSurfaceD2D()
    1.22 +{
    1.23 +  if (mBitmap) {
    1.24 +    DrawTargetD2D::mVRAMUsageSS -= GetByteSize();
    1.25 +  }
    1.26 +}
    1.27 +
    1.28 +IntSize
    1.29 +SourceSurfaceD2D::GetSize() const
    1.30 +{
    1.31 +  return mSize;
    1.32 +}
    1.33 +
    1.34 +SurfaceFormat
    1.35 +SourceSurfaceD2D::GetFormat() const
    1.36 +{
    1.37 +  return mFormat;
    1.38 +}
    1.39 +
    1.40 +bool
    1.41 +SourceSurfaceD2D::IsValid() const
    1.42 +{
    1.43 +  return mDevice == Factory::GetDirect3D10Device();
    1.44 +}
    1.45 +
    1.46 +TemporaryRef<DataSourceSurface>
    1.47 +SourceSurfaceD2D::GetDataSurface()
    1.48 +{
    1.49 +  RefPtr<DataSourceSurfaceD2D> result = new DataSourceSurfaceD2D(this);
    1.50 +  if (result->IsValid()) {
    1.51 +    return result;
    1.52 +  }
    1.53 +  return nullptr;
    1.54 +}
    1.55 +
    1.56 +bool
    1.57 +SourceSurfaceD2D::InitFromData(unsigned char *aData,
    1.58 +                               const IntSize &aSize,
    1.59 +                               int32_t aStride,
    1.60 +                               SurfaceFormat aFormat,
    1.61 +                               ID2D1RenderTarget *aRT)
    1.62 +{
    1.63 +  HRESULT hr;
    1.64 +
    1.65 +  mFormat = aFormat;
    1.66 +  mSize = aSize;
    1.67 +
    1.68 +  if ((uint32_t)aSize.width > aRT->GetMaximumBitmapSize() ||
    1.69 +      (uint32_t)aSize.height > aRT->GetMaximumBitmapSize()) {
    1.70 +    gfxDebug() << "Bitmap does not fit in texture.";
    1.71 +    return false;
    1.72 +  }
    1.73 +
    1.74 +  D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(aFormat));
    1.75 +  hr = aRT->CreateBitmap(D2DIntSize(aSize), aData, aStride, props, byRef(mBitmap));
    1.76 +
    1.77 +  if (FAILED(hr)) {
    1.78 +    gfxWarning() << "Failed to create D2D Bitmap for data. Code: " << hr;
    1.79 +    return false;
    1.80 +  }
    1.81 +
    1.82 +  DrawTargetD2D::mVRAMUsageSS += GetByteSize();
    1.83 +  mDevice = Factory::GetDirect3D10Device();
    1.84 +
    1.85 +  return true;
    1.86 +}
    1.87 +
    1.88 +bool
    1.89 +SourceSurfaceD2D::InitFromTexture(ID3D10Texture2D *aTexture,
    1.90 +                                  SurfaceFormat aFormat,
    1.91 +                                  ID2D1RenderTarget *aRT)
    1.92 +{
    1.93 +  HRESULT hr;
    1.94 +
    1.95 +  RefPtr<IDXGISurface> surf;
    1.96 +
    1.97 +  hr = aTexture->QueryInterface((IDXGISurface**)&surf);
    1.98 +
    1.99 +  if (FAILED(hr)) {
   1.100 +    gfxWarning() << "Failed to QI texture to surface. Code: " << hr;
   1.101 +    return false;
   1.102 +  }
   1.103 +
   1.104 +  D3D10_TEXTURE2D_DESC desc;
   1.105 +  aTexture->GetDesc(&desc);
   1.106 +
   1.107 +  mSize = IntSize(desc.Width, desc.Height);
   1.108 +  mFormat = aFormat;
   1.109 +
   1.110 +  D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(aFormat));
   1.111 +  hr = aRT->CreateSharedBitmap(IID_IDXGISurface, surf, &props, byRef(mBitmap));
   1.112 +
   1.113 +  if (FAILED(hr)) {
   1.114 +    gfxWarning() << "Failed to create SharedBitmap. Code: " << hr;
   1.115 +    return false;
   1.116 +  }
   1.117 +
   1.118 +  aTexture->GetDevice(byRef(mDevice));
   1.119 +  DrawTargetD2D::mVRAMUsageSS += GetByteSize();
   1.120 +
   1.121 +  return true;
   1.122 +}
   1.123 +
   1.124 +uint32_t
   1.125 +SourceSurfaceD2D::GetByteSize() const
   1.126 +{
   1.127 +  return mSize.width * mSize.height * BytesPerPixel(mFormat);
   1.128 +}
   1.129 +
   1.130 +DataSourceSurfaceD2D::DataSourceSurfaceD2D(SourceSurfaceD2D* aSourceSurface)
   1.131 +  : mTexture(nullptr)
   1.132 +  , mFormat(aSourceSurface->mFormat)
   1.133 +  , mSize(aSourceSurface->mSize)
   1.134 +  , mMapped(false)
   1.135 +{
   1.136 +  // We allocate ourselves a regular D3D surface (sourceTexture) and paint the
   1.137 +  // D2D bitmap into it via a DXGI render target. Then we need to copy
   1.138 +  // sourceTexture into a staging texture (mTexture), which we will lazily map
   1.139 +  // to get the data.
   1.140 +
   1.141 +  CD3D10_TEXTURE2D_DESC desc(DXGIFormat(mFormat), mSize.width, mSize.height);
   1.142 +  desc.MipLevels = 1;
   1.143 +  desc.Usage = D3D10_USAGE_DEFAULT;
   1.144 +  desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
   1.145 +  RefPtr<ID3D10Texture2D> sourceTexture;
   1.146 +  HRESULT hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr,
   1.147 +                                                        byRef(sourceTexture));
   1.148 +  if (FAILED(hr)) {
   1.149 +    gfxWarning() << "Failed to create texture. Code: " << hr;
   1.150 +    return;
   1.151 +  }
   1.152 +
   1.153 +  RefPtr<IDXGISurface> dxgiSurface;
   1.154 +  hr = sourceTexture->QueryInterface((IDXGISurface**)byRef(dxgiSurface));
   1.155 +  if (FAILED(hr)) {
   1.156 +    gfxWarning() << "Failed to create DXGI surface. Code: " << hr;
   1.157 +    return;
   1.158 +  }
   1.159 +
   1.160 +  D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties(
   1.161 +            D2D1_RENDER_TARGET_TYPE_DEFAULT,
   1.162 +            D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED));
   1.163 +
   1.164 +  RefPtr<ID2D1RenderTarget> renderTarget;
   1.165 +  hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(dxgiSurface,
   1.166 +                                                               &rtProps,
   1.167 +                                                               byRef(renderTarget));
   1.168 +  if (FAILED(hr)) {
   1.169 +    gfxWarning() << "Failed to create render target. Code: " << hr;
   1.170 +    return;
   1.171 +  }
   1.172 +
   1.173 +  renderTarget->BeginDraw();
   1.174 +  renderTarget->Clear(D2D1::ColorF(0, 0.0f));
   1.175 +  renderTarget->DrawBitmap(aSourceSurface->mBitmap,
   1.176 +                           D2D1::RectF(0, 0,
   1.177 +                                       Float(mSize.width),
   1.178 +                                       Float(mSize.height)));
   1.179 +  hr = renderTarget->EndDraw();
   1.180 +  if (FAILED(hr)) {
   1.181 +    gfxWarning() << "Failed to draw bitmap. Code: " << hr;
   1.182 +    return;
   1.183 +  }
   1.184 +
   1.185 +  desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ | D3D10_CPU_ACCESS_WRITE;
   1.186 +  desc.Usage = D3D10_USAGE_STAGING;
   1.187 +  desc.BindFlags = 0;
   1.188 +  hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr, byRef(mTexture));
   1.189 +  if (FAILED(hr)) {
   1.190 +    gfxWarning() << "Failed to create staging texture. Code: " << hr;
   1.191 +    mTexture = nullptr;
   1.192 +    return;
   1.193 +  }
   1.194 +
   1.195 +  aSourceSurface->mDevice->CopyResource(mTexture, sourceTexture);
   1.196 +}
   1.197 +
   1.198 +DataSourceSurfaceD2D::~DataSourceSurfaceD2D()
   1.199 +{
   1.200 +  if (mMapped) {
   1.201 +    mTexture->Unmap(0);
   1.202 +  }
   1.203 +}
   1.204 +
   1.205 +unsigned char*
   1.206 +DataSourceSurfaceD2D::GetData()
   1.207 +{
   1.208 +  EnsureMappedTexture();
   1.209 +  if (!mMapped) {
   1.210 +    return nullptr;
   1.211 +  }
   1.212 +
   1.213 +  return reinterpret_cast<unsigned char*>(mData.pData);
   1.214 +}
   1.215 +
   1.216 +int32_t
   1.217 +DataSourceSurfaceD2D::Stride()
   1.218 +{
   1.219 +  EnsureMappedTexture();
   1.220 +  if (!mMapped) {
   1.221 +    return 0;
   1.222 +  }
   1.223 +
   1.224 +  return mData.RowPitch;
   1.225 +}
   1.226 +
   1.227 +IntSize
   1.228 +DataSourceSurfaceD2D::GetSize() const
   1.229 +{
   1.230 +  return mSize;
   1.231 +}
   1.232 +
   1.233 +SurfaceFormat
   1.234 +DataSourceSurfaceD2D::GetFormat() const
   1.235 +{
   1.236 +  return mFormat;
   1.237 +}
   1.238 +
   1.239 +bool
   1.240 +DataSourceSurfaceD2D::Map(MapType aMapType, MappedSurface *aMappedSurface)
   1.241 +{
   1.242 +  // DataSourceSurfaces used with the new Map API should not be used with GetData!!
   1.243 +  MOZ_ASSERT(!mMapped);
   1.244 +  MOZ_ASSERT(!mIsMapped);
   1.245 +
   1.246 +  if (!mTexture) {
   1.247 +    return false;
   1.248 +  }
   1.249 +
   1.250 +  D3D10_MAP mapType;
   1.251 +
   1.252 +  if (aMapType == MapType::READ) {
   1.253 +    mapType = D3D10_MAP_READ;
   1.254 +  } else if (aMapType == MapType::WRITE) {
   1.255 +    mapType = D3D10_MAP_WRITE;
   1.256 +  } else {
   1.257 +    mapType = D3D10_MAP_READ_WRITE;
   1.258 +  }
   1.259 +
   1.260 +  D3D10_MAPPED_TEXTURE2D map;
   1.261 +
   1.262 +  HRESULT hr = mTexture->Map(0, mapType, 0, &map);
   1.263 +
   1.264 +  if (FAILED(hr)) {
   1.265 +    gfxWarning() << "Texture map failed with code: " << hr;
   1.266 +    return false;
   1.267 +  }
   1.268 +
   1.269 +  aMappedSurface->mData = (uint8_t*)map.pData;
   1.270 +  aMappedSurface->mStride = map.RowPitch;
   1.271 +  mIsMapped = true;
   1.272 +
   1.273 +  return true;
   1.274 +}
   1.275 +
   1.276 +void
   1.277 +DataSourceSurfaceD2D::Unmap()
   1.278 +{
   1.279 +  MOZ_ASSERT(mIsMapped);
   1.280 +
   1.281 +  mIsMapped = false;
   1.282 +  mTexture->Unmap(0);
   1.283 +}
   1.284 +
   1.285 +void
   1.286 +DataSourceSurfaceD2D::EnsureMappedTexture()
   1.287 +{
   1.288 +  // Do not use GetData() after having used Map!
   1.289 +  MOZ_ASSERT(!mIsMapped);
   1.290 +
   1.291 +  if (mMapped ||
   1.292 +      !mTexture) {
   1.293 +    return;
   1.294 +  }
   1.295 +
   1.296 +  HRESULT hr = mTexture->Map(0, D3D10_MAP_READ, 0, &mData);
   1.297 +  if (FAILED(hr)) {
   1.298 +    gfxWarning() << "Failed to map texture. Code: " << hr;
   1.299 +    mTexture = nullptr;
   1.300 +  } else {
   1.301 +    mMapped = true;
   1.302 +  }
   1.303 +}
   1.304 +
   1.305 +}
   1.306 +}

mercurial