1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/d3d9/TextureD3D9.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1137 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 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 "TextureD3D9.h" 1.10 +#include "CompositorD3D9.h" 1.11 +#include "gfxContext.h" 1.12 +#include "gfxImageSurface.h" 1.13 +#include "Effects.h" 1.14 +#include "mozilla/layers/YCbCrImageDataSerializer.h" 1.15 +#include "gfxWindowsPlatform.h" 1.16 +#include "gfx2DGlue.h" 1.17 +#include "gfxUtils.h" 1.18 +#include "mozilla/gfx/2D.h" 1.19 + 1.20 +using namespace mozilla::gfx; 1.21 + 1.22 +namespace mozilla { 1.23 +namespace layers { 1.24 + 1.25 +static uint32_t GetRequiredTilesD3D9(uint32_t aSize, uint32_t aMaxSize) 1.26 +{ 1.27 + uint32_t requiredTiles = aSize / aMaxSize; 1.28 + if (aSize % aMaxSize) { 1.29 + requiredTiles++; 1.30 + } 1.31 + return requiredTiles; 1.32 +} 1.33 + 1.34 +TextureSourceD3D9::~TextureSourceD3D9() 1.35 +{ 1.36 + MOZ_ASSERT(!mCreatingDeviceManager || 1.37 + mCreatingDeviceManager->IsInTextureHostList(this), 1.38 + "Inconsistency in list of texture hosts."); 1.39 + // Remove ourselves from the list of d3d9 texture hosts. 1.40 + if (mPreviousHost) { 1.41 + MOZ_ASSERT(mPreviousHost->mNextHost == this); 1.42 + mPreviousHost->mNextHost = mNextHost; 1.43 + } else if (mCreatingDeviceManager) { 1.44 + mCreatingDeviceManager->RemoveTextureListHead(this); 1.45 + } 1.46 + if (mNextHost) { 1.47 + MOZ_ASSERT(mNextHost->mPreviousHost == this); 1.48 + mNextHost->mPreviousHost = mPreviousHost; 1.49 + } 1.50 +} 1.51 + 1.52 +TemporaryRef<TextureHost> 1.53 +CreateTextureHostD3D9(const SurfaceDescriptor& aDesc, 1.54 + ISurfaceAllocator* aDeallocator, 1.55 + TextureFlags aFlags) 1.56 +{ 1.57 + RefPtr<TextureHost> result; 1.58 + switch (aDesc.type()) { 1.59 + case SurfaceDescriptor::TSurfaceDescriptorShmem: 1.60 + case SurfaceDescriptor::TSurfaceDescriptorMemory: { 1.61 + result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags); 1.62 + break; 1.63 + } 1.64 + case SurfaceDescriptor::TSurfaceDescriptorD3D9: { 1.65 + result = new TextureHostD3D9(aFlags, aDesc); 1.66 + break; 1.67 + } 1.68 + case SurfaceDescriptor::TSurfaceDescriptorDIB: { 1.69 + result = new DIBTextureHostD3D9(aFlags, aDesc); 1.70 + break; 1.71 + } 1.72 + case SurfaceDescriptor::TSurfaceDescriptorD3D10: { 1.73 + result = new DXGITextureHostD3D9(aFlags, aDesc); 1.74 + break; 1.75 + } 1.76 + default: { 1.77 + NS_WARNING("Unsupported SurfaceDescriptor type"); 1.78 + } 1.79 + } 1.80 + return result.forget(); 1.81 +} 1.82 + 1.83 +static SurfaceFormat 1.84 +D3D9FormatToSurfaceFormat(_D3DFORMAT format) 1.85 +{ 1.86 + switch (format) { 1.87 + case D3DFMT_X8R8G8B8: 1.88 + return SurfaceFormat::B8G8R8X8; 1.89 + case D3DFMT_A8R8G8B8: 1.90 + return SurfaceFormat::B8G8R8A8; 1.91 + case D3DFMT_A8: 1.92 + return SurfaceFormat::A8; 1.93 + default: 1.94 + NS_ERROR("Bad texture format"); 1.95 + } 1.96 + return SurfaceFormat::UNKNOWN; 1.97 +} 1.98 + 1.99 +static _D3DFORMAT 1.100 +SurfaceFormatToD3D9Format(SurfaceFormat format) 1.101 +{ 1.102 + switch (format) { 1.103 + case SurfaceFormat::B8G8R8X8: 1.104 + return D3DFMT_X8R8G8B8; 1.105 + case SurfaceFormat::B8G8R8A8: 1.106 + return D3DFMT_A8R8G8B8; 1.107 + case SurfaceFormat::A8: 1.108 + return D3DFMT_A8; 1.109 + default: 1.110 + NS_ERROR("Bad texture format"); 1.111 + } 1.112 + return D3DFMT_A8R8G8B8; 1.113 +} 1.114 + 1.115 +CompositingRenderTargetD3D9::CompositingRenderTargetD3D9(IDirect3DTexture9* aTexture, 1.116 + SurfaceInitMode aInit, 1.117 + const gfx::IntRect& aRect) 1.118 + : CompositingRenderTarget(aRect.TopLeft()) 1.119 + , mInitMode(aInit) 1.120 + , mInitialized(false) 1.121 +{ 1.122 + MOZ_COUNT_CTOR(CompositingRenderTargetD3D9); 1.123 + MOZ_ASSERT(aTexture); 1.124 + 1.125 + mTexture = aTexture; 1.126 + HRESULT hr = mTexture->GetSurfaceLevel(0, getter_AddRefs(mSurface)); 1.127 + NS_ASSERTION(mSurface, "Couldn't create surface for texture"); 1.128 + TextureSourceD3D9::SetSize(aRect.Size()); 1.129 +} 1.130 + 1.131 +CompositingRenderTargetD3D9::CompositingRenderTargetD3D9(IDirect3DSurface9* aSurface, 1.132 + SurfaceInitMode aInit, 1.133 + const gfx::IntRect& aRect) 1.134 + : CompositingRenderTarget(aRect.TopLeft()) 1.135 + , mSurface(aSurface) 1.136 + , mInitMode(aInit) 1.137 + , mInitialized(false) 1.138 +{ 1.139 + MOZ_COUNT_CTOR(CompositingRenderTargetD3D9); 1.140 + MOZ_ASSERT(mSurface); 1.141 + TextureSourceD3D9::SetSize(aRect.Size()); 1.142 +} 1.143 + 1.144 +CompositingRenderTargetD3D9::~CompositingRenderTargetD3D9() 1.145 +{ 1.146 + MOZ_COUNT_DTOR(CompositingRenderTargetD3D9); 1.147 +} 1.148 + 1.149 +void 1.150 +CompositingRenderTargetD3D9::BindRenderTarget(IDirect3DDevice9* aDevice) 1.151 +{ 1.152 + aDevice->SetRenderTarget(0, mSurface); 1.153 + if (!mInitialized && 1.154 + mInitMode == INIT_MODE_CLEAR) { 1.155 + mInitialized = true; 1.156 + aDevice->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 0), 0, 0); 1.157 + } 1.158 +} 1.159 + 1.160 +IntSize 1.161 +CompositingRenderTargetD3D9::GetSize() const 1.162 +{ 1.163 + return TextureSourceD3D9::GetSize(); 1.164 +} 1.165 + 1.166 +/** 1.167 + * Helper method for DataToTexture and SurfaceToTexture. 1.168 + * The last three params are out params. 1.169 + * Returns the created texture, or null if we fail. 1.170 + */ 1.171 +TemporaryRef<IDirect3DTexture9> 1.172 +TextureSourceD3D9::InitTextures(DeviceManagerD3D9* aDeviceManager, 1.173 + const IntSize &aSize, 1.174 + _D3DFORMAT aFormat, 1.175 + RefPtr<IDirect3DSurface9>& aSurface, 1.176 + D3DLOCKED_RECT& aLockedRect) 1.177 +{ 1.178 + if (!aDeviceManager) { 1.179 + return nullptr; 1.180 + } 1.181 + RefPtr<IDirect3DTexture9> result; 1.182 + // D3D9Ex doesn't support managed textures and we don't want the hassle even 1.183 + // if we don't have Ex. We could use dynamic textures 1.184 + // here but since Images are immutable that probably isn't such a great 1.185 + // idea. 1.186 + result = aDeviceManager->CreateTexture(aSize, aFormat, D3DPOOL_DEFAULT, this); 1.187 + if (!result) { 1.188 + return nullptr; 1.189 + } 1.190 + 1.191 + RefPtr<IDirect3DTexture9> tmpTexture = 1.192 + aDeviceManager->CreateTexture(aSize, aFormat, D3DPOOL_SYSTEMMEM, this); 1.193 + if (!tmpTexture) { 1.194 + return nullptr; 1.195 + } 1.196 + 1.197 + tmpTexture->GetSurfaceLevel(0, byRef(aSurface)); 1.198 + aSurface->LockRect(&aLockedRect, nullptr, 0); 1.199 + if (!aLockedRect.pBits) { 1.200 + NS_WARNING("Could not lock surface"); 1.201 + return nullptr; 1.202 + } 1.203 + 1.204 + return result; 1.205 +} 1.206 + 1.207 +/** 1.208 + * Helper method for DataToTexture and SurfaceToTexture. 1.209 + */ 1.210 +static void 1.211 +FinishTextures(DeviceManagerD3D9* aDeviceManager, 1.212 + IDirect3DTexture9* aTexture, 1.213 + IDirect3DSurface9* aSurface) 1.214 +{ 1.215 + if (!aDeviceManager) { 1.216 + return; 1.217 + } 1.218 + 1.219 + aSurface->UnlockRect(); 1.220 + nsRefPtr<IDirect3DSurface9> dstSurface; 1.221 + aTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface)); 1.222 + aDeviceManager->device()->UpdateSurface(aSurface, nullptr, dstSurface, 1.223 + nullptr); 1.224 +} 1.225 + 1.226 +TemporaryRef<IDirect3DTexture9> 1.227 +TextureSourceD3D9::DataToTexture(DeviceManagerD3D9* aDeviceManager, 1.228 + unsigned char *aData, 1.229 + int aStride, 1.230 + const IntSize &aSize, 1.231 + _D3DFORMAT aFormat, 1.232 + uint32_t aBPP) 1.233 +{ 1.234 + RefPtr<IDirect3DSurface9> surface; 1.235 + D3DLOCKED_RECT lockedRect; 1.236 + RefPtr<IDirect3DTexture9> texture = InitTextures(aDeviceManager, aSize, aFormat, 1.237 + surface, lockedRect); 1.238 + if (!texture) { 1.239 + return nullptr; 1.240 + } 1.241 + 1.242 + uint32_t width = aSize.width * aBPP; 1.243 + 1.244 + for (int y = 0; y < aSize.height; y++) { 1.245 + memcpy((char*)lockedRect.pBits + lockedRect.Pitch * y, 1.246 + aData + aStride * y, 1.247 + width); 1.248 + } 1.249 + 1.250 + FinishTextures(aDeviceManager, texture, surface); 1.251 + 1.252 + return texture; 1.253 +} 1.254 + 1.255 +TemporaryRef<IDirect3DTexture9> 1.256 +TextureSourceD3D9::TextureToTexture(DeviceManagerD3D9* aDeviceManager, 1.257 + IDirect3DTexture9* aTexture, 1.258 + const IntSize& aSize, 1.259 + _D3DFORMAT aFormat) 1.260 +{ 1.261 + if (!aDeviceManager) { 1.262 + return nullptr; 1.263 + } 1.264 + 1.265 + RefPtr<IDirect3DTexture9> texture = 1.266 + aDeviceManager->CreateTexture(aSize, aFormat, D3DPOOL_DEFAULT, this); 1.267 + if (!texture) { 1.268 + return nullptr; 1.269 + } 1.270 + 1.271 + HRESULT hr = aDeviceManager->device()->UpdateTexture(aTexture, texture); 1.272 + if (FAILED(hr)) { 1.273 + return nullptr; 1.274 + } 1.275 + 1.276 + return texture; 1.277 +} 1.278 + 1.279 +TemporaryRef<IDirect3DTexture9> 1.280 +TextureSourceD3D9::SurfaceToTexture(DeviceManagerD3D9* aDeviceManager, 1.281 + gfxWindowsSurface* aSurface, 1.282 + const IntSize& aSize, 1.283 + _D3DFORMAT aFormat) 1.284 +{ 1.285 + RefPtr<IDirect3DSurface9> surface; 1.286 + D3DLOCKED_RECT lockedRect; 1.287 + 1.288 + RefPtr<IDirect3DTexture9> texture = InitTextures(aDeviceManager, aSize, aFormat, 1.289 + surface, lockedRect); 1.290 + if (!texture) { 1.291 + return nullptr; 1.292 + } 1.293 + 1.294 + nsRefPtr<gfxImageSurface> imgSurface = 1.295 + new gfxImageSurface(reinterpret_cast<unsigned char*>(lockedRect.pBits), 1.296 + gfxIntSize(aSize.width, aSize.height), 1.297 + lockedRect.Pitch, 1.298 + gfxPlatform::GetPlatform()->OptimalFormatForContent(aSurface->GetContentType())); 1.299 + 1.300 + nsRefPtr<gfxContext> context = new gfxContext(imgSurface); 1.301 + context->SetSource(aSurface); 1.302 + context->SetOperator(gfxContext::OPERATOR_SOURCE); 1.303 + context->Paint(); 1.304 + 1.305 + FinishTextures(aDeviceManager, texture, surface); 1.306 + 1.307 + return texture; 1.308 +} 1.309 + 1.310 +class D3D9TextureClientData : public TextureClientData 1.311 +{ 1.312 +public: 1.313 + D3D9TextureClientData(IDirect3DTexture9* aTexture) 1.314 + : mTexture(aTexture) 1.315 + {} 1.316 + 1.317 + D3D9TextureClientData(gfxWindowsSurface* aWindowSurface) 1.318 + : mWindowSurface(aWindowSurface) 1.319 + {} 1.320 + 1.321 + virtual void DeallocateSharedData(ISurfaceAllocator*) MOZ_OVERRIDE 1.322 + { 1.323 + mWindowSurface = nullptr; 1.324 + mTexture = nullptr; 1.325 + } 1.326 + 1.327 +private: 1.328 + RefPtr<IDirect3DTexture9> mTexture; 1.329 + nsRefPtr<gfxWindowsSurface> mWindowSurface; 1.330 +}; 1.331 + 1.332 +DataTextureSourceD3D9::DataTextureSourceD3D9(gfx::SurfaceFormat aFormat, 1.333 + CompositorD3D9* aCompositor, 1.334 + TextureFlags aFlags, 1.335 + StereoMode aStereoMode) 1.336 + : mFormat(aFormat) 1.337 + , mCompositor(aCompositor) 1.338 + , mCurrentTile(0) 1.339 + , mFlags(aFlags) 1.340 + , mIsTiled(false) 1.341 + , mIterating(false) 1.342 +{ 1.343 + mStereoMode = aStereoMode; 1.344 + MOZ_COUNT_CTOR(DataTextureSourceD3D9); 1.345 +} 1.346 + 1.347 +DataTextureSourceD3D9::DataTextureSourceD3D9(gfx::SurfaceFormat aFormat, 1.348 + gfx::IntSize aSize, 1.349 + CompositorD3D9* aCompositor, 1.350 + IDirect3DTexture9* aTexture, 1.351 + TextureFlags aFlags) 1.352 + : mFormat(aFormat) 1.353 + , mCompositor(aCompositor) 1.354 + , mCurrentTile(0) 1.355 + , mFlags(aFlags) 1.356 + , mIsTiled(false) 1.357 + , mIterating(false) 1.358 +{ 1.359 + mSize = aSize; 1.360 + mTexture = aTexture; 1.361 + mStereoMode = StereoMode::MONO; 1.362 + MOZ_COUNT_CTOR(DataTextureSourceD3D9); 1.363 +} 1.364 + 1.365 +DataTextureSourceD3D9::~DataTextureSourceD3D9() 1.366 +{ 1.367 + MOZ_COUNT_DTOR(DataTextureSourceD3D9); 1.368 +} 1.369 + 1.370 +IDirect3DTexture9* 1.371 +DataTextureSourceD3D9::GetD3D9Texture() 1.372 +{ 1.373 + return mIterating ? mTileTextures[mCurrentTile] 1.374 + : mTexture; 1.375 +} 1.376 + 1.377 +bool 1.378 +DataTextureSourceD3D9::Update(gfx::DataSourceSurface* aSurface, 1.379 + nsIntRegion* aDestRegion, 1.380 + gfx::IntPoint* aSrcOffset) 1.381 +{ 1.382 + // Right now we only support full surface update. If aDestRegion is provided, 1.383 + // It will be ignored. Incremental update with a source offset is only used 1.384 + // on Mac so it is not clear that we ever will need to support it for D3D. 1.385 + MOZ_ASSERT(!aSrcOffset); 1.386 + 1.387 + if (!mCompositor || !mCompositor->device()) { 1.388 + NS_WARNING("No D3D device to update the texture."); 1.389 + return false; 1.390 + } 1.391 + mSize = aSurface->GetSize(); 1.392 + 1.393 + uint32_t bpp = 0; 1.394 + 1.395 + _D3DFORMAT format = D3DFMT_A8R8G8B8; 1.396 + mFormat = aSurface->GetFormat(); 1.397 + switch (mFormat) { 1.398 + case SurfaceFormat::B8G8R8X8: 1.399 + format = D3DFMT_X8R8G8B8; 1.400 + bpp = 4; 1.401 + break; 1.402 + case SurfaceFormat::B8G8R8A8: 1.403 + format = D3DFMT_A8R8G8B8; 1.404 + bpp = 4; 1.405 + break; 1.406 + case SurfaceFormat::A8: 1.407 + format = D3DFMT_A8; 1.408 + bpp = 1; 1.409 + break; 1.410 + default: 1.411 + NS_WARNING("Bad image format"); 1.412 + return false; 1.413 + } 1.414 + 1.415 + int32_t maxSize = mCompositor->GetMaxTextureSize(); 1.416 + DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(); 1.417 + if ((mSize.width <= maxSize && mSize.height <= maxSize) || 1.418 + (mFlags & TEXTURE_DISALLOW_BIGIMAGE)) { 1.419 + mTexture = DataToTexture(deviceManager, 1.420 + aSurface->GetData(), aSurface->Stride(), 1.421 + IntSize(mSize), format, bpp); 1.422 + if (!mTexture) { 1.423 + NS_WARNING("Could not upload texture"); 1.424 + Reset(); 1.425 + return false; 1.426 + } 1.427 + mIsTiled = false; 1.428 + } else { 1.429 + mIsTiled = true; 1.430 + uint32_t tileCount = GetRequiredTilesD3D9(mSize.width, maxSize) * 1.431 + GetRequiredTilesD3D9(mSize.height, maxSize); 1.432 + mTileTextures.resize(tileCount); 1.433 + mTexture = nullptr; 1.434 + 1.435 + for (uint32_t i = 0; i < tileCount; i++) { 1.436 + IntRect tileRect = GetTileRect(i); 1.437 + unsigned char* data = aSurface->GetData() + 1.438 + tileRect.y * aSurface->Stride() + 1.439 + tileRect.x * bpp; 1.440 + mTileTextures[i] = DataToTexture(deviceManager, 1.441 + data, 1.442 + aSurface->Stride(), 1.443 + IntSize(tileRect.width, tileRect.height), 1.444 + format, 1.445 + bpp); 1.446 + if (!mTileTextures[i]) { 1.447 + NS_WARNING("Could not upload texture"); 1.448 + Reset(); 1.449 + return false; 1.450 + } 1.451 + } 1.452 + } 1.453 + 1.454 + return true; 1.455 +} 1.456 + 1.457 +bool 1.458 +DataTextureSourceD3D9::Update(gfxWindowsSurface* aSurface) 1.459 +{ 1.460 + MOZ_ASSERT(aSurface); 1.461 + if (!mCompositor || !mCompositor->device()) { 1.462 + NS_WARNING("No D3D device to update the texture."); 1.463 + return false; 1.464 + } 1.465 + mSize = ToIntSize(aSurface->GetSize()); 1.466 + 1.467 + uint32_t bpp = 0; 1.468 + 1.469 + _D3DFORMAT format = D3DFMT_A8R8G8B8; 1.470 + mFormat = ImageFormatToSurfaceFormat( 1.471 + gfxPlatform::GetPlatform()->OptimalFormatForContent(aSurface->GetContentType())); 1.472 + switch (mFormat) { 1.473 + case SurfaceFormat::B8G8R8X8: 1.474 + format = D3DFMT_X8R8G8B8; 1.475 + bpp = 4; 1.476 + break; 1.477 + case SurfaceFormat::B8G8R8A8: 1.478 + format = D3DFMT_A8R8G8B8; 1.479 + bpp = 4; 1.480 + break; 1.481 + case SurfaceFormat::A8: 1.482 + format = D3DFMT_A8; 1.483 + bpp = 1; 1.484 + break; 1.485 + default: 1.486 + NS_WARNING("Bad image format"); 1.487 + return false; 1.488 + } 1.489 + 1.490 + int32_t maxSize = mCompositor->GetMaxTextureSize(); 1.491 + DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(); 1.492 + if ((mSize.width <= maxSize && mSize.height <= maxSize) || 1.493 + (mFlags & TEXTURE_DISALLOW_BIGIMAGE)) { 1.494 + mTexture = SurfaceToTexture(deviceManager, aSurface, mSize, format); 1.495 + 1.496 + if (!mTexture) { 1.497 + NS_WARNING("Could not upload texture"); 1.498 + Reset(); 1.499 + return false; 1.500 + } 1.501 + mIsTiled = false; 1.502 + } else { 1.503 + mIsTiled = true; 1.504 + uint32_t tileCount = GetRequiredTilesD3D9(mSize.width, maxSize) * 1.505 + GetRequiredTilesD3D9(mSize.height, maxSize); 1.506 + mTileTextures.resize(tileCount); 1.507 + mTexture = nullptr; 1.508 + nsRefPtr<gfxImageSurface> imgSurface = aSurface->GetAsImageSurface(); 1.509 + 1.510 + for (uint32_t i = 0; i < tileCount; i++) { 1.511 + IntRect tileRect = GetTileRect(i); 1.512 + unsigned char* data = imgSurface->Data() + 1.513 + tileRect.y * imgSurface->Stride() + 1.514 + tileRect.x * bpp; 1.515 + mTileTextures[i] = DataToTexture(deviceManager, 1.516 + data, 1.517 + imgSurface->Stride(), 1.518 + IntSize(tileRect.width, tileRect.height), 1.519 + format, 1.520 + bpp); 1.521 + if (!mTileTextures[i]) { 1.522 + NS_WARNING("Could not upload texture"); 1.523 + Reset(); 1.524 + return false; 1.525 + } 1.526 + } 1.527 + } 1.528 + 1.529 + return true; 1.530 +} 1.531 + 1.532 +void 1.533 +DataTextureSourceD3D9::SetCompositor(Compositor* aCompositor) 1.534 +{ 1.535 + CompositorD3D9* d3dCompositor = static_cast<CompositorD3D9*>(aCompositor); 1.536 + if (mCompositor && mCompositor != d3dCompositor) { 1.537 + Reset(); 1.538 + } 1.539 + mCompositor = d3dCompositor; 1.540 +} 1.541 + 1.542 +void 1.543 +DataTextureSourceD3D9::Reset() 1.544 +{ 1.545 + mSize.width = 0; 1.546 + mSize.height = 0; 1.547 + mIsTiled = false; 1.548 + mTexture = nullptr; 1.549 + mTileTextures.clear(); 1.550 +} 1.551 + 1.552 +IntRect 1.553 +DataTextureSourceD3D9::GetTileRect(uint32_t aTileIndex) const 1.554 +{ 1.555 + uint32_t maxSize = mCompositor->GetMaxTextureSize(); 1.556 + uint32_t horizontalTiles = GetRequiredTilesD3D9(mSize.width, maxSize); 1.557 + uint32_t verticalTiles = GetRequiredTilesD3D9(mSize.height, maxSize); 1.558 + 1.559 + uint32_t verticalTile = aTileIndex / horizontalTiles; 1.560 + uint32_t horizontalTile = aTileIndex % horizontalTiles; 1.561 + 1.562 + return IntRect(horizontalTile * maxSize, 1.563 + verticalTile * maxSize, 1.564 + horizontalTile < (horizontalTiles - 1) ? maxSize : mSize.width % maxSize, 1.565 + verticalTile < (verticalTiles - 1) ? maxSize : mSize.height % maxSize); 1.566 +} 1.567 + 1.568 +nsIntRect 1.569 +DataTextureSourceD3D9::GetTileRect() 1.570 +{ 1.571 + return ThebesIntRect(GetTileRect(mCurrentTile)); 1.572 +} 1.573 + 1.574 +CairoTextureClientD3D9::CairoTextureClientD3D9(gfx::SurfaceFormat aFormat, TextureFlags aFlags) 1.575 + : TextureClient(aFlags) 1.576 + , mFormat(aFormat) 1.577 + , mIsLocked(false) 1.578 + , mNeedsClear(false) 1.579 + , mLockRect(false) 1.580 +{ 1.581 + MOZ_COUNT_CTOR(CairoTextureClientD3D9); 1.582 +} 1.583 + 1.584 +CairoTextureClientD3D9::~CairoTextureClientD3D9() 1.585 +{ 1.586 + MOZ_COUNT_DTOR(CairoTextureClientD3D9); 1.587 +} 1.588 + 1.589 +bool 1.590 +CairoTextureClientD3D9::Lock(OpenMode) 1.591 +{ 1.592 + MOZ_ASSERT(!mIsLocked); 1.593 + if (!IsValid() || !IsAllocated()) { 1.594 + return false; 1.595 + } 1.596 + 1.597 + if (!gfxWindowsPlatform::GetPlatform()->GetD3D9Device()) { 1.598 + // If the device has failed then we should not lock the surface, 1.599 + // even if we could. 1.600 + mD3D9Surface = nullptr; 1.601 + return false; 1.602 + } 1.603 + 1.604 + if (!mD3D9Surface) { 1.605 + HRESULT hr = mTexture->GetSurfaceLevel(0, getter_AddRefs(mD3D9Surface)); 1.606 + if (FAILED(hr)) { 1.607 + NS_WARNING("Failed to get texture surface level."); 1.608 + return false; 1.609 + } 1.610 + } 1.611 + 1.612 + mIsLocked = true; 1.613 + 1.614 + if (mNeedsClear) { 1.615 + mDrawTarget = GetAsDrawTarget(); 1.616 + mDrawTarget->ClearRect(Rect(0, 0, GetSize().width, GetSize().height)); 1.617 + mNeedsClear = false; 1.618 + } 1.619 + 1.620 + return true; 1.621 +} 1.622 + 1.623 +void 1.624 +CairoTextureClientD3D9::Unlock() 1.625 +{ 1.626 + MOZ_ASSERT(mIsLocked, "Unlocked called while the texture is not locked!"); 1.627 + if (mDrawTarget) { 1.628 + mDrawTarget->Flush(); 1.629 + mDrawTarget = nullptr; 1.630 + } 1.631 + 1.632 + if (mLockRect) { 1.633 + mD3D9Surface->UnlockRect(); 1.634 + mLockRect = false; 1.635 + } 1.636 + 1.637 + if (mSurface) { 1.638 + mSurface = nullptr; 1.639 + } 1.640 + mIsLocked = false; 1.641 +} 1.642 + 1.643 +bool 1.644 +CairoTextureClientD3D9::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) 1.645 +{ 1.646 + MOZ_ASSERT(IsValid()); 1.647 + if (!IsAllocated()) { 1.648 + return false; 1.649 + } 1.650 + 1.651 + mTexture->AddRef(); // Release in TextureHostD3D9::TextureHostD3D9 1.652 + aOutDescriptor = SurfaceDescriptorD3D9(reinterpret_cast<uintptr_t>(mTexture.get())); 1.653 + return true; 1.654 +} 1.655 + 1.656 +TemporaryRef<gfx::DrawTarget> 1.657 +CairoTextureClientD3D9::GetAsDrawTarget() 1.658 +{ 1.659 + MOZ_ASSERT(mIsLocked && mD3D9Surface); 1.660 + if (mDrawTarget) { 1.661 + return mDrawTarget; 1.662 + } 1.663 + 1.664 + if (ContentForFormat(mFormat) == gfxContentType::COLOR) { 1.665 + mSurface = new gfxWindowsSurface(mD3D9Surface); 1.666 + if (!mSurface || mSurface->CairoStatus()) { 1.667 + NS_WARNING("Could not create surface for d3d9 surface"); 1.668 + mSurface = nullptr; 1.669 + return nullptr; 1.670 + } 1.671 + } else { 1.672 + // gfxWindowsSurface don't support transparency so we can't use the d3d9 1.673 + // windows surface optimization. 1.674 + // Instead we have to use a gfxImageSurface and fallback for font drawing. 1.675 + D3DLOCKED_RECT rect; 1.676 + mD3D9Surface->LockRect(&rect, nullptr, 0); 1.677 + mSurface = new gfxImageSurface((uint8_t*)rect.pBits, ThebesIntSize(mSize), 1.678 + rect.Pitch, SurfaceFormatToImageFormat(mFormat)); 1.679 + mLockRect = true; 1.680 + } 1.681 + 1.682 + mDrawTarget = 1.683 + gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mSurface, mSize); 1.684 + 1.685 + return mDrawTarget; 1.686 +} 1.687 + 1.688 +bool 1.689 +CairoTextureClientD3D9::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags) 1.690 +{ 1.691 + MOZ_ASSERT(!IsAllocated()); 1.692 + mSize = aSize; 1.693 + _D3DFORMAT format = SurfaceFormatToD3D9Format(mFormat); 1.694 + 1.695 + DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(); 1.696 + if (!deviceManager || 1.697 + !(mTexture = deviceManager->CreateTexture(mSize, format, D3DPOOL_SYSTEMMEM, nullptr))) { 1.698 + NS_WARNING("Could not create d3d9 texture"); 1.699 + return false; 1.700 + } 1.701 + 1.702 + mNeedsClear = aFlags & ALLOC_CLEAR_BUFFER; 1.703 + 1.704 + MOZ_ASSERT(mTexture); 1.705 + return true; 1.706 +} 1.707 + 1.708 +TextureClientData* 1.709 +CairoTextureClientD3D9::DropTextureData() 1.710 +{ 1.711 + TextureClientData* data = new D3D9TextureClientData(mTexture); 1.712 + mTexture = nullptr; 1.713 + MarkInvalid(); 1.714 + return data; 1.715 +} 1.716 + 1.717 +DIBTextureClientD3D9::DIBTextureClientD3D9(gfx::SurfaceFormat aFormat, TextureFlags aFlags) 1.718 + : TextureClient(aFlags) 1.719 + , mFormat(aFormat) 1.720 + , mIsLocked(false) 1.721 +{ 1.722 + MOZ_COUNT_CTOR(DIBTextureClientD3D9); 1.723 +} 1.724 + 1.725 +DIBTextureClientD3D9::~DIBTextureClientD3D9() 1.726 +{ 1.727 + MOZ_COUNT_DTOR(DIBTextureClientD3D9); 1.728 +} 1.729 + 1.730 +bool 1.731 +DIBTextureClientD3D9::Lock(OpenMode) 1.732 +{ 1.733 + MOZ_ASSERT(!mIsLocked); 1.734 + if (!IsValid()) { 1.735 + return false; 1.736 + } 1.737 + mIsLocked = true; 1.738 + return true; 1.739 +} 1.740 + 1.741 +void 1.742 +DIBTextureClientD3D9::Unlock() 1.743 +{ 1.744 + MOZ_ASSERT(mIsLocked, "Unlocked called while the texture is not locked!"); 1.745 + if (mDrawTarget) { 1.746 + mDrawTarget->Flush(); 1.747 + mDrawTarget = nullptr; 1.748 + } 1.749 + 1.750 + mIsLocked = false; 1.751 +} 1.752 + 1.753 +bool 1.754 +DIBTextureClientD3D9::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) 1.755 +{ 1.756 + MOZ_ASSERT(IsValid()); 1.757 + if (!IsAllocated()) { 1.758 + return false; 1.759 + } 1.760 + MOZ_ASSERT(mSurface); 1.761 + // The host will release this ref when it receives the surface descriptor. 1.762 + // We AddRef in case we die before the host receives the pointer. 1.763 + aOutDescriptor = SurfaceDescriptorDIB(reinterpret_cast<uintptr_t>(mSurface.get())); 1.764 + mSurface->AddRef(); 1.765 + return true; 1.766 +} 1.767 + 1.768 +TemporaryRef<gfx::DrawTarget> 1.769 +DIBTextureClientD3D9::GetAsDrawTarget() 1.770 +{ 1.771 + MOZ_ASSERT(mIsLocked && IsAllocated()); 1.772 + 1.773 + if (!mDrawTarget) { 1.774 + mDrawTarget = 1.775 + gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mSurface, mSize); 1.776 + } 1.777 + 1.778 + return mDrawTarget; 1.779 +} 1.780 + 1.781 +bool 1.782 +DIBTextureClientD3D9::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags) 1.783 +{ 1.784 + MOZ_ASSERT(!IsAllocated()); 1.785 + mSize = aSize; 1.786 + 1.787 + mSurface = new gfxWindowsSurface(gfxIntSize(aSize.width, aSize.height), 1.788 + SurfaceFormatToImageFormat(mFormat)); 1.789 + if (!mSurface || mSurface->CairoStatus()) 1.790 + { 1.791 + NS_WARNING("Could not create surface"); 1.792 + mSurface = nullptr; 1.793 + return false; 1.794 + } 1.795 + 1.796 + return true; 1.797 +} 1.798 + 1.799 +TextureClientData* 1.800 +DIBTextureClientD3D9::DropTextureData() 1.801 +{ 1.802 + TextureClientData* data = new D3D9TextureClientData(mSurface); 1.803 + mSurface = nullptr; 1.804 + MarkInvalid(); 1.805 + return data; 1.806 +} 1.807 + 1.808 +SharedTextureClientD3D9::SharedTextureClientD3D9(gfx::SurfaceFormat aFormat, TextureFlags aFlags) 1.809 + : TextureClient(aFlags) 1.810 + , mFormat(aFormat) 1.811 + , mHandle(0) 1.812 + , mIsLocked(false) 1.813 +{ 1.814 + MOZ_COUNT_CTOR(SharedTextureClientD3D9); 1.815 +} 1.816 + 1.817 +SharedTextureClientD3D9::~SharedTextureClientD3D9() 1.818 +{ 1.819 + MOZ_COUNT_DTOR(SharedTextureClientD3D9); 1.820 +} 1.821 + 1.822 +TextureClientData* 1.823 +SharedTextureClientD3D9::DropTextureData() 1.824 +{ 1.825 + TextureClientData* data = new D3D9TextureClientData(mTexture); 1.826 + mTexture = nullptr; 1.827 + MarkInvalid(); 1.828 + return data; 1.829 +} 1.830 + 1.831 +bool 1.832 +SharedTextureClientD3D9::Lock(OpenMode) 1.833 +{ 1.834 + MOZ_ASSERT(!mIsLocked); 1.835 + if (!IsValid()) { 1.836 + return false; 1.837 + } 1.838 + mIsLocked = true; 1.839 + return true; 1.840 +} 1.841 + 1.842 +void 1.843 +SharedTextureClientD3D9::Unlock() 1.844 +{ 1.845 + MOZ_ASSERT(mIsLocked, "Unlock called while the texture is not locked!"); 1.846 +} 1.847 + 1.848 +bool 1.849 +SharedTextureClientD3D9::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) 1.850 +{ 1.851 + MOZ_ASSERT(IsValid()); 1.852 + if (!IsAllocated()) { 1.853 + return false; 1.854 + } 1.855 + 1.856 + aOutDescriptor = SurfaceDescriptorD3D10((WindowsHandle)(mHandle), mFormat, GetSize()); 1.857 + return true; 1.858 +} 1.859 + 1.860 +TextureHostD3D9::TextureHostD3D9(TextureFlags aFlags, 1.861 + const SurfaceDescriptorD3D9& aDescriptor) 1.862 + : TextureHost(aFlags) 1.863 + , mFormat(SurfaceFormat::UNKNOWN) 1.864 + , mIsLocked(false) 1.865 +{ 1.866 + mTexture = reinterpret_cast<IDirect3DTexture9*>(aDescriptor.texture()); 1.867 + mTexture->Release(); // see AddRef in CairoTextureClientD3D9::ToSurfaceDescriptor 1.868 + MOZ_ASSERT(mTexture); 1.869 + D3DSURFACE_DESC desc; 1.870 + HRESULT hr = mTexture->GetLevelDesc(0, &desc); 1.871 + if (!FAILED(hr)) { 1.872 + mFormat = D3D9FormatToSurfaceFormat(desc.Format); 1.873 + mSize.width = desc.Width; 1.874 + mSize.height = desc.Height; 1.875 + } 1.876 +} 1.877 + 1.878 +bool 1.879 +DataTextureSourceD3D9::UpdateFromTexture(IDirect3DTexture9* aTexture, 1.880 + const nsIntRegion* aRegion) 1.881 +{ 1.882 + MOZ_ASSERT(aTexture); 1.883 + 1.884 + D3DSURFACE_DESC desc; 1.885 + HRESULT hr = aTexture->GetLevelDesc(0, &desc); 1.886 + if (FAILED(hr)) { 1.887 + return false; 1.888 + } else { 1.889 + // If we changed the compositor, the size might have been reset to zero 1.890 + // Otherwise the texture size must not change. 1.891 + MOZ_ASSERT(mFormat == D3D9FormatToSurfaceFormat(desc.Format)); 1.892 + MOZ_ASSERT(!mSize.width || mSize.width == desc.Width); 1.893 + MOZ_ASSERT(!mSize.height || mSize.height == desc.Height); 1.894 + mSize = IntSize(desc.Width, desc.Height); 1.895 + } 1.896 + 1.897 + DeviceManagerD3D9* dm = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(); 1.898 + if (!mTexture) { 1.899 + mTexture = dm->CreateTexture(mSize, SurfaceFormatToD3D9Format(mFormat), 1.900 + D3DPOOL_DEFAULT, this); 1.901 + if (!mTexture) { 1.902 + NS_WARNING("Failed to create a texture"); 1.903 + return false; 1.904 + } 1.905 + } 1.906 + 1.907 + RefPtr<IDirect3DSurface9> srcSurface; 1.908 + RefPtr<IDirect3DSurface9> dstSurface; 1.909 + 1.910 + hr = aTexture->GetSurfaceLevel(0, byRef(srcSurface)); 1.911 + if (FAILED(hr)) { 1.912 + return false; 1.913 + } 1.914 + hr = mTexture->GetSurfaceLevel(0, byRef(dstSurface)); 1.915 + if (FAILED(hr)) { 1.916 + return false; 1.917 + } 1.918 + 1.919 + if (aRegion) { 1.920 + nsIntRegionRectIterator iter(*aRegion); 1.921 + const nsIntRect *iterRect; 1.922 + while ((iterRect = iter.Next())) { 1.923 + RECT rect; 1.924 + rect.left = iterRect->x; 1.925 + rect.top = iterRect->y; 1.926 + rect.right = iterRect->XMost(); 1.927 + rect.bottom = iterRect->YMost(); 1.928 + 1.929 + POINT point; 1.930 + point.x = iterRect->x; 1.931 + point.y = iterRect->y; 1.932 + hr = dm->device()->UpdateSurface(srcSurface, &rect, dstSurface, &point); 1.933 + if (FAILED(hr)) { 1.934 + NS_WARNING("Failed Update the surface"); 1.935 + return false; 1.936 + } 1.937 + } 1.938 + } else { 1.939 + hr = dm->device()->UpdateSurface(srcSurface, nullptr, dstSurface, nullptr); 1.940 + if (FAILED(hr)) { 1.941 + NS_WARNING("Failed Update the surface"); 1.942 + return false; 1.943 + } 1.944 + } 1.945 + mIsTiled = false; 1.946 + return true; 1.947 +} 1.948 + 1.949 +void 1.950 +TextureHostD3D9::Updated(const nsIntRegion* aRegion) 1.951 +{ 1.952 + if (!mTexture) { 1.953 + return; 1.954 + } 1.955 + 1.956 + if (!mTextureSource) { 1.957 + mTextureSource = new DataTextureSourceD3D9(mFormat, mSize, mCompositor, 1.958 + nullptr, mFlags); 1.959 + } 1.960 + 1.961 + mTextureSource->UpdateFromTexture(mTexture, aRegion); 1.962 +} 1.963 + 1.964 +IDirect3DDevice9* 1.965 +TextureHostD3D9::GetDevice() 1.966 +{ 1.967 + return mCompositor ? mCompositor->device() : nullptr; 1.968 +} 1.969 + 1.970 +void 1.971 +TextureHostD3D9::SetCompositor(Compositor* aCompositor) 1.972 +{ 1.973 + mCompositor = static_cast<CompositorD3D9*>(aCompositor); 1.974 + if (mTextureSource) { 1.975 + mTextureSource->SetCompositor(aCompositor); 1.976 + } 1.977 +} 1.978 + 1.979 +NewTextureSource* 1.980 +TextureHostD3D9::GetTextureSources() 1.981 +{ 1.982 + MOZ_ASSERT(mIsLocked); 1.983 + return mTextureSource; 1.984 +} 1.985 + 1.986 +bool 1.987 +TextureHostD3D9::Lock() 1.988 +{ 1.989 + MOZ_ASSERT(!mIsLocked); 1.990 + mIsLocked = true; 1.991 + return true; 1.992 +} 1.993 + 1.994 +void 1.995 +TextureHostD3D9::Unlock() 1.996 +{ 1.997 + MOZ_ASSERT(mIsLocked); 1.998 + mIsLocked = false; 1.999 +} 1.1000 + 1.1001 +void 1.1002 +TextureHostD3D9::DeallocateDeviceData() 1.1003 +{ 1.1004 + mTextureSource = nullptr; 1.1005 +} 1.1006 + 1.1007 +DIBTextureHostD3D9::DIBTextureHostD3D9(TextureFlags aFlags, 1.1008 + const SurfaceDescriptorDIB& aDescriptor) 1.1009 + : TextureHost(aFlags) 1.1010 + , mIsLocked(false) 1.1011 +{ 1.1012 + // We added an extra ref for transport, so we shouldn't AddRef now. 1.1013 + mSurface = 1.1014 + dont_AddRef(reinterpret_cast<gfxWindowsSurface*>(aDescriptor.surface())); 1.1015 + MOZ_ASSERT(mSurface); 1.1016 + 1.1017 + mSize = ToIntSize(mSurface->GetSize()); 1.1018 + mFormat = ImageFormatToSurfaceFormat( 1.1019 + gfxPlatform::GetPlatform()->OptimalFormatForContent(mSurface->GetContentType())); 1.1020 +} 1.1021 + 1.1022 +NewTextureSource* 1.1023 +DIBTextureHostD3D9::GetTextureSources() 1.1024 +{ 1.1025 + if (!mTextureSource) { 1.1026 + Updated(); 1.1027 + } 1.1028 + 1.1029 + return mTextureSource; 1.1030 +} 1.1031 + 1.1032 +void 1.1033 +DIBTextureHostD3D9::Updated(const nsIntRegion*) 1.1034 +{ 1.1035 + if (!mTextureSource) { 1.1036 + mTextureSource = new DataTextureSourceD3D9(mFormat, mCompositor, mFlags); 1.1037 + } 1.1038 + 1.1039 + if (!mTextureSource->Update(mSurface)) { 1.1040 + mTextureSource = nullptr; 1.1041 + } 1.1042 +} 1.1043 + 1.1044 +bool 1.1045 +DIBTextureHostD3D9::Lock() 1.1046 +{ 1.1047 + MOZ_ASSERT(!mIsLocked); 1.1048 + mIsLocked = true; 1.1049 + return true; 1.1050 +} 1.1051 + 1.1052 +void 1.1053 +DIBTextureHostD3D9::Unlock() 1.1054 +{ 1.1055 + MOZ_ASSERT(mIsLocked); 1.1056 + mIsLocked = false; 1.1057 +} 1.1058 + 1.1059 +void 1.1060 +DIBTextureHostD3D9::SetCompositor(Compositor* aCompositor) 1.1061 +{ 1.1062 + mCompositor = static_cast<CompositorD3D9*>(aCompositor); 1.1063 +} 1.1064 + 1.1065 +void 1.1066 +DIBTextureHostD3D9::DeallocateDeviceData() 1.1067 +{ 1.1068 + mTextureSource = nullptr; 1.1069 +} 1.1070 + 1.1071 +DXGITextureHostD3D9::DXGITextureHostD3D9(TextureFlags aFlags, 1.1072 + const SurfaceDescriptorD3D10& aDescriptor) 1.1073 + : TextureHost(aFlags) 1.1074 + , mHandle(aDescriptor.handle()) 1.1075 + , mFormat(aDescriptor.format()) 1.1076 + , mSize(aDescriptor.size()) 1.1077 + , mIsLocked(false) 1.1078 +{ 1.1079 + MOZ_ASSERT(mHandle); 1.1080 +} 1.1081 + 1.1082 +NewTextureSource* 1.1083 +DXGITextureHostD3D9::GetTextureSources() 1.1084 +{ 1.1085 + return mTextureSource; 1.1086 +} 1.1087 + 1.1088 +bool 1.1089 +DXGITextureHostD3D9::Lock() 1.1090 +{ 1.1091 + DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(); 1.1092 + if (!deviceManager) { 1.1093 + NS_WARNING("trying to lock a TextureHost without a D3D device"); 1.1094 + return false; 1.1095 + } 1.1096 + 1.1097 + if (!mTextureSource) { 1.1098 + nsRefPtr<IDirect3DTexture9> tex; 1.1099 + HRESULT hr = deviceManager->device()->CreateTexture(mSize.width, 1.1100 + mSize.height, 1.1101 + 1, 1.1102 + D3DUSAGE_RENDERTARGET, 1.1103 + SurfaceFormatToD3D9Format(mFormat), 1.1104 + D3DPOOL_DEFAULT, 1.1105 + getter_AddRefs(tex), 1.1106 + (HANDLE*)&mHandle); 1.1107 + if (FAILED(hr)) { 1.1108 + NS_WARNING("Failed to open shared texture"); 1.1109 + return false; 1.1110 + } 1.1111 + 1.1112 + mTextureSource = new DataTextureSourceD3D9(mFormat, mSize, mCompositor, tex); 1.1113 + } 1.1114 + 1.1115 + MOZ_ASSERT(!mIsLocked); 1.1116 + mIsLocked = true; 1.1117 + return true; 1.1118 +} 1.1119 + 1.1120 +void 1.1121 +DXGITextureHostD3D9::Unlock() 1.1122 +{ 1.1123 + MOZ_ASSERT(mIsLocked); 1.1124 + mIsLocked = false; 1.1125 +} 1.1126 + 1.1127 +void 1.1128 +DXGITextureHostD3D9::SetCompositor(Compositor* aCompositor) 1.1129 +{ 1.1130 + mCompositor = static_cast<CompositorD3D9*>(aCompositor); 1.1131 +} 1.1132 + 1.1133 +void 1.1134 +DXGITextureHostD3D9::DeallocateDeviceData() 1.1135 +{ 1.1136 + mTextureSource = nullptr; 1.1137 +} 1.1138 + 1.1139 +} 1.1140 +}