diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index a6f1e60982..b1dfc673fe 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -48,6 +48,7 @@ #include "TimeUnits.h" #include "VideoSegment.h" #include "VideoUtils.h" +#include "gfxPrefs.h" namespace mozilla { @@ -2442,7 +2443,7 @@ MediaDecoderStateMachine::CheckFrameValidity(VideoData* aData) MOZ_ASSERT(OnTaskQueue()); // Update corrupt-frames statistics - if (aData->mImage && !aData->mImage->IsValid()) { + if (aData->mImage && !aData->mImage->IsValid() && !gfxPrefs::HardwareVideoDecodingForceEnabled()) { FrameStatistics& frameStats = *mFrameStats; frameStats.NotifyCorruptFrame(); // If more than 10% of the last 30 frames have been corrupted, then try disabling diff --git a/dom/media/platforms/wmf/DXVA2Manager.cpp b/dom/media/platforms/wmf/DXVA2Manager.cpp index d83c9005dc..2244d6a8f6 100644 --- a/dom/media/platforms/wmf/DXVA2Manager.cpp +++ b/dom/media/platforms/wmf/DXVA2Manager.cpp @@ -37,6 +37,40 @@ const GUID MF_XVP_PLAYBACK_MODE = DEFINE_GUID(MF_LOW_LATENCY, 0x9c27891a, 0xed7a, 0x40e1, 0x88, 0xe8, 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee); +// R600, R700, Evergreen and Cayman AMD cards. These support DXVA via UVD3 or earlier, and don't +// handle 1080p60 well. +static const DWORD sAMDPreUVD4[] = { + 0x9400, 0x9401, 0x9402, 0x9403, 0x9405, 0x940a, 0x940b, 0x940f, 0x94c0, 0x94c1, 0x94c3, 0x94c4, 0x94c5, + 0x94c6, 0x94c7, 0x94c8, 0x94c9, 0x94cb, 0x94cc, 0x94cd, 0x9580, 0x9581, 0x9583, 0x9586, 0x9587, 0x9588, + 0x9589, 0x958a, 0x958b, 0x958c, 0x958d, 0x958e, 0x958f, 0x9500, 0x9501, 0x9504, 0x9505, 0x9506, 0x9507, + 0x9508, 0x9509, 0x950f, 0x9511, 0x9515, 0x9517, 0x9519, 0x95c0, 0x95c2, 0x95c4, 0x95c5, 0x95c6, 0x95c7, + 0x95c9, 0x95cc, 0x95cd, 0x95ce, 0x95cf, 0x9590, 0x9591, 0x9593, 0x9595, 0x9596, 0x9597, 0x9598, 0x9599, + 0x959b, 0x9610, 0x9611, 0x9612, 0x9613, 0x9614, 0x9615, 0x9616, 0x9710, 0x9711, 0x9712, 0x9713, 0x9714, + 0x9715, 0x9440, 0x9441, 0x9442, 0x9443, 0x9444, 0x9446, 0x944a, 0x944b, 0x944c, 0x944e, 0x9450, 0x9452, + 0x9456, 0x945a, 0x945b, 0x945e, 0x9460, 0x9462, 0x946a, 0x946b, 0x947a, 0x947b, 0x9480, 0x9487, 0x9488, + 0x9489, 0x948a, 0x948f, 0x9490, 0x9491, 0x9495, 0x9498, 0x949c, 0x949e, 0x949f, 0x9540, 0x9541, 0x9542, + 0x954e, 0x954f, 0x9552, 0x9553, 0x9555, 0x9557, 0x955f, 0x94a0, 0x94a1, 0x94a3, 0x94b1, 0x94b3, 0x94b4, + 0x94b5, 0x94b9, 0x68e0, 0x68e1, 0x68e4, 0x68e5, 0x68e8, 0x68e9, 0x68f1, 0x68f2, 0x68f8, 0x68f9, 0x68fa, + 0x68fe, 0x68c0, 0x68c1, 0x68c7, 0x68c8, 0x68c9, 0x68d8, 0x68d9, 0x68da, 0x68de, 0x68a0, 0x68a1, 0x68a8, + 0x68a9, 0x68b0, 0x68b8, 0x68b9, 0x68ba, 0x68be, 0x68bf, 0x6880, 0x6888, 0x6889, 0x688a, 0x688c, 0x688d, + 0x6898, 0x6899, 0x689b, 0x689e, 0x689c, 0x689d, 0x9802, 0x9803, 0x9804, 0x9805, 0x9806, 0x9807, 0x9808, + 0x9809, 0x980a, 0x9640, 0x9641, 0x9647, 0x9648, 0x964a, 0x964b, 0x964c, 0x964e, 0x964f, 0x9642, 0x9643, + 0x9644, 0x9645, 0x9649, 0x6720, 0x6721, 0x6722, 0x6723, 0x6724, 0x6725, 0x6726, 0x6727, 0x6728, 0x6729, + 0x6738, 0x6739, 0x673e, 0x6740, 0x6741, 0x6742, 0x6743, 0x6744, 0x6745, 0x6746, 0x6747, 0x6748, 0x6749, + 0x674a, 0x6750, 0x6751, 0x6758, 0x6759, 0x675b, 0x675d, 0x675f, 0x6840, 0x6841, 0x6842, 0x6843, 0x6849, + 0x6850, 0x6858, 0x6859, 0x6760, 0x6761, 0x6762, 0x6763, 0x6764, 0x6765, 0x6766, 0x6767, 0x6768, 0x6770, + 0x6771, 0x6772, 0x6778, 0x6779, 0x677b, 0x6700, 0x6701, 0x6702, 0x6703, 0x6704, 0x6705, 0x6706, 0x6707, + 0x6708, 0x6709, 0x6718, 0x6719, 0x671c, 0x671d, 0x671f, 0x9900, 0x9901, 0x9903, 0x9904, 0x9905, 0x9906, + 0x9907, 0x9908, 0x9909, 0x990a, 0x990b, 0x990c, 0x990d, 0x990e, 0x990f, 0x9910, 0x9913, 0x9917, 0x9918, + 0x9919, 0x9990, 0x9991, 0x9992, 0x9993, 0x9994, 0x9995, 0x9996, 0x9997, 0x9998, 0x9999, 0x999a, 0x999b, + 0x999c, 0x999d, 0x99a0, 0x99a2, 0x99a4 +}; + +// The size we use for our synchronization surface. +// 16x16 is the size recommended by Microsoft (in the D3D9ExDXGISharedSurf sample) that works +// best to avoid driver bugs. +static const uint32_t kSyncSurfaceSize = 16; + namespace mozilla { using layers::Image; @@ -63,7 +97,7 @@ public: ImageContainer* aContainer, Image** aOutImage) override; - virtual bool SupportsConfig(IMFMediaType* aType) override; + bool SupportsConfig(IMFMediaType* aType, float aFramerate) override; private: RefPtr mD3D9; @@ -71,8 +105,11 @@ private: RefPtr mDeviceManager; RefPtr mTextureClientAllocator; RefPtr mDecoderService; + RefPtr mSyncSurface; + GUID mDecoderGUID; UINT32 mResetToken; bool mFirstFrame; + bool mIsAMDPreUVD4; }; void GetDXVA2ExtendedFormatFromMFMediaType(IMFMediaType *pType, @@ -140,26 +177,39 @@ static const GUID DXVA2_ModeH264_E = { 0x1b81be68, 0xa0c7, 0x11d3, { 0xb9, 0x84, 0x00, 0xc0, 0x4f, 0x2e, 0x73, 0xc5 } }; +static const GUID DXVA2_Intel_ModeH264_E = { + 0x604F8E68, 0x4951, 0x4c54, { 0x88, 0xFE, 0xAB, 0xD2, 0x5C, 0x15, 0xB3, 0xD6 } +}; + // This tests if a DXVA video decoder can be created for the given media type/resolution. // It uses the same decoder device (DXVA2_ModeH264_E - DXVA2_ModeH264_VLD_NoFGT) as the H264 // decoder MFT provided by windows (CLSID_CMSH264DecoderMFT) uses, so we can use it to determine // if the MFT will use software fallback or not. bool -D3D9DXVA2Manager::SupportsConfig(IMFMediaType* aType) +D3D9DXVA2Manager::SupportsConfig(IMFMediaType* aType, float aFramerate) { DXVA2_VideoDesc desc; HRESULT hr = ConvertMFTypeToDXVAType(aType, &desc); NS_ENSURE_TRUE(SUCCEEDED(hr), false); + // AMD cards with UVD3 or earlier perform poorly trying to decode 1080p60 in hardware, + // so use software instead. Pick 45 as an arbitrary upper bound for the framerate we can + // handle. + if (mIsAMDPreUVD4 && + (desc.SampleWidth >= 1920 || desc.SampleHeight >= 1088) && + aFramerate > 45) { + return false; + } + UINT configCount; DXVA2_ConfigPictureDecode* configs = nullptr; - hr = mDecoderService->GetDecoderConfigurations(DXVA2_ModeH264_E, &desc, nullptr, &configCount, &configs); + hr = mDecoderService->GetDecoderConfigurations(mDecoderGUID, &desc, nullptr, &configCount, &configs); NS_ENSURE_TRUE(SUCCEEDED(hr), false); RefPtr surface; hr = mDecoderService->CreateSurface(desc.SampleWidth, desc.SampleHeight, 0, (D3DFORMAT)MAKEFOURCC('N', 'V', '1', '2'), - D3DPOOL_DEFAULT, 0, DXVA2_VideoDecoderRenderTarget, - surface.StartAssignment(), NULL); + D3DPOOL_DEFAULT, 0, DXVA2_VideoDecoderRenderTarget, + surface.StartAssignment(), NULL); if (!SUCCEEDED(hr)) { CoTaskMemFree(configs); return false; @@ -168,7 +218,7 @@ D3D9DXVA2Manager::SupportsConfig(IMFMediaType* aType) for (UINT i = 0; i < configCount; i++) { RefPtr decoder; IDirect3DSurface9* surfaces = surface; - hr = mDecoderService->CreateVideoDecoder(DXVA2_ModeH264_E, &desc, &configs[i], &surfaces, 1, decoder.StartAssignment()); + hr = mDecoderService->CreateVideoDecoder(mDecoderGUID, &desc, &configs[i], &surfaces, 1, decoder.StartAssignment()); if (SUCCEEDED(hr) && decoder) { CoTaskMemFree(configs); return true; @@ -181,6 +231,7 @@ D3D9DXVA2Manager::SupportsConfig(IMFMediaType* aType) D3D9DXVA2Manager::D3D9DXVA2Manager() : mResetToken(0) , mFirstFrame(true) + , mIsAMDPreUVD4(false) { MOZ_COUNT_CTOR(D3D9DXVA2Manager); MOZ_ASSERT(NS_IsMainThread()); @@ -235,21 +286,23 @@ D3D9DXVA2Manager::Init(nsACString& aFailureReason) return hr; } - // Create D3D9DeviceEx. + // Create D3D9DeviceEx. We pass null HWNDs here even though the documentation + // suggests that one of them should not be. At this point in time Chromium + // does the same thing for video acceleration. D3DPRESENT_PARAMETERS params = {0}; params.BackBufferWidth = 1; params.BackBufferHeight = 1; params.BackBufferFormat = D3DFMT_UNKNOWN; params.BackBufferCount = 1; params.SwapEffect = D3DSWAPEFFECT_DISCARD; - params.hDeviceWindow = ::GetShellWindow(); + params.hDeviceWindow = nullptr; params.Windowed = TRUE; params.Flags = D3DPRESENTFLAG_VIDEO; RefPtr device; hr = d3d9Ex->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, - ::GetShellWindow(), + nullptr, D3DCREATE_FPU_PRESERVE | D3DCREATE_MULTITHREADED | D3DCREATE_MIXED_VERTEXPROCESSING, @@ -292,20 +345,31 @@ D3D9DXVA2Manager::Init(nsACString& aFailureReason) HANDLE deviceHandle; RefPtr decoderService; hr = deviceManager->OpenDeviceHandle(&deviceHandle); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + if (!SUCCEEDED(hr)) { + aFailureReason = nsPrintfCString("IDirect3DDeviceManager9::OpenDeviceHandle failed with error %X", hr); + return hr; + } hr = deviceManager->GetVideoService(deviceHandle, IID_PPV_ARGS(decoderService.StartAssignment())); deviceManager->CloseDeviceHandle(deviceHandle); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + if (!SUCCEEDED(hr)) { + aFailureReason = nsPrintfCString("IDirectXVideoDecoderServer::GetVideoService failed with error %X", hr); + return hr; + } UINT deviceCount; GUID* decoderDevices = nullptr; hr = decoderService->GetDecoderDeviceGuids(&deviceCount, &decoderDevices); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + if (!SUCCEEDED(hr)) { + aFailureReason = nsPrintfCString("IDirectXVideoDecoderServer::GetDecoderDeviceGuids failed with error %X", hr); + return hr; + } bool found = false; for (UINT i = 0; i < deviceCount; i++) { - if (decoderDevices[i] == DXVA2_ModeH264_E) { + if (decoderDevices[i] == DXVA2_ModeH264_E || + decoderDevices[i] == DXVA2_Intel_ModeH264_E) { + mDecoderGUID = decoderDevices[i]; found = true; break; } @@ -313,15 +377,40 @@ D3D9DXVA2Manager::Init(nsACString& aFailureReason) CoTaskMemFree(decoderDevices); if (!found) { + aFailureReason.AssignLiteral("Failed to find an appropriate decoder GUID"); return E_FAIL; } + D3DADAPTER_IDENTIFIER9 adapter; + hr = d3d9Ex->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &adapter); + if (!SUCCEEDED(hr)) { + aFailureReason = nsPrintfCString("IDirect3D9Ex::GetAdapterIdentifier failed with error %X", hr); + return hr; + } + + if (adapter.VendorId == 0x1022 && + !Preferences::GetBool("media.wmf.skip-blacklist", false)) { + for (size_t i = 0; i < MOZ_ARRAY_LENGTH(sAMDPreUVD4); i++) { + if (adapter.DeviceId == sAMDPreUVD4[i]) { + mIsAMDPreUVD4 = true; + break; + } + } + } + + RefPtr syncSurf; + hr = device->CreateRenderTarget(kSyncSurfaceSize, kSyncSurfaceSize, + D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, + 0, TRUE, getter_AddRefs(syncSurf), NULL); + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + mDecoderService = decoderService; mResetToken = resetToken; mD3D9 = d3d9Ex; mDevice = device; mDeviceManager = deviceManager; + mSyncSurface = syncSurf; mTextureClientAllocator = new D3D9RecycleAllocator(layers::ImageBridgeChild::GetSingleton(), mDevice); @@ -347,11 +436,24 @@ D3D9DXVA2Manager::CopyToImage(IMFSample* aSample, getter_AddRefs(surface)); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - RefPtr image = new D3D9SurfaceImage(mFirstFrame); + RefPtr image = new D3D9SurfaceImage(); hr = image->AllocateAndCopy(mTextureClientAllocator, surface, aRegion); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - mFirstFrame = false; + RefPtr sourceSurf = image->GetD3D9Surface(); + + // Copy a small rect into our sync surface, and then map it + // to block until decoding/color conversion completes. + RECT copyRect = { 0, 0, kSyncSurfaceSize, kSyncSurfaceSize }; + hr = mDevice->StretchRect(sourceSurf, ©Rect, mSyncSurface, ©Rect, D3DTEXF_NONE); + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + + D3DLOCKED_RECT lockedRect; + hr = mSyncSurface->LockRect(&lockedRect, NULL, D3DLOCK_READONLY); + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + + hr = mSyncSurface->UnlockRect(); + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); image.forget(aOutImage); return S_OK; @@ -408,6 +510,8 @@ public: bool IsD3D11() override { return true; } + bool SupportsConfig(IMFMediaType* aType, float aFramerate) override; + private: HRESULT CreateFormatConverter(); @@ -419,15 +523,65 @@ private: RefPtr mDXGIDeviceManager; RefPtr mTransform; RefPtr mTextureClientAllocator; + RefPtr mSyncSurface; + GUID mDecoderGUID; uint32_t mWidth; uint32_t mHeight; UINT mDeviceManagerToken; + bool mIsAMDPreUVD4; }; +bool +D3D11DXVA2Manager::SupportsConfig(IMFMediaType* aType, float aFramerate) +{ + RefPtr videoDevice; + HRESULT hr = mDevice->QueryInterface(static_cast(getter_AddRefs(videoDevice))); + NS_ENSURE_TRUE(SUCCEEDED(hr), false); + + D3D11_VIDEO_DECODER_DESC desc; + desc.Guid = mDecoderGUID; + + UINT32 width = 0; + UINT32 height = 0; + hr = MFGetAttributeSize(aType, MF_MT_FRAME_SIZE, &width, &height); + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + desc.SampleWidth = width; + desc.SampleHeight = height; + + desc.OutputFormat = DXGI_FORMAT_NV12; + + // AMD cards with UVD3 or earlier perform poorly trying to decode 1080p60 in hardware, + // so use software instead. Pick 45 as an arbitrary upper bound for the framerate we can + // handle. + if (mIsAMDPreUVD4 && + (desc.SampleWidth >= 1920 || desc.SampleHeight >= 1088) && + aFramerate > 45) { + return false; + } + + UINT configCount = 0; + hr = videoDevice->GetVideoDecoderConfigCount(&desc, &configCount); + NS_ENSURE_TRUE(SUCCEEDED(hr), false); + + for (UINT i = 0; i < configCount; i++) { + D3D11_VIDEO_DECODER_CONFIG config; + hr = videoDevice->GetVideoDecoderConfig(&desc, i, &config); + if (SUCCEEDED(hr)) { + RefPtr decoder; + hr = videoDevice->CreateVideoDecoder(&desc, &config, decoder.StartAssignment()); + if (SUCCEEDED(hr) && decoder) { + return true; + } + } + } + return false; +} + D3D11DXVA2Manager::D3D11DXVA2Manager() : mWidth(0) , mHeight(0) , mDeviceManagerToken(0) + , mIsAMDPreUVD4(false) { } @@ -484,6 +638,87 @@ D3D11DXVA2Manager::Init(nsACString& aFailureReason) return hr; } + RefPtr videoDevice; + hr = mDevice->QueryInterface(static_cast(getter_AddRefs(videoDevice))); + if (!SUCCEEDED(hr)) { + aFailureReason = nsPrintfCString("QI to ID3D11VideoDevice failed with code %X", hr); + return hr; + } + + bool found = false; + UINT profileCount = videoDevice->GetVideoDecoderProfileCount(); + for (UINT i = 0; i < profileCount; i++) { + GUID id; + hr = videoDevice->GetVideoDecoderProfile(i, &id); + if (SUCCEEDED(hr) && (id == DXVA2_ModeH264_E || id == DXVA2_Intel_ModeH264_E)) { + mDecoderGUID = id; + found = true; + break; + } + } + if (!found) { + aFailureReason.AssignLiteral("Failed to find an appropriate decoder GUID"); + return E_FAIL; + } + + BOOL nv12Support = false; + hr = videoDevice->CheckVideoDecoderFormat(&mDecoderGUID, DXGI_FORMAT_NV12, &nv12Support); + if (!SUCCEEDED(hr)) { + aFailureReason = nsPrintfCString("CheckVideoDecoderFormat failed with code %X", hr); + return hr; + } + if (!nv12Support) { + aFailureReason.AssignLiteral("Decoder doesn't support NV12 surfaces"); + return E_FAIL; + } + + RefPtr dxgiDevice; + hr = mDevice->QueryInterface(static_cast(getter_AddRefs(dxgiDevice))); + if (!SUCCEEDED(hr)) { + aFailureReason = nsPrintfCString("QI to IDXGIDevice failed with code %X", hr); + return hr; + } + + RefPtr adapter; + hr = dxgiDevice->GetAdapter(adapter.StartAssignment()); + if (!SUCCEEDED(hr)) { + aFailureReason = nsPrintfCString("IDXGIDevice::GetAdapter failed with code %X", hr); + return hr; + } + + DXGI_ADAPTER_DESC adapterDesc; + hr = adapter->GetDesc(&adapterDesc); + if (!SUCCEEDED(hr)) { + aFailureReason = nsPrintfCString("IDXGIAdapter::GetDesc failed with code %X", hr); + return hr; + } + + if (adapterDesc.VendorId == 0x1022 && + !Preferences::GetBool("media.wmf.skip-blacklist", false)) { + for (size_t i = 0; i < MOZ_ARRAY_LENGTH(sAMDPreUVD4); i++) { + if (adapterDesc.DeviceId == sAMDPreUVD4[i]) { + mIsAMDPreUVD4 = true; + break; + } + } + } + + D3D11_TEXTURE2D_DESC desc; + desc.Width = kSyncSurfaceSize; + desc.Height = kSyncSurfaceSize; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc.MiscFlags = 0; + + hr = mDevice->CreateTexture2D(&desc, NULL, getter_AddRefs(mSyncSurface)); + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + mTextureClientAllocator = new D3D11RecycleAllocator(layers::ImageBridgeChild::GetSingleton(), mDevice); mTextureClientAllocator->SetMaxPoolSize(5); @@ -535,18 +770,22 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample, hr = CreateOutputSample(sample, texture); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - RefPtr keyedMutex; - hr = texture->QueryInterface(static_cast(getter_AddRefs(keyedMutex))); - NS_ENSURE_TRUE(SUCCEEDED(hr) && keyedMutex, hr); - - hr = keyedMutex->AcquireSync(0, INFINITE); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - hr = mTransform->Output(&sample); - keyedMutex->ReleaseSync(0); + RefPtr ctx; + mDevice->GetImmediateContext(getter_AddRefs(ctx)); + + // Copy a small rect into our sync surface, and then map it + // to block until decoding/color conversion completes. + D3D11_BOX rect = { 0, 0, 0, kSyncSurfaceSize, kSyncSurfaceSize, 1 }; + ctx->CopySubresourceRegion(mSyncSurface, 0, 0, 0, 0, texture, 0, &rect); + + D3D11_MAPPED_SUBRESOURCE mapped; + hr = ctx->Map(mSyncSurface, 0, D3D11_MAP_READ, 0, &mapped); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + ctx->Unmap(mSyncSurface, 0); + image.forget(aOutImage); return S_OK; diff --git a/dom/media/platforms/wmf/DXVA2Manager.h b/dom/media/platforms/wmf/DXVA2Manager.h index 2b2d8ade85..c44d1859fd 100644 --- a/dom/media/platforms/wmf/DXVA2Manager.h +++ b/dom/media/platforms/wmf/DXVA2Manager.h @@ -44,7 +44,7 @@ public: virtual ~DXVA2Manager(); - virtual bool SupportsConfig(IMFMediaType* aType) { return true; } + virtual bool SupportsConfig(IMFMediaType* aType, float aFramerate) = 0; protected: Mutex mLock; diff --git a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp index e3642954cc..d5db7f8012 100644 --- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp +++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp @@ -305,6 +305,8 @@ WMFVideoMFTManager::Input(MediaRawData* aSample) &mLastInput); NS_ENSURE_TRUE(SUCCEEDED(hr) && mLastInput != nullptr, hr); + mLastDuration = aSample->mDuration; + // Forward sample data to the decoder. return mDecoder->Input(mLastInput); } @@ -328,7 +330,11 @@ WMFVideoMFTManager::MaybeToggleDXVA(IMFMediaType* aType) return false; } - if (mDXVA2Manager->SupportsConfig(aType)) { + // Assume the current samples duration is representative for the + // entire video. + float framerate = 1000000.0 / mLastDuration; + + if (mDXVA2Manager->SupportsConfig(aType, framerate)) { if (!mUseHwAccel) { // DXVA disabled, but supported for this resolution ULONG_PTR manager = ULONG_PTR(mDXVA2Manager->GetDXVADeviceManager()); diff --git a/dom/media/platforms/wmf/WMFVideoMFTManager.h b/dom/media/platforms/wmf/WMFVideoMFTManager.h index 9a44a712f9..aad6a28b38 100644 --- a/dom/media/platforms/wmf/WMFVideoMFTManager.h +++ b/dom/media/platforms/wmf/WMFVideoMFTManager.h @@ -77,6 +77,7 @@ private: nsAutoPtr mDXVA2Manager; RefPtr mLastInput; + float mLastDuration; const bool mDXVAEnabled; const layers::LayersBackend mLayersBackend; diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 6bfeebd4f6..fb837db22a 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -1256,7 +1256,7 @@ public: CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT); static already_AddRefed - CreateDrawTargetForData(BackendType aBackend, unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat); + CreateDrawTargetForData(BackendType aBackend, unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat, bool aUninitialized = false); static already_AddRefed CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSize); diff --git a/gfx/2d/DrawTargetSkia.cpp b/gfx/2d/DrawTargetSkia.cpp index 1ba1360242..68fb7ce18c 100644 --- a/gfx/2d/DrawTargetSkia.cpp +++ b/gfx/2d/DrawTargetSkia.cpp @@ -896,10 +896,10 @@ VerifyRGBXFormat(uint8_t* aData, const IntSize &aSize, const int32_t aStride, Su #endif void -DrawTargetSkia::Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) +DrawTargetSkia::Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat, bool aUninitialized) { MOZ_ASSERT((aFormat != SurfaceFormat::B8G8R8X8) || - VerifyRGBXFormat(aData, aSize, aStride, aFormat)); + aUninitialized || VerifyRGBXFormat(aData, aSize, aStride, aFormat)); SkBitmap bitmap; bitmap.setInfo(MakeSkiaImageInfo(aSize, aFormat), aStride); diff --git a/gfx/2d/DrawTargetSkia.h b/gfx/2d/DrawTargetSkia.h index 9a30786680..d5bc47f297 100644 --- a/gfx/2d/DrawTargetSkia.h +++ b/gfx/2d/DrawTargetSkia.h @@ -111,7 +111,7 @@ public: virtual void *GetNativeSurface(NativeSurfaceType aType) override; bool Init(const IntSize &aSize, SurfaceFormat aFormat); - void Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat); + void Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat, bool aUninitialized = false); #ifdef USE_SKIA_GPU bool InitWithGrContext(GrContext* aGrContext, diff --git a/gfx/2d/Factory.cpp b/gfx/2d/Factory.cpp index 2da98fc7f6..d4c878cb8f 100644 --- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -395,7 +395,8 @@ Factory::CreateDrawTargetForData(BackendType aBackend, unsigned char *aData, const IntSize &aSize, int32_t aStride, - SurfaceFormat aFormat) + SurfaceFormat aFormat, + bool aUninitialized) { MOZ_ASSERT(aData); if (!AllowedSurfaceSize(aSize)) { @@ -411,7 +412,7 @@ Factory::CreateDrawTargetForData(BackendType aBackend, { RefPtr newTarget; newTarget = new DrawTargetSkia(); - newTarget->Init(aData, aSize, aStride, aFormat); + newTarget->Init(aData, aSize, aStride, aFormat, aUninitialized); retVal = newTarget; break; } diff --git a/gfx/gl/SharedSurface.cpp b/gfx/gl/SharedSurface.cpp index 72d1a320b2..1bcab887f2 100644 --- a/gfx/gl/SharedSurface.cpp +++ b/gfx/gl/SharedSurface.cpp @@ -288,7 +288,7 @@ ChooseBufferBits(const SurfaceCaps& caps, SurfaceFactory::SurfaceFactory(SharedSurfaceType type, GLContext* gl, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags) : mType(type) , mGL(gl) @@ -304,7 +304,9 @@ SurfaceFactory::SurfaceFactory(SharedSurfaceType type, GLContext* gl, SurfaceFactory::~SurfaceFactory() { while (!mRecycleTotalPool.empty()) { - StopRecycling(*mRecycleTotalPool.begin()); + RefPtr tex = *mRecycleTotalPool.begin(); + StopRecycling(tex); + tex->CancelWaitForCompositorRecycle(); } MOZ_RELEASE_ASSERT(mRecycleTotalPool.empty()); diff --git a/gfx/gl/SharedSurface.h b/gfx/gl/SharedSurface.h index 32eb015004..b7ae47bbdd 100644 --- a/gfx/gl/SharedSurface.h +++ b/gfx/gl/SharedSurface.h @@ -39,7 +39,7 @@ class DrawTarget; } // namespace gfx namespace layers { -class ISurfaceAllocator; +class ClientIPCAllocator; class SharedSurfaceTextureClient; enum class TextureFlags : uint32_t; class SurfaceDescriptor; @@ -68,7 +68,9 @@ protected: bool mIsLocked; bool mIsProducerAcquired; bool mIsConsumerAcquired; - DebugOnly mOwningThread; +#ifdef DEBUG + nsIThread* const mOwningThread; +#endif SharedSurface(SharedSurfaceType type, AttachmentType attachType, @@ -267,7 +269,7 @@ public: const SharedSurfaceType mType; GLContext* const mGL; const SurfaceCaps mCaps; - const RefPtr mAllocator; + const RefPtr mAllocator; const layers::TextureFlags mFlags; const GLFormats mFormats; Mutex mMutex; @@ -278,7 +280,7 @@ protected: RefSet mRecycleTotalPool; SurfaceFactory(SharedSurfaceType type, GLContext* gl, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags); public: diff --git a/gfx/gl/SharedSurfaceANGLE.cpp b/gfx/gl/SharedSurfaceANGLE.cpp index 70cd2bffe2..de083a2ae8 100644 --- a/gfx/gl/SharedSurfaceANGLE.cpp +++ b/gfx/gl/SharedSurfaceANGLE.cpp @@ -321,7 +321,7 @@ SharedSurface_ANGLEShareHandle::ReadbackBySharedHandle(gfx::DataSourceSurface* o /*static*/ UniquePtr SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags) { GLLibraryEGL* egl = &sEGLLibrary; @@ -341,7 +341,7 @@ SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl, const SurfaceCaps& caps, SurfaceFactory_ANGLEShareHandle::SurfaceFactory_ANGLEShareHandle(GLContext* gl, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags, GLLibraryEGL* egl, EGLConfig config) diff --git a/gfx/gl/SharedSurfaceANGLE.h b/gfx/gl/SharedSurfaceANGLE.h index 349edcc051..85c7d9a06e 100644 --- a/gfx/gl/SharedSurfaceANGLE.h +++ b/gfx/gl/SharedSurfaceANGLE.h @@ -89,12 +89,12 @@ protected: public: static UniquePtr Create(GLContext* gl, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags); protected: SurfaceFactory_ANGLEShareHandle(GLContext* gl, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags, GLLibraryEGL* egl, EGLConfig config); diff --git a/gfx/gl/SharedSurfaceD3D11Interop.cpp b/gfx/gl/SharedSurfaceD3D11Interop.cpp index 9ba40e47e1..4d2d410996 100644 --- a/gfx/gl/SharedSurfaceD3D11Interop.cpp +++ b/gfx/gl/SharedSurfaceD3D11Interop.cpp @@ -383,7 +383,7 @@ SharedSurface_D3D11Interop::ToSurfaceDescriptor(layers::SurfaceDescriptor* const /*static*/ UniquePtr SurfaceFactory_D3D11Interop::Create(GLContext* gl, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags) { WGLLibrary* wgl = &sWGLLib; @@ -404,7 +404,7 @@ SurfaceFactory_D3D11Interop::Create(GLContext* gl, const SurfaceCaps& caps, SurfaceFactory_D3D11Interop::SurfaceFactory_D3D11Interop(GLContext* gl, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags, const RefPtr& dxgl) : SurfaceFactory(SharedSurfaceType::DXGLInterop2, gl, caps, allocator, flags) diff --git a/gfx/gl/SharedSurfaceD3D11Interop.h b/gfx/gl/SharedSurfaceD3D11Interop.h index 60cd05b90e..afff243c46 100644 --- a/gfx/gl/SharedSurfaceD3D11Interop.h +++ b/gfx/gl/SharedSurfaceD3D11Interop.h @@ -89,12 +89,12 @@ public: static UniquePtr Create(GLContext* gl, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags); protected: SurfaceFactory_D3D11Interop(GLContext* gl, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags, const RefPtr& dxgl); diff --git a/gfx/gl/SharedSurfaceEGL.cpp b/gfx/gl/SharedSurfaceEGL.cpp index 45ecf6a5c3..aebf18bf09 100644 --- a/gfx/gl/SharedSurfaceEGL.cpp +++ b/gfx/gl/SharedSurfaceEGL.cpp @@ -188,7 +188,7 @@ SharedSurface_EGLImage::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surfa /*static*/ UniquePtr SurfaceFactory_EGLImage::Create(GLContext* prodGL, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags) { EGLContext context = GLContextEGL::Cast(prodGL)->mContext; diff --git a/gfx/gl/SharedSurfaceEGL.h b/gfx/gl/SharedSurfaceEGL.h index 53f4bb084a..8fbe23ad54 100644 --- a/gfx/gl/SharedSurfaceEGL.h +++ b/gfx/gl/SharedSurfaceEGL.h @@ -93,14 +93,14 @@ public: // Fallible: static UniquePtr Create(GLContext* prodGL, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags); protected: const EGLContext mContext; SurfaceFactory_EGLImage(GLContext* prodGL, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags, EGLContext context) : SurfaceFactory(SharedSurfaceType::EGLImageShare, prodGL, caps, allocator, flags) diff --git a/gfx/gl/SharedSurfaceGL.h b/gfx/gl/SharedSurfaceGL.h index 775e166969..55fd8f84d9 100644 --- a/gfx/gl/SharedSurfaceGL.h +++ b/gfx/gl/SharedSurfaceGL.h @@ -149,7 +149,7 @@ class SurfaceFactory_GLTexture public: SurfaceFactory_GLTexture(GLContext* prodGL, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags) : SurfaceFactory(SharedSurfaceType::SharedGLTexture, prodGL, caps, allocator, flags) { diff --git a/gfx/gl/SharedSurfaceGLX.cpp b/gfx/gl/SharedSurfaceGLX.cpp index 64f9eb0559..82ad71bcb2 100644 --- a/gfx/gl/SharedSurfaceGLX.cpp +++ b/gfx/gl/SharedSurfaceGLX.cpp @@ -120,7 +120,7 @@ SharedSurface_GLXDrawable::ReadbackBySharedHandle(gfx::DataSourceSurface* out_su UniquePtr SurfaceFactory_GLXDrawable::Create(GLContext* prodGL, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags) { MOZ_ASSERT(caps.alpha, "GLX surfaces require an alpha channel!"); diff --git a/gfx/gl/SharedSurfaceGLX.h b/gfx/gl/SharedSurfaceGLX.h index c60200c2cb..e605a88a1f 100644 --- a/gfx/gl/SharedSurfaceGLX.h +++ b/gfx/gl/SharedSurfaceGLX.h @@ -49,14 +49,14 @@ class SurfaceFactory_GLXDrawable public: static UniquePtr Create(GLContext* prodGL, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags); virtual UniquePtr CreateShared(const gfx::IntSize& size) override; private: SurfaceFactory_GLXDrawable(GLContext* prodGL, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags) : SurfaceFactory(SharedSurfaceType::GLXDrawable, prodGL, caps, allocator, flags) { } diff --git a/gfx/gl/SharedSurfaceGralloc.cpp b/gfx/gl/SharedSurfaceGralloc.cpp index 3537780ef1..d4ecc820a3 100644 --- a/gfx/gl/SharedSurfaceGralloc.cpp +++ b/gfx/gl/SharedSurfaceGralloc.cpp @@ -35,7 +35,7 @@ using namespace mozilla::layers; using namespace android; SurfaceFactory_Gralloc::SurfaceFactory_Gralloc(GLContext* prodGL, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags) : SurfaceFactory(SharedSurfaceType::Gralloc, prodGL, caps, allocator, flags) { @@ -48,7 +48,7 @@ SharedSurface_Gralloc::Create(GLContext* prodGL, const gfx::IntSize& size, bool hasAlpha, layers::TextureFlags flags, - ISurfaceAllocator* allocator) + ClientIPCAllocator* allocator) { GLLibraryEGL* egl = &sEGLLibrary; MOZ_ASSERT(egl); @@ -118,7 +118,7 @@ SharedSurface_Gralloc::SharedSurface_Gralloc(GLContext* prodGL, const gfx::IntSize& size, bool hasAlpha, GLLibraryEGL* egl, - layers::ISurfaceAllocator* allocator, + layers::ClientIPCAllocator* allocator, layers::TextureClient* textureClient, GLuint prodTex) : SharedSurface(SharedSurfaceType::Gralloc, diff --git a/gfx/gl/SharedSurfaceGralloc.h b/gfx/gl/SharedSurfaceGralloc.h index 09b4c12782..21c9e5fbac 100644 --- a/gfx/gl/SharedSurfaceGralloc.h +++ b/gfx/gl/SharedSurfaceGralloc.h @@ -12,7 +12,7 @@ namespace mozilla { namespace layers { -class ISurfaceAllocator; +class ClientIPCAllocator; class TextureClient; } @@ -29,7 +29,7 @@ public: const gfx::IntSize& size, bool hasAlpha, layers::TextureFlags flags, - layers::ISurfaceAllocator* allocator); + layers::ClientIPCAllocator* allocator); static SharedSurface_Gralloc* Cast(SharedSurface* surf) { MOZ_ASSERT(surf->mType == SharedSurfaceType::Gralloc); @@ -40,7 +40,7 @@ public: protected: GLLibraryEGL* const mEGL; EGLSync mSync; - RefPtr mAllocator; + RefPtr mAllocator; RefPtr mTextureClient; const GLuint mProdTex; @@ -48,7 +48,7 @@ protected: const gfx::IntSize& size, bool hasAlpha, GLLibraryEGL* egl, - layers::ISurfaceAllocator* allocator, + layers::ClientIPCAllocator* allocator, layers::TextureClient* textureClient, GLuint prodTex); @@ -83,7 +83,7 @@ class SurfaceFactory_Gralloc { public: SurfaceFactory_Gralloc(GLContext* prodGL, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags); virtual UniquePtr CreateShared(const gfx::IntSize& size) override { diff --git a/gfx/gl/SharedSurfaceIO.cpp b/gfx/gl/SharedSurfaceIO.cpp index d26b9966ce..c515ae6312 100644 --- a/gfx/gl/SharedSurfaceIO.cpp +++ b/gfx/gl/SharedSurfaceIO.cpp @@ -212,7 +212,7 @@ SharedSurface_IOSurface::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surf /*static*/ UniquePtr SurfaceFactory_IOSurface::Create(GLContext* gl, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags) { gfx::IntSize maxDims(MacIOSurface::GetMaxWidth(), diff --git a/gfx/gl/SharedSurfaceIO.h b/gfx/gl/SharedSurfaceIO.h index bbb9d7f893..44d15acffc 100644 --- a/gfx/gl/SharedSurfaceIO.h +++ b/gfx/gl/SharedSurfaceIO.h @@ -77,13 +77,13 @@ public: // Infallible. static UniquePtr Create(GLContext* gl, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags); protected: const gfx::IntSize mMaxDims; SurfaceFactory_IOSurface(GLContext* gl, const SurfaceCaps& caps, - const RefPtr& allocator, + const RefPtr& allocator, const layers::TextureFlags& flags, const gfx::IntSize& maxDims) : SurfaceFactory(SharedSurfaceType::IOSurface, gl, caps, allocator, flags) diff --git a/gfx/layers/BufferTexture.cpp b/gfx/layers/BufferTexture.cpp index 74178b187b..5d7d8151bc 100644 --- a/gfx/layers/BufferTexture.cpp +++ b/gfx/layers/BufferTexture.cpp @@ -10,6 +10,7 @@ #include "mozilla/gfx/Logging.h" #include "mozilla/gfx/2D.h" #include "mozilla/fallible.h" +#include #ifdef MOZ_WIDGET_GTK #include "gfxPlatformGtk.h" @@ -24,16 +25,16 @@ public: static MemoryTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::BackendType aMoz2DBackend,TextureFlags aFlags, TextureAllocationFlags aAllocFlags, - ISurfaceAllocator* aAllocator); + ClientIPCAllocator* aAllocator); virtual TextureData* - CreateSimilar(ISurfaceAllocator* aAllocator, + CreateSimilar(ClientIPCAllocator* aAllocator, TextureFlags aFlags = TextureFlags::DEFAULT, TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override; - virtual void Deallocate(ISurfaceAllocator*) override; + virtual void Deallocate(ClientIPCAllocator*) override; MemoryTextureData(const BufferDescriptor& aDesc, gfx::BackendType aMoz2DBackend, @@ -61,16 +62,16 @@ public: static ShmemTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::BackendType aMoz2DBackend, TextureFlags aFlags, TextureAllocationFlags aAllocFlags, - ISurfaceAllocator* aAllocator); + ClientIPCAllocator* aAllocator); virtual TextureData* - CreateSimilar(ISurfaceAllocator* aAllocator, + CreateSimilar(ClientIPCAllocator* aAllocator, TextureFlags aFlags = TextureFlags::DEFAULT, TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override; - virtual void Deallocate(ISurfaceAllocator* aAllocator) override; + virtual void Deallocate(ClientIPCAllocator* aAllocator) override; ShmemTextureData(const BufferDescriptor& aDesc, gfx::BackendType aMoz2DBackend, mozilla::ipc::Shmem aShmem) @@ -110,19 +111,20 @@ BufferTextureData* BufferTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::BackendType aMoz2DBackend, TextureFlags aFlags, TextureAllocationFlags aAllocFlags, - ISurfaceAllocator* aAllocator) + ClientIPCAllocator* aAllocator) { if (!aAllocator || aAllocator->IsSameProcess()) { return MemoryTextureData::Create(aSize, aFormat, aMoz2DBackend, aFlags, aAllocFlags, aAllocator); - } else { + } else if (aAllocator->AsShmemAllocator()) { return ShmemTextureData::Create(aSize, aFormat, aMoz2DBackend, aFlags, aAllocFlags, aAllocator); } + return nullptr; } BufferTextureData* -BufferTextureData::CreateInternal(ISurfaceAllocator* aAllocator, +BufferTextureData::CreateInternal(ClientIPCAllocator* aAllocator, const BufferDescriptor& aDesc, gfx::BackendType aMoz2DBackend, int32_t aBufferSize, @@ -137,18 +139,19 @@ BufferTextureData::CreateInternal(ISurfaceAllocator* aAllocator, GfxMemoryImageReporter::DidAlloc(buffer); return new MemoryTextureData(aDesc, aMoz2DBackend, buffer, aBufferSize); - } else { + } else if (aAllocator->AsShmemAllocator()) { ipc::Shmem shm; - if (!aAllocator->AllocUnsafeShmem(aBufferSize, OptimalShmemType(), &shm)) { + if (!aAllocator->AsShmemAllocator()->AllocUnsafeShmem(aBufferSize, OptimalShmemType(), &shm)) { return nullptr; } return new ShmemTextureData(aDesc, aMoz2DBackend, shm); } + return nullptr; } BufferTextureData* -BufferTextureData::CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator, +BufferTextureData::CreateForYCbCrWithBufferSize(ClientIPCAllocator* aAllocator, gfx::SurfaceFormat aFormat, int32_t aBufferSize, TextureFlags aTextureFlags) @@ -167,7 +170,7 @@ BufferTextureData::CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator, } BufferTextureData* -BufferTextureData::CreateForYCbCr(ISurfaceAllocator* aAllocator, +BufferTextureData::CreateForYCbCr(ClientIPCAllocator* aAllocator, gfx::IntSize aYSize, gfx::IntSize aCbCrSize, StereoMode aStereoMode, @@ -206,12 +209,12 @@ BufferTextureData::GetFormat() const bool -BufferTextureData::HasInternalBuffer() const +BufferTextureData::HasIntermediateBuffer() const { if (mDescriptor.type() == BufferDescriptor::TYCbCrDescriptor) { return true; } - return mDescriptor.get_RGBDescriptor().hasInternalBuffer(); + return mDescriptor.get_RGBDescriptor().hasIntermediateBuffer(); } bool @@ -245,7 +248,7 @@ BufferTextureData::BorrowDrawTarget() uint32_t stride = ImageDataSerializer::GetRGBStride(rgb); mDrawTarget = gfx::Factory::CreateDrawTargetForData(mMoz2DBackend, GetBuffer(), rgb.size(), - stride, rgb.format()); + stride, rgb.format(), true); if (mDrawTarget) { RefPtr dt = mDrawTarget; @@ -257,7 +260,7 @@ BufferTextureData::BorrowDrawTarget() if (mMoz2DBackend != gfx::BackendType::CAIRO) { mDrawTarget = gfx::Factory::CreateDrawTargetForData(gfx::BackendType::CAIRO, GetBuffer(), rgb.size(), - stride, rgb.format()); + stride, rgb.format(), true); } if (!mDrawTarget) { @@ -397,7 +400,7 @@ MemoryTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) return true; } -static bool InitBuffer(uint8_t* buf, size_t bufSize, TextureAllocationFlags aAllocFlags) +static bool InitBuffer(uint8_t* buf, size_t bufSize, gfx::SurfaceFormat aFormat, TextureAllocationFlags aAllocFlags) { if (!buf) { gfxDebug() << "BufferTextureData: Failed to allocate " << bufSize << " bytes"; @@ -406,7 +409,13 @@ static bool InitBuffer(uint8_t* buf, size_t bufSize, TextureAllocationFlags aAll if ((aAllocFlags & ALLOC_CLEAR_BUFFER) || (aAllocFlags & ALLOC_CLEAR_BUFFER_BLACK)) { - memset(buf, 0, bufSize); + if (aFormat == gfx::SurfaceFormat::B8G8R8X8) { + // Even though BGRX was requested, XRGB_UINT32 is what is meant, + // so use 0xFF000000 to put alpha in the right place. + std::fill_n(reinterpret_cast(buf), bufSize / sizeof(uint32_t), 0xFF000000); + } else { + memset(buf, 0, bufSize); + } } if (aAllocFlags & ALLOC_CLEAR_BUFFER_WHITE) { @@ -420,7 +429,7 @@ MemoryTextureData* MemoryTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::BackendType aMoz2DBackend, TextureFlags aFlags, TextureAllocationFlags aAllocFlags, - ISurfaceAllocator* aAllocator) + ClientIPCAllocator* aAllocator) { // Should have used CreateForYCbCr. MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV); @@ -436,24 +445,24 @@ MemoryTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, } uint8_t* buf = new (fallible) uint8_t[bufSize]; - if (!InitBuffer(buf, bufSize, aAllocFlags)) { + if (!InitBuffer(buf, bufSize, aFormat, aAllocFlags)) { return nullptr; } auto fwd = aAllocator ? aAllocator->AsCompositableForwarder() : nullptr; - bool hasInternalBuffer = fwd ? ComputeHasIntermediateBuffer(aFormat, + bool hasIntermediateBuffer = fwd ? ComputeHasIntermediateBuffer(aFormat, fwd->GetCompositorBackendType()) - : true; + : true; GfxMemoryImageReporter::DidAlloc(buf); - BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat, hasInternalBuffer); + BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat, hasIntermediateBuffer); return new MemoryTextureData(descriptor, aMoz2DBackend, buf, bufSize); } void -MemoryTextureData::Deallocate(ISurfaceAllocator*) +MemoryTextureData::Deallocate(ClientIPCAllocator*) { MOZ_ASSERT(mBuffer); GfxMemoryImageReporter::WillFree(mBuffer); @@ -462,7 +471,7 @@ MemoryTextureData::Deallocate(ISurfaceAllocator*) } TextureData* -MemoryTextureData::CreateSimilar(ISurfaceAllocator* aAllocator, +MemoryTextureData::CreateSimilar(ClientIPCAllocator* aAllocator, TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const { @@ -487,13 +496,13 @@ ShmemTextureData* ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::BackendType aMoz2DBackend, TextureFlags aFlags, TextureAllocationFlags aAllocFlags, - ISurfaceAllocator* aAllocator) + ClientIPCAllocator* aAllocator) { MOZ_ASSERT(aAllocator); // Should have used CreateForYCbCr. MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV); - if (!aAllocator) { + if (!aAllocator || !aAllocator->AsShmemAllocator()) { return nullptr; } @@ -508,21 +517,21 @@ ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, } mozilla::ipc::Shmem shm; - if (!aAllocator->AllocUnsafeShmem(bufSize, OptimalShmemType(), &shm)) { + if (!aAllocator->AsShmemAllocator()->AllocUnsafeShmem(bufSize, OptimalShmemType(), &shm)) { return nullptr; } uint8_t* buf = shm.get(); - if (!InitBuffer(buf, bufSize, aAllocFlags)) { + if (!InitBuffer(buf, bufSize, aFormat, aAllocFlags)) { return nullptr; } auto fwd = aAllocator->AsCompositableForwarder(); - bool hasInternalBuffer = fwd ? ComputeHasIntermediateBuffer(aFormat, + bool hasIntermediateBuffer = fwd ? ComputeHasIntermediateBuffer(aFormat, fwd->GetCompositorBackendType()) - : true; + : true; - BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat, hasInternalBuffer); + BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat, hasIntermediateBuffer); return new ShmemTextureData(descriptor, aMoz2DBackend, shm); @@ -530,7 +539,7 @@ ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, } TextureData* -ShmemTextureData::CreateSimilar(ISurfaceAllocator* aAllocator, +ShmemTextureData::CreateSimilar(ClientIPCAllocator* aAllocator, TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const { @@ -539,9 +548,9 @@ ShmemTextureData::CreateSimilar(ISurfaceAllocator* aAllocator, } void -ShmemTextureData::Deallocate(ISurfaceAllocator* aAllocator) +ShmemTextureData::Deallocate(ClientIPCAllocator* aAllocator) { - aAllocator->DeallocShmem(mShmem); + aAllocator->AsShmemAllocator()->DeallocShmem(mShmem); } } // namespace diff --git a/gfx/layers/BufferTexture.h b/gfx/layers/BufferTexture.h index bdae634ec7..b0ba2aa40c 100644 --- a/gfx/layers/BufferTexture.h +++ b/gfx/layers/BufferTexture.h @@ -21,9 +21,9 @@ public: static BufferTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::BackendType aMoz2DBackend,TextureFlags aFlags, TextureAllocationFlags aAllocFlags, - ISurfaceAllocator* aAllocator); + ClientIPCAllocator* aAllocator); - static BufferTextureData* CreateForYCbCr(ISurfaceAllocator* aAllocator, + static BufferTextureData* CreateForYCbCr(ClientIPCAllocator* aAllocator, gfx::IntSize aYSize, gfx::IntSize aCbCrSize, StereoMode aStereoMode, @@ -32,7 +32,7 @@ public: // It is generally better to use CreateForYCbCr instead. // This creates a half-initialized texture since we don't know the sizes and // offsets in the buffer. - static BufferTextureData* CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator, + static BufferTextureData* CreateForYCbCrWithBufferSize(ClientIPCAllocator* aAllocator, gfx::SurfaceFormat aFormat, int32_t aSize, TextureFlags aTextureFlags); @@ -55,7 +55,7 @@ public: virtual bool SupportsMoz2D() const override; - virtual bool HasInternalBuffer() const override; + virtual bool HasIntermediateBuffer() const override; // use TextureClient's default implementation virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override; @@ -64,7 +64,7 @@ public: void SetDesciptor(const BufferDescriptor& aDesc); protected: - static BufferTextureData* CreateInternal(ISurfaceAllocator* aAllocator, + static BufferTextureData* CreateInternal(ClientIPCAllocator* aAllocator, const BufferDescriptor& aDesc, gfx::BackendType aMoz2DBackend, int32_t aBufferSize, diff --git a/gfx/layers/D3D11ShareHandleImage.cpp b/gfx/layers/D3D11ShareHandleImage.cpp index d80d551187..3ebca000b9 100644 --- a/gfx/layers/D3D11ShareHandleImage.cpp +++ b/gfx/layers/D3D11ShareHandleImage.cpp @@ -55,17 +55,6 @@ D3D11ShareHandleImage::GetAsSourceSurface() RefPtr device; texture->GetDevice(getter_AddRefs(device)); - RefPtr keyedMutex; - if (FAILED(texture->QueryInterface(static_cast(getter_AddRefs(keyedMutex))))) { - NS_WARNING("Failed to QueryInterface for IDXGIKeyedMutex, strange."); - return nullptr; - } - - if (FAILED(keyedMutex->AcquireSync(0, 0))) { - NS_WARNING("Failed to acquire sync for keyedMutex, plugin failed to release?"); - return nullptr; - } - D3D11_TEXTURE2D_DESC desc; texture->GetDesc(&desc); @@ -83,19 +72,16 @@ D3D11ShareHandleImage::GetAsSourceSurface() if (FAILED(hr)) { NS_WARNING("Failed to create 2D staging texture."); - keyedMutex->ReleaseSync(0); return nullptr; } RefPtr context; device->GetImmediateContext(getter_AddRefs(context)); if (!context) { - keyedMutex->ReleaseSync(0); return nullptr; } context->CopyResource(softTexture, texture); - keyedMutex->ReleaseSync(0); RefPtr surface = gfx::Factory::CreateDataSourceSurface(mSize, gfx::SurfaceFormat::B8G8R8X8); @@ -152,7 +138,8 @@ D3D11RecycleAllocator::CreateOrRecycleClient(gfx::SurfaceFormat aFormat, CreateOrRecycle(aFormat, aSize, BackendSelector::Content, - layers::TextureFlags::DEFAULT); + layers::TextureFlags::DEFAULT, + TextureAllocationFlags::ALLOC_MANUAL_SYNCHRONIZATION); return textureClient.forget(); } diff --git a/gfx/layers/D3D9SurfaceImage.cpp b/gfx/layers/D3D9SurfaceImage.cpp index bc49f45261..49e31ee9b8 100644 --- a/gfx/layers/D3D9SurfaceImage.cpp +++ b/gfx/layers/D3D9SurfaceImage.cpp @@ -15,11 +15,10 @@ namespace mozilla { namespace layers { -D3D9SurfaceImage::D3D9SurfaceImage(bool aIsFirstFrame) +D3D9SurfaceImage::D3D9SurfaceImage() : Image(nullptr, ImageFormat::D3D9_RGB32_TEXTURE) , mSize(0, 0) - , mValid(false) - , mIsFirstFrame(aIsFirstFrame) + , mValid(true) {} D3D9SurfaceImage::~D3D9SurfaceImage() @@ -73,50 +72,16 @@ D3D9SurfaceImage::AllocateAndCopy(D3D9RecycleAllocator* aAllocator, hr = device->StretchRect(surface, &src, textureSurface, nullptr, D3DTEXF_NONE); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - // Flush the draw command now, so that by the time we come to draw this - // image, we're less likely to need to wait for the draw operation to - // complete. - RefPtr query; - hr = device->CreateQuery(D3DQUERYTYPE_EVENT, getter_AddRefs(query)); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - hr = query->Issue(D3DISSUE_END); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - mTextureClient = textureClient; mSize = aRegion.Size(); - mQuery = query; return S_OK; } -bool -D3D9SurfaceImage::IsValid() +already_AddRefed +D3D9SurfaceImage::GetD3D9Surface() { - EnsureSynchronized(); - return mValid; -} - -void -D3D9SurfaceImage::EnsureSynchronized() -{ - RefPtr query = mQuery; - if (!query) { - // Not setup, or already synchronized. - return; - } - int iterations = 0; - while (iterations < (mIsFirstFrame ? 100 : 10)) { - HRESULT hr = query->GetData(nullptr, 0, D3DGETDATA_FLUSH); - if (hr == S_FALSE) { - Sleep(1); - iterations++; - continue; - } - if (hr == S_OK) { - mValid = true; - } - break; - } - mQuery = nullptr; + return static_cast( + mTextureClient->GetInternalData())->GetD3D9Surface(); } const D3DSURFACE_DESC& @@ -136,7 +101,6 @@ D3D9SurfaceImage::GetTextureClient(CompositableClient* aClient) { MOZ_ASSERT(mTextureClient); MOZ_ASSERT(mTextureClient->GetAllocator() == aClient->GetForwarder()); - EnsureSynchronized(); return mTextureClient; } @@ -153,9 +117,6 @@ D3D9SurfaceImage::GetAsSourceSurface() return nullptr; } - // Ensure that the texture is ready to be used. - EnsureSynchronized(); - DXGID3D9TextureData* texData = static_cast(mTextureClient->GetInternalData()); // Readback the texture from GPU memory into system memory, so that // we can copy it into the Cairo image. This is expensive. diff --git a/gfx/layers/D3D9SurfaceImage.h b/gfx/layers/D3D9SurfaceImage.h index 86c7616ad2..f861bc0a28 100644 --- a/gfx/layers/D3D9SurfaceImage.h +++ b/gfx/layers/D3D9SurfaceImage.h @@ -47,7 +47,7 @@ protected: // resource is ready to use. class D3D9SurfaceImage : public Image { public: - explicit D3D9SurfaceImage(bool aIsFirstFrame); + explicit D3D9SurfaceImage(); virtual ~D3D9SurfaceImage(); HRESULT AllocateAndCopy(D3D9RecycleAllocator* aAllocator, @@ -63,19 +63,17 @@ public: virtual TextureClient* GetTextureClient(CompositableClient* aClient) override; - virtual bool IsValid() override; + already_AddRefed GetD3D9Surface(); + + virtual bool IsValid() override { return mValid; } + + void Invalidate() { mValid = false; } private: - // Blocks the calling thread until the copy operation started in SetData() - // is complete, whereupon the texture is safe to use. - void EnsureSynchronized(); - gfx::IntSize mSize; - RefPtr mQuery; RefPtr mTextureClient; bool mValid; - bool mIsFirstFrame; }; } // namepace layers diff --git a/gfx/layers/GrallocImages.cpp b/gfx/layers/GrallocImages.cpp index e149a45972..8c3f1de1d9 100644 --- a/gfx/layers/GrallocImages.cpp +++ b/gfx/layers/GrallocImages.cpp @@ -73,7 +73,7 @@ GrallocImage::SetData(const Data& aData) return false; } - ISurfaceAllocator* allocator = ImageBridgeChild::GetSingleton(); + ClientIPCAllocator* allocator = ImageBridgeChild::GetSingleton(); GrallocTextureData* texData = GrallocTextureData::Create(mData.mYSize, HAL_PIXEL_FORMAT_YV12, gfx::BackendType::NONE, GraphicBuffer::USAGE_SW_READ_OFTEN | diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index e73cf33e6d..013f3b1cdb 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -250,7 +250,9 @@ Layer::Layer(LayerManager* aManager, void* aImplData) : mScrollbarDirection(ScrollDirection::NONE), mScrollbarThumbRatio(0.0f), mIsScrollbarContainer(false), +#ifdef DEBUG mDebugColorIndex(0), +#endif mAnimationGeneration(0) { MOZ_COUNT_CTOR(Layer); diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index ed55e4a5e0..14a3b6d84d 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -1845,7 +1845,9 @@ protected: // CSS pixels of the scrollframe's space). float mScrollbarThumbRatio; bool mIsScrollbarContainer; - DebugOnly mDebugColorIndex; +#ifdef DEBUG + uint32_t mDebugColorIndex; +#endif // If this layer is used for OMTA, then this counter is used to ensure we // stay in sync with the animation manager uint64_t mAnimationGeneration; diff --git a/gfx/layers/TextureDIB.cpp b/gfx/layers/TextureDIB.cpp index 7c825da3a3..3f631b5391 100644 --- a/gfx/layers/TextureDIB.cpp +++ b/gfx/layers/TextureDIB.cpp @@ -24,7 +24,7 @@ public: virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override; virtual TextureData* - CreateSimilar(ISurfaceAllocator* aAllocator, + CreateSimilar(ClientIPCAllocator* aAllocator, TextureFlags aFlags = TextureFlags::DEFAULT, TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; @@ -33,7 +33,7 @@ public: static DIBTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat); - virtual void Deallocate(ISurfaceAllocator* aAllocator) override + virtual void Deallocate(ClientIPCAllocator* aAllocator) override { mSurface = nullptr; } @@ -61,7 +61,7 @@ public: virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override; virtual TextureData* - CreateSimilar(ISurfaceAllocator* aAllocator, + CreateSimilar(ClientIPCAllocator* aAllocator, TextureFlags aFlags = TextureFlags::DEFAULT, TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; @@ -69,7 +69,7 @@ public: static DIBTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, - ISurfaceAllocator* aAllocator); + ClientIPCAllocator* aAllocator); void DeallocateData() { @@ -84,7 +84,7 @@ public: } } - virtual void Deallocate(ISurfaceAllocator* aAllocator) override + virtual void Deallocate(ClientIPCAllocator* aAllocator) override { DeallocateData(); } @@ -125,7 +125,7 @@ DIBTextureData::BorrowDrawTarget() DIBTextureData* DIBTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, - ISurfaceAllocator* aAllocator) + ClientIPCAllocator* aAllocator) { if (!aAllocator) { return nullptr; @@ -141,7 +141,7 @@ DIBTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, } TextureData* -MemoryDIBTextureData::CreateSimilar(ISurfaceAllocator* aAllocator, +MemoryDIBTextureData::CreateSimilar(ClientIPCAllocator* aAllocator, TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const { @@ -204,7 +204,7 @@ MemoryDIBTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface) } TextureData* -ShmemDIBTextureData::CreateSimilar(ISurfaceAllocator* aAllocator, +ShmemDIBTextureData::CreateSimilar(ClientIPCAllocator* aAllocator, TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const { @@ -268,9 +268,9 @@ ShmemDIBTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) DIBTextureData* ShmemDIBTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, - ISurfaceAllocator* aAllocator) + ClientIPCAllocator* aAllocator) { - MOZ_ASSERT(aAllocator->ParentPid() != base::ProcessId()); + MOZ_ASSERT(aAllocator->AsLayerForwarder()->GetParentPid() != base::ProcessId()); DWORD mapSize = aSize.width * aSize.height * BytesPerPixel(aFormat); HANDLE fileMapping = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, mapSize, NULL); @@ -332,7 +332,7 @@ ShmemDIBTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, HANDLE hostHandle = NULL; - if (!ipc::DuplicateHandle(fileMapping, aAllocator->ParentPid(), + if (!ipc::DuplicateHandle(fileMapping, aAllocator->AsLayerForwarder()->GetParentPid(), &hostHandle, 0, DUPLICATE_SAME_ACCESS)) { gfxCriticalError() << "Failed to duplicate handle to parent process for surface."; ::DeleteObject(bitmap); diff --git a/gfx/layers/TextureDIB.h b/gfx/layers/TextureDIB.h index 6e340f2150..cf94da6c42 100644 --- a/gfx/layers/TextureDIB.h +++ b/gfx/layers/TextureDIB.h @@ -30,11 +30,11 @@ public: virtual already_AddRefed BorrowDrawTarget() override; - virtual bool HasInternalBuffer() const override { return true; } + virtual bool HasIntermediateBuffer() const override { return true; } static DIBTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, - ISurfaceAllocator* aAllocator); + ClientIPCAllocator* aAllocator); protected: DIBTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, @@ -80,7 +80,7 @@ public: virtual void Unlock() override; - virtual bool HasInternalBuffer() const { return true; } + virtual bool HasIntermediateBuffer() const { return true; } virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override; diff --git a/gfx/layers/basic/TextureClientX11.cpp b/gfx/layers/basic/TextureClientX11.cpp index 9fdb04ad6e..0d7ff0c333 100644 --- a/gfx/layers/basic/TextureClientX11.cpp +++ b/gfx/layers/basic/TextureClientX11.cpp @@ -96,13 +96,13 @@ X11TextureData::UpdateFromSurface(gfx::SourceSurface* aSurface) } void -X11TextureData::Deallocate(ISurfaceAllocator*) +X11TextureData::Deallocate(ClientIPCAllocator*) { mSurface = nullptr; } TextureData* -X11TextureData::CreateSimilar(ISurfaceAllocator* aAllocator, +X11TextureData::CreateSimilar(ClientIPCAllocator* aAllocator, TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const { @@ -111,7 +111,7 @@ X11TextureData::CreateSimilar(ISurfaceAllocator* aAllocator, X11TextureData* X11TextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, - TextureFlags aFlags, ISurfaceAllocator* aAllocator) + TextureFlags aFlags, ClientIPCAllocator* aAllocator) { MOZ_ASSERT(aSize.width >= 0 && aSize.height >= 0); if (aSize.width <= 0 || aSize.height <= 0 || diff --git a/gfx/layers/basic/TextureClientX11.h b/gfx/layers/basic/TextureClientX11.h index efb1add8e9..69d2f2fcff 100644 --- a/gfx/layers/basic/TextureClientX11.h +++ b/gfx/layers/basic/TextureClientX11.h @@ -17,7 +17,7 @@ class X11TextureData : public TextureData { public: static X11TextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, - TextureFlags aFlags, ISurfaceAllocator* aAllocator); + TextureFlags aFlags, ClientIPCAllocator* aAllocator); virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override; @@ -33,12 +33,12 @@ public: virtual bool SupportsMoz2D() const override { return true; } - virtual bool HasInternalBuffer() const override { return false; } + virtual bool HasIntermediateBuffer() const override { return false; } - virtual void Deallocate(ISurfaceAllocator*) override; + virtual void Deallocate(ClientIPCAllocator*) override; virtual TextureData* - CreateSimilar(ISurfaceAllocator* aAllocator, + CreateSimilar(ClientIPCAllocator* aAllocator, TextureFlags aFlags = TextureFlags::DEFAULT, TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; diff --git a/gfx/layers/client/CanvasClient.cpp b/gfx/layers/client/CanvasClient.cpp index a11c8c35f4..7796a4d89b 100644 --- a/gfx/layers/client/CanvasClient.cpp +++ b/gfx/layers/client/CanvasClient.cpp @@ -182,7 +182,7 @@ static inline void SwapRB_R8G8B8A8(uint8_t* pixel) { class TexClientFactory { - ISurfaceAllocator* const mAllocator; + ClientIPCAllocator* const mAllocator; const bool mHasAlpha; const gfx::IntSize mSize; const gfx::BackendType mBackendType; @@ -190,7 +190,7 @@ class TexClientFactory const LayersBackend mLayersBackend; public: - TexClientFactory(ISurfaceAllocator* allocator, bool hasAlpha, + TexClientFactory(ClientIPCAllocator* allocator, bool hasAlpha, const gfx::IntSize& size, gfx::BackendType backendType, TextureFlags baseTexFlags, LayersBackend layersBackend) : mAllocator(allocator) @@ -238,7 +238,7 @@ public: }; static already_AddRefed -TexClientFromReadback(SharedSurface* src, ISurfaceAllocator* allocator, +TexClientFromReadback(SharedSurface* src, ClientIPCAllocator* allocator, TextureFlags baseFlags, LayersBackend layersBackend) { auto backendType = gfx::BackendType::CAIRO; diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index f5c022a302..c891becbc7 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -538,7 +538,7 @@ ClientLayerManager::MakeSnapshotIfRequired() DrawOptions(1.0f, CompositionOp::OP_OVER)); dt->SetTransform(oldMatrix); } - mForwarder->DestroySharedSurface(&inSnapshot); + mForwarder->DestroySurfaceDescriptor(&inSnapshot); } } } diff --git a/gfx/layers/client/CompositableClient.cpp b/gfx/layers/client/CompositableClient.cpp index 0d0b0a3c92..96b54a8a75 100644 --- a/gfx/layers/client/CompositableClient.cpp +++ b/gfx/layers/client/CompositableClient.cpp @@ -62,12 +62,12 @@ RemoveTextureFromCompositableTracker::ReleaseTextureClient() { if (mTextureClient && mTextureClient->GetAllocator() && - !mTextureClient->GetAllocator()->IsImageBridgeChild()) + !mTextureClient->GetAllocator()->UsesImageBridge()) { TextureClientReleaseTask* task = new TextureClientReleaseTask(mTextureClient); - RefPtr allocator = mTextureClient->GetAllocator(); + RefPtr allocator = mTextureClient->GetAllocator(); mTextureClient = nullptr; - allocator->GetMessageLoop()->PostTask(FROM_HERE, task); + allocator->AsClientAllocator()->GetMessageLoop()->PostTask(FROM_HERE, task); } else { mTextureClient = nullptr; } diff --git a/gfx/layers/client/ImageClient.cpp b/gfx/layers/client/ImageClient.cpp index 785a8d16f1..b43847dbfe 100644 --- a/gfx/layers/client/ImageClient.cpp +++ b/gfx/layers/client/ImageClient.cpp @@ -75,8 +75,7 @@ void ImageClient::RemoveTextureWithWaiter(TextureClient* aTexture, AsyncTransactionWaiter* aAsyncTransactionWaiter) { - if ((aAsyncTransactionWaiter || - GetForwarder()->IsImageBridgeChild()) + if ((aAsyncTransactionWaiter || GetForwarder()->UsesImageBridge()) #ifndef MOZ_WIDGET_GONK // If the texture client is taking part in recycling then we should make sure // the host has finished with it before dropping the ref and triggering diff --git a/gfx/layers/client/SingleTiledContentClient.cpp b/gfx/layers/client/SingleTiledContentClient.cpp index 2b9bd7d313..16488e08c2 100644 --- a/gfx/layers/client/SingleTiledContentClient.cpp +++ b/gfx/layers/client/SingleTiledContentClient.cpp @@ -209,7 +209,7 @@ ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion, mTile.Flip(); UnlockTile(mTile); - if (backBuffer->HasInternalBuffer()) { + if (backBuffer->HasIntermediateBuffer()) { // If our new buffer has an internal buffer, we don't want to keep another // TextureClient around unnecessarily, so discard the back-buffer. mTile.DiscardBackBuffer(); diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index 4c8a84575c..45059f739d 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -73,9 +73,10 @@ struct TextureDeallocParams { TextureData* data; RefPtr actor; - RefPtr allocator; + RefPtr allocator; bool clientDeallocation; bool syncDeallocation; + bool workAroundSharedSurfaceOwnershipIssue; }; void DeallocateTextureClient(TextureDeallocParams params); @@ -132,9 +133,18 @@ public: SendClientRecycle(); } + void CancelWaitForCompositorRecycle() + { + RECYCLE_LOG("[CLIENT] Cancelling wait for recycle %p\n", mWaitForRecycle.get()); + { + MonitorAutoLock mon(mMonitor); + mWaitForRecycle = nullptr; + } + } + CompositableForwarder* GetForwarder() { return mForwarder; } - ISurfaceAllocator* GetAllocator() { return mForwarder; } + ClientIPCAllocator* GetAllocator() { return mForwarder; } void ActorDestroy(ActorDestroyReason why) override; @@ -179,7 +189,7 @@ private: }; -static void DestroyTextureData(TextureData* aTextureData, ISurfaceAllocator* aAllocator, +static void DestroyTextureData(TextureData* aTextureData, ClientIPCAllocator* aAllocator, bool aDeallocate, bool aMainThreadOnly) { if (!aTextureData) { @@ -187,7 +197,7 @@ static void DestroyTextureData(TextureData* aTextureData, ISurfaceAllocator* aAl } if (aMainThreadOnly && !NS_IsMainThread()) { - RefPtr allocatorRef = aAllocator; + RefPtr allocatorRef = aAllocator; NS_DispatchToMainThread(NS_NewRunnableFunction([aTextureData, allocatorRef, aDeallocate]() -> void { DestroyTextureData(aTextureData, allocatorRef, aDeallocate, true); })); @@ -239,7 +249,7 @@ DeallocateTextureClient(TextureDeallocParams params) MessageLoop* ipdlMsgLoop = nullptr; if (params.allocator) { - ipdlMsgLoop = params.allocator->GetMessageLoop(); + ipdlMsgLoop = params.allocator->AsClientAllocator()->GetMessageLoop(); if (!ipdlMsgLoop) { // An allocator with no message loop means we are too late in the shutdown // sequence. @@ -273,7 +283,7 @@ DeallocateTextureClient(TextureDeallocParams params) if (!ipdlMsgLoop) { // If we don't have a message loop we can't know for sure that we are in - // the IPDL thread and use the ISurfaceAllocator. + // the IPDL thread and use the ClientIPCAllocator. // This should ideally not happen outside of gtest, but some shutdown raciness // could put us in this situation. params.allocator = nullptr; @@ -282,9 +292,14 @@ DeallocateTextureClient(TextureDeallocParams params) if (!actor) { // We don't have an IPDL actor, probably because we destroyed the TextureClient // before sharing it with the compositor. It means the data cannot be owned by - // the TextureHost since we never created the TextureHost. + // the TextureHost since we never created the TextureHost... + // ..except if the lovely mWorkaroundAnnoyingSharedSurfaceOwnershipIssues member + // is set to true. In this case we are in a special situation where this + // TextureClient is in wrapped into another TextureClient which assumes it owns + // our data. This is specific to the gralloc SharedSurface. + bool shouldDeallocate = !params.workAroundSharedSurfaceOwnershipIssue; DestroyTextureData(params.data, params.allocator, - true, // client-side deallocation + shouldDeallocate, false); // main-thread deallocation return; } @@ -331,6 +346,7 @@ void TextureClient::Destroy(bool aForceSync) params.actor = actor; params.allocator = mAllocator; params.clientDeallocation = !!(mFlags & TextureFlags::DEALLOCATE_CLIENT); + params.workAroundSharedSurfaceOwnershipIssue = mWorkaroundAnnoyingSharedSurfaceOwnershipIssues; if (mWorkaroundAnnoyingSharedSurfaceLifetimeIssues) { params.data = nullptr; } else { @@ -397,10 +413,10 @@ TextureClient::Unlock() } bool -TextureClient::HasInternalBuffer() const +TextureClient::HasIntermediateBuffer() const { MOZ_ASSERT(IsValid()); - return mData->HasInternalBuffer(); + return mData->HasIntermediateBuffer(); } gfx::IntSize @@ -616,6 +632,14 @@ TextureClient::WaitForCompositorRecycle() } } +void +TextureClient::CancelWaitForCompositorRecycle() +{ + if (IsSharedWithCompositor()) { + mActor->CancelWaitForCompositorRecycle(); + } +} + void TextureClient::SetAddedToCompositableClient() { @@ -645,7 +669,7 @@ TextureClient::SetRecycleAllocator(TextureClientRecycleAllocator* aAllocator) bool TextureClient::InitIPDLActor(CompositableForwarder* aForwarder) { - MOZ_ASSERT(aForwarder && aForwarder->GetMessageLoop() == mAllocator->GetMessageLoop()); + MOZ_ASSERT(aForwarder && aForwarder->GetMessageLoop() == mAllocator->AsClientAllocator()->GetMessageLoop()); if (mActor && !mActor->mDestroyed && mActor->GetForwarder() == aForwarder) { return true; } @@ -779,7 +803,7 @@ TextureClient::CreateForDrawing(CompositableForwarder* aAllocator, // static already_AddRefed -TextureClient::CreateForRawBufferAccess(ISurfaceAllocator* aAllocator, +TextureClient::CreateForRawBufferAccess(ClientIPCAllocator* aAllocator, gfx::SurfaceFormat aFormat, gfx::IntSize aSize, gfx::BackendType aMoz2DBackend, @@ -799,13 +823,6 @@ TextureClient::CreateForRawBufferAccess(ISurfaceAllocator* aAllocator, return nullptr; } - if (aFormat == SurfaceFormat::B8G8R8X8 && - (aAllocFlags != TextureAllocationFlags::ALLOC_CLEAR_BUFFER_BLACK) && - aMoz2DBackend == gfx::BackendType::SKIA) { - // skia requires alpha component of RGBX textures to be 255. - aAllocFlags = TextureAllocationFlags::ALLOC_CLEAR_BUFFER_WHITE; - } - TextureData* texData = BufferTextureData::Create(aSize, aFormat, aMoz2DBackend, aTextureFlags, aAllocFlags, aAllocator); @@ -818,7 +835,7 @@ TextureClient::CreateForRawBufferAccess(ISurfaceAllocator* aAllocator, // static already_AddRefed -TextureClient::CreateForYCbCr(ISurfaceAllocator* aAllocator, +TextureClient::CreateForYCbCr(ClientIPCAllocator* aAllocator, gfx::IntSize aYSize, gfx::IntSize aCbCrSize, StereoMode aStereoMode, @@ -845,7 +862,7 @@ TextureClient::CreateForYCbCr(ISurfaceAllocator* aAllocator, // static already_AddRefed -TextureClient::CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator, +TextureClient::CreateForYCbCrWithBufferSize(ClientIPCAllocator* aAllocator, gfx::SurfaceFormat aFormat, size_t aSize, TextureFlags aTextureFlags) @@ -866,7 +883,7 @@ TextureClient::CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator, return MakeAndAddRef(data, aTextureFlags, aAllocator); } -TextureClient::TextureClient(TextureData* aData, TextureFlags aFlags, ISurfaceAllocator* aAllocator) +TextureClient::TextureClient(TextureData* aData, TextureFlags aFlags, ClientIPCAllocator* aAllocator) : mAllocator(aAllocator) , mActor(nullptr) , mData(aData) @@ -878,6 +895,7 @@ TextureClient::TextureClient(TextureData* aData, TextureFlags aFlags, ISurfaceAl , mIsLocked(false) , mAddedToCompositableClient(false) , mWorkaroundAnnoyingSharedSurfaceLifetimeIssues(false) +, mWorkaroundAnnoyingSharedSurfaceOwnershipIssues(false) #ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL , mPoolTracker(nullptr) #endif @@ -1027,7 +1045,7 @@ SyncObject::CreateSyncObject(SyncHandle aHandle) } already_AddRefed -TextureClient::CreateWithData(TextureData* aData, TextureFlags aFlags, ISurfaceAllocator* aAllocator) +TextureClient::CreateWithData(TextureData* aData, TextureFlags aFlags, ClientIPCAllocator* aAllocator) { if (!aData) { return nullptr; diff --git a/gfx/layers/client/TextureClient.h b/gfx/layers/client/TextureClient.h index 8f1fde7af9..2e151ec4e9 100644 --- a/gfx/layers/client/TextureClient.h +++ b/gfx/layers/client/TextureClient.h @@ -48,7 +48,7 @@ namespace layers { class AsyncTransactionWaiter; class CompositableForwarder; class GrallocTextureData; -class ISurfaceAllocator; +class ClientIPCAllocator; class CompositableClient; struct PlanarYCbCrData; class Image; @@ -80,6 +80,10 @@ enum TextureAllocationFlags { // TextureClientD3D11, which may otherwise choose D3D10 or non-KeyedMutex // surfaces when used on the main thread. ALLOC_FOR_OUT_OF_BAND_CONTENT = 1 << 5, + + // Disable any cross-device synchronization. This is also for TextureClientD3D11, + // and creates a texture without KeyedMutex. + ALLOC_MANUAL_SYNCHRONIZATION = 1 << 6, }; #ifdef XP_WIN @@ -193,7 +197,7 @@ public: virtual bool CanExposeMappedData() const { return false; } - virtual bool HasInternalBuffer() const = 0; + virtual bool HasIntermediateBuffer() const = 0; virtual bool HasSynchronization() const { return false; } @@ -203,15 +207,15 @@ public: virtual bool BorrowMappedYCbCrData(MappedYCbCrTextureData&) { return false; } - virtual void Deallocate(ISurfaceAllocator* aAllocator) = 0; + virtual void Deallocate(ClientIPCAllocator* aAllocator) = 0; /// Depending on the texture's flags either Deallocate or Forget is called. - virtual void Forget(ISurfaceAllocator* aAllocator) {} + virtual void Forget(ClientIPCAllocator* aAllocator) {} virtual bool Serialize(SurfaceDescriptor& aDescriptor) = 0; virtual TextureData* - CreateSimilar(ISurfaceAllocator* aAllocator, + CreateSimilar(ClientIPCAllocator* aAllocator, TextureFlags aFlags = TextureFlags::DEFAULT, TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const { return nullptr; } @@ -263,12 +267,12 @@ class TextureClient : public AtomicRefCountedWithFinalize { public: - explicit TextureClient(TextureData* aData, TextureFlags aFlags, ISurfaceAllocator* aAllocator); + explicit TextureClient(TextureData* aData, TextureFlags aFlags, ClientIPCAllocator* aAllocator); virtual ~TextureClient(); static already_AddRefed - CreateWithData(TextureData* aData, TextureFlags aFlags, ISurfaceAllocator* aAllocator); + CreateWithData(TextureData* aData, TextureFlags aFlags, ClientIPCAllocator* aAllocator); // Creates and allocates a TextureClient usable with Moz2D. static already_AddRefed @@ -281,7 +285,7 @@ public: // Creates and allocates a TextureClient supporting the YCbCr format. static already_AddRefed - CreateForYCbCr(ISurfaceAllocator* aAllocator, + CreateForYCbCr(ClientIPCAllocator* aAllocator, gfx::IntSize aYSize, gfx::IntSize aCbCrSize, StereoMode aStereoMode, @@ -290,7 +294,7 @@ public: // Creates and allocates a TextureClient (can be accessed through raw // pointers). static already_AddRefed - CreateForRawBufferAccess(ISurfaceAllocator* aAllocator, + CreateForRawBufferAccess(ClientIPCAllocator* aAllocator, gfx::SurfaceFormat aFormat, gfx::IntSize aSize, gfx::BackendType aMoz2dBackend, @@ -301,7 +305,7 @@ public: // pointers) with a certain buffer size. It's unfortunate that we need this. // providing format and sizes could let us do more optimization. static already_AddRefed - CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator, + CreateForYCbCrWithBufferSize(ClientIPCAllocator* aAllocator, gfx::SurfaceFormat aFormat, size_t aSize, TextureFlags aTextureFlags); @@ -413,7 +417,7 @@ public: * in-memory buffer. The consequence of this is that locking the * TextureClient does not contend with locking the texture on the host side. */ - bool HasInternalBuffer() const; + bool HasIntermediateBuffer() const; /** * Allocate and deallocate a TextureChild actor. @@ -463,6 +467,12 @@ public: */ void WaitForCompositorRecycle(); + /** + * Should only be called when dying. We no longer care whether the compositor + * has finished with the texture. + */ + void CancelWaitForCompositorRecycle(); + /** * After being shared with the compositor side, an immutable texture is never * modified, it can only be read. It is safe to not Lock/Unlock immutable @@ -571,7 +581,7 @@ public: void SyncWithObject(SyncObject* aFence) { mData->SyncWithObject(aFence); } - ISurfaceAllocator* GetAllocator() { return mAllocator; } + ClientIPCAllocator* GetAllocator() { return mAllocator; } TextureClientRecycleAllocator* GetRecycleAllocator() { return mRecycleAllocator; } void SetRecycleAllocator(TextureClientRecycleAllocator* aAllocator); @@ -609,7 +619,7 @@ protected: bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor); - RefPtr mAllocator; + RefPtr mAllocator; RefPtr mActor; RefPtr mRecycleAllocator; RefPtr mRemoveFromCompositableWaiter; @@ -623,11 +633,14 @@ protected: gl::GfxTextureWasteTracker mWasteTracker; OpenMode mOpenMode; - DebugOnly mExpectedDtRefs; +#ifdef DEBUG + uint32_t mExpectedDtRefs; +#endif bool mIsLocked; bool mAddedToCompositableClient; bool mWorkaroundAnnoyingSharedSurfaceLifetimeIssues; + bool mWorkaroundAnnoyingSharedSurfaceOwnershipIssues; RefPtr mReadbackSink; @@ -677,7 +690,9 @@ public: MOZ_GUARD_OBJECT_NOTIFIER_INIT; mSucceeded = mTexture->Lock(aMode); +#ifdef DEBUG mChecked = false; +#endif } ~TextureClientAutoLock() { MOZ_ASSERT(mChecked); @@ -687,13 +702,17 @@ public: } bool Succeeded() { +#ifdef DEBUG mChecked = true; +#endif return mSucceeded; } private: TextureClient* mTexture; - DebugOnly mChecked; +#ifdef DEBUG + bool mChecked; +#endif bool mSucceeded; }; diff --git a/gfx/layers/client/TextureClientRecycleAllocator.cpp b/gfx/layers/client/TextureClientRecycleAllocator.cpp index f4c04d4888..0cc89e81e6 100644 --- a/gfx/layers/client/TextureClientRecycleAllocator.cpp +++ b/gfx/layers/client/TextureClientRecycleAllocator.cpp @@ -83,7 +83,8 @@ TextureClientRecycleAllocator::CreateOrRecycle(gfx::SurfaceFormat aFormat, // This class does not handle ContentClient's TextureClient allocation. MOZ_ASSERT(aAllocFlags == TextureAllocationFlags::ALLOC_DEFAULT || aAllocFlags == TextureAllocationFlags::ALLOC_DISALLOW_BUFFERTEXTURECLIENT || - aAllocFlags == TextureAllocationFlags::ALLOC_FOR_OUT_OF_BAND_CONTENT); + aAllocFlags == TextureAllocationFlags::ALLOC_FOR_OUT_OF_BAND_CONTENT || + aAllocFlags == TextureAllocationFlags::ALLOC_MANUAL_SYNCHRONIZATION); MOZ_ASSERT(!(aTextureFlags & TextureFlags::RECYCLE)); aTextureFlags = aTextureFlags | TextureFlags::RECYCLE; // Set recycle flag diff --git a/gfx/layers/client/TextureClientSharedSurface.cpp b/gfx/layers/client/TextureClientSharedSurface.cpp index 7aec59290b..58a740035e 100644 --- a/gfx/layers/client/TextureClientSharedSurface.cpp +++ b/gfx/layers/client/TextureClientSharedSurface.cpp @@ -32,7 +32,7 @@ SharedSurfaceTextureData::~SharedSurfaceTextureData() {} void -SharedSurfaceTextureData::Deallocate(ISurfaceAllocator*) +SharedSurfaceTextureData::Deallocate(ClientIPCAllocator*) {} gfx::IntSize @@ -50,7 +50,7 @@ SharedSurfaceTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) SharedSurfaceTextureClient::SharedSurfaceTextureClient(SharedSurfaceTextureData* aData, TextureFlags aFlags, - ISurfaceAllocator* aAllocator) + ClientIPCAllocator* aAllocator) : TextureClient(aData, aFlags, aAllocator) { mWorkaroundAnnoyingSharedSurfaceLifetimeIssues = true; @@ -58,7 +58,7 @@ SharedSurfaceTextureClient::SharedSurfaceTextureClient(SharedSurfaceTextureData* already_AddRefed SharedSurfaceTextureClient::Create(UniquePtr surf, gl::SurfaceFactory* factory, - ISurfaceAllocator* aAllocator, TextureFlags aFlags) + ClientIPCAllocator* aAllocator, TextureFlags aFlags) { if (!surf) { return nullptr; diff --git a/gfx/layers/client/TextureClientSharedSurface.h b/gfx/layers/client/TextureClientSharedSurface.h index 08adecde16..3913737eac 100644 --- a/gfx/layers/client/TextureClientSharedSurface.h +++ b/gfx/layers/client/TextureClientSharedSurface.h @@ -44,7 +44,7 @@ public: virtual void Unlock() override {} - virtual bool HasInternalBuffer() const override { return false; } + virtual bool HasIntermediateBuffer() const override { return false; } virtual gfx::SurfaceFormat GetFormat() const override { return gfx::SurfaceFormat::UNKNOWN; @@ -54,7 +54,7 @@ public: virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override; - virtual void Deallocate(ISurfaceAllocator*) override; + virtual void Deallocate(ClientIPCAllocator*) override; gl::SharedSurface* Surf() const { return mSurf.get(); } }; @@ -64,13 +64,13 @@ class SharedSurfaceTextureClient : public TextureClient public: SharedSurfaceTextureClient(SharedSurfaceTextureData* aData, TextureFlags aFlags, - ISurfaceAllocator* aAllocator); + ClientIPCAllocator* aAllocator); ~SharedSurfaceTextureClient(); static already_AddRefed Create(UniquePtr surf, gl::SurfaceFactory* factory, - ISurfaceAllocator* aAllocator, TextureFlags aFlags); + ClientIPCAllocator* aAllocator, TextureFlags aFlags); virtual void SetReleaseFenceHandle(const FenceHandle& aReleaseFenceHandle) override; diff --git a/gfx/layers/client/TiledContentClient.cpp b/gfx/layers/client/TiledContentClient.cpp index 73ec1f3573..19ea417a4b 100644 --- a/gfx/layers/client/TiledContentClient.cpp +++ b/gfx/layers/client/TiledContentClient.cpp @@ -387,7 +387,7 @@ gfxMemorySharedReadLock::GetReadCount() return mReadCount; } -gfxShmSharedReadLock::gfxShmSharedReadLock(ISurfaceAllocator* aAllocator) +gfxShmSharedReadLock::gfxShmSharedReadLock(ClientIPCAllocator* aAllocator) : mAllocator(aAllocator) , mAllocSuccess(false) { @@ -395,7 +395,8 @@ gfxShmSharedReadLock::gfxShmSharedReadLock(ISurfaceAllocator* aAllocator) MOZ_ASSERT(mAllocator); if (mAllocator) { #define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3) - if (mAllocator->AllocShmemSection(MOZ_ALIGN_WORD(sizeof(ShmReadLockInfo)), &mShmemSection)) { + if (mAllocator->AsLayerForwarder()->GetTileLockAllocator()->AllocShmemSection( + MOZ_ALIGN_WORD(sizeof(ShmReadLockInfo)), &mShmemSection)) { ShmReadLockInfo* info = GetShmReadLockInfoPtr(); info->readCount = 1; mAllocSuccess = true; @@ -427,7 +428,13 @@ gfxShmSharedReadLock::ReadUnlock() { int32_t readCount = PR_ATOMIC_DECREMENT(&info->readCount); MOZ_ASSERT(readCount >= 0); if (readCount <= 0) { - mAllocator->FreeShmemSection(mShmemSection); + auto fwd = mAllocator->AsLayerForwarder(); + if (fwd) { + fwd->GetTileLockAllocator()->DeallocShmemSection(mShmemSection); + } else { + // we are on the compositor process + FixedSizeSmallShmemSectionAllocator::FreeShmemSection(mShmemSection); + } } return readCount; } @@ -725,7 +732,7 @@ TileClient::GetBackBuffer(const nsIntRegion& aDirtyRegion, // Try to re-use the front-buffer if possible bool createdTextureClient = false; if (mFrontBuffer && - mFrontBuffer->HasInternalBuffer() && + mFrontBuffer->HasIntermediateBuffer() && mFrontLock->GetReadCount() == 1 && !(aMode == SurfaceMode::SURFACE_COMPONENT_ALPHA && !mFrontBufferOnWhite)) { // If we had a backbuffer we no longer care about it since we'll @@ -1362,7 +1369,7 @@ ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile, // Note, we don't call UpdatedTexture. The Updated function is called manually // by the TiledContentHost before composition. - if (backBuffer->HasInternalBuffer()) { + if (backBuffer->HasIntermediateBuffer()) { // If our new buffer has an internal buffer, we don't want to keep another // TextureClient around unnecessarily, so discard the back-buffer. aTile.DiscardBackBuffer(); diff --git a/gfx/layers/client/TiledContentClient.h b/gfx/layers/client/TiledContentClient.h index c53b396fa3..ee80c21726 100644 --- a/gfx/layers/client/TiledContentClient.h +++ b/gfx/layers/client/TiledContentClient.h @@ -97,7 +97,7 @@ private: }; public: - explicit gfxShmSharedReadLock(ISurfaceAllocator* aAllocator); + explicit gfxShmSharedReadLock(ClientIPCAllocator* aAllocator); protected: ~gfxShmSharedReadLock(); diff --git a/gfx/layers/composite/ImageHost.cpp b/gfx/layers/composite/ImageHost.cpp index b5d19ad873..81b92cf394 100644 --- a/gfx/layers/composite/ImageHost.cpp +++ b/gfx/layers/composite/ImageHost.cpp @@ -108,7 +108,7 @@ ImageHost::SetCurrentTextureHost(TextureHost* aTexture) } bool swapTextureSources = !!mCurrentTextureHost && !!mCurrentTextureSource - && mCurrentTextureHost->HasInternalBuffer(); + && mCurrentTextureHost->HasIntermediateBuffer(); if (swapTextureSources) { auto dataSource = mCurrentTextureSource->AsDataTextureSource(); diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index 452aa04878..fb2897f154 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -395,14 +395,14 @@ BufferTextureHost::BufferTextureHost(const BufferDescriptor& aDesc, const YCbCrDescriptor& ycbcr = mDescriptor.get_YCbCrDescriptor(); mSize = ycbcr.ySize(); mFormat = gfx::SurfaceFormat::YUV; - mHasInternalBuffer = true; + mHasIntermediateBuffer = true; break; } case BufferDescriptor::TRGBDescriptor: { const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor(); mSize = rgb.size(); mFormat = rgb.format(); - mHasInternalBuffer = rgb.hasInternalBuffer(); + mHasIntermediateBuffer = rgb.hasIntermediateBuffer(); break; } default: MOZ_CRASH(); @@ -496,7 +496,7 @@ BufferTextureHost::Unlock() bool BufferTextureHost::EnsureWrappingTextureSource() { - MOZ_ASSERT(!mHasInternalBuffer); + MOZ_ASSERT(!mHasIntermediateBuffer); MOZ_ASSERT(mFormat != gfx::SurfaceFormat::YUV); if (mFirstSource) { @@ -516,6 +516,16 @@ BufferTextureHost::EnsureWrappingTextureSource() } mFirstSource = mCompositor->CreateDataTextureSourceAround(surf); + if (!mFirstSource) { + // BasicCompositor::CreateDataTextureSourceAround never returns null + // and we don't expect to take this branch if we are using another backend. + // Returning false is fine but if we get into this situation it probably + // means something fishy is going on, like a texture being used with + // several compositor backends. + NS_WARNING("Failed to use a BufferTextureHost without intermediate buffer"); + return false; + } + mFirstSource->SetUpdateSerial(mUpdateSerial); mFirstSource->SetOwner(this); @@ -525,7 +535,7 @@ BufferTextureHost::EnsureWrappingTextureSource() void BufferTextureHost::PrepareTextureSource(CompositableTextureSourceRef& aTexture) { - if (!mHasInternalBuffer) { + if (!mHasIntermediateBuffer) { EnsureWrappingTextureSource(); } @@ -543,9 +553,11 @@ BufferTextureHost::PrepareTextureSource(CompositableTextureSourceRef& aTexture) bool compatibleFormats = texture && (mFormat == texture->GetFormat() || (mFormat == gfx::SurfaceFormat::YUV + && mCompositor && mCompositor->SupportsEffect(EffectTypes::YCBCR) && texture->GetNextSibling()) || (mFormat == gfx::SurfaceFormat::YUV + && mCompositor && !mCompositor->SupportsEffect(EffectTypes::YCBCR) && texture->GetFormat() == gfx::SurfaceFormat::B8G8R8X8)); @@ -557,6 +569,7 @@ BufferTextureHost::PrepareTextureSource(CompositableTextureSourceRef& aTexture) if (!shouldCreateTexture) { mFirstSource = texture; mFirstSource->SetOwner(this); + mNeedsFullUpdate = true; } } @@ -629,7 +642,7 @@ BufferTextureHost::Upload(nsIntRegion *aRegion) // attached to a layer. return false; } - if (!mHasInternalBuffer && EnsureWrappingTextureSource()) { + if (!mHasIntermediateBuffer && EnsureWrappingTextureSource()) { return true; } @@ -788,7 +801,7 @@ ShmemTextureHost::DeallocateSharedData() if (mShmem) { MOZ_ASSERT(mDeallocator, "Shared memory would leak without a ISurfaceAllocator"); - mDeallocator->DeallocShmem(*mShmem); + mDeallocator->AsShmemAllocator()->DeallocShmem(*mShmem); mShmem = nullptr; } } diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 8ce0cb929a..392e888ccf 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -530,7 +530,7 @@ public: * in-memory buffer. The consequence of this is that locking the * TextureHost does not contend with locking the texture on the client side. */ - virtual bool HasInternalBuffer() const { return false; } + virtual bool HasIntermediateBuffer() const { return false; } void AddCompositableRef() { ++mCompositableCount; } @@ -630,7 +630,7 @@ public: virtual already_AddRefed GetAsSurface() override; - virtual bool HasInternalBuffer() const override { return mHasInternalBuffer; } + virtual bool HasIntermediateBuffer() const override { return mHasIntermediateBuffer; } protected: bool Upload(nsIntRegion *aRegion = nullptr); @@ -648,7 +648,7 @@ protected: uint32_t mUpdateSerial; bool mLocked; bool mNeedsFullUpdate; - bool mHasInternalBuffer; + bool mHasIntermediateBuffer; }; /** diff --git a/gfx/layers/composite/TiledContentHost.cpp b/gfx/layers/composite/TiledContentHost.cpp index 9a0b93195b..94cc69d017 100644 --- a/gfx/layers/composite/TiledContentHost.cpp +++ b/gfx/layers/composite/TiledContentHost.cpp @@ -150,7 +150,7 @@ UseTileTexture(CompositableTextureHostRef& aTexture, // We possibly upload the entire texture contents here. This is a purposeful // decision, as sub-image upload can often be slow and/or unreliable, but // we may want to reevaluate this in the future. - // For !HasInternalBuffer() textures, this is likely a no-op. + // For !HasIntermediateBuffer() textures, this is likely a no-op. nsIntRegion region = aUpdateRect; aTexture->Updated(®ion); #endif @@ -368,7 +368,7 @@ TiledLayerBufferComposite::UseTiles(const SurfaceDescriptorTiles& aTiles, aCompositor); } - if (tile.mTextureHost->HasInternalBuffer()) { + if (tile.mTextureHost->HasIntermediateBuffer()) { // Now that we did the texture upload (in UseTileTexture), we can release // the lock. tile.ReadUnlock(); diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index 11f971913e..21d95f07b1 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -362,7 +362,9 @@ D3D11TextureData::Create(IntSize aSize, SurfaceFormat aFormat, TextureAllocation newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; if (!NS_IsMainThread() || !!(aFlags & ALLOC_FOR_OUT_OF_BAND_CONTENT)) { // On the main thread we use the syncobject to handle synchronization. - newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; + if (!(aFlags & ALLOC_MANUAL_SYNCHRONIZATION)) { + newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; + } } HRESULT hr = d3d11device->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(texture11)); @@ -380,7 +382,7 @@ D3D11TextureData::Create(IntSize aSize, SurfaceFormat aFormat, TextureAllocation } void -D3D11TextureData::Deallocate(ISurfaceAllocator* aAllocator) +D3D11TextureData::Deallocate(ClientIPCAllocator* aAllocator) { mTexture = nullptr; } @@ -389,7 +391,7 @@ already_AddRefed CreateD3D11TextureClientWithDevice(IntSize aSize, SurfaceFormat aFormat, TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags, ID3D11Device* aDevice, - ISurfaceAllocator* aAllocator) + ClientIPCAllocator* aAllocator) { TextureData* data = D3D11TextureData::Create(aSize, aFormat, aAllocFlags, aDevice); if (!data) { @@ -399,7 +401,7 @@ CreateD3D11TextureClientWithDevice(IntSize aSize, SurfaceFormat aFormat, } TextureData* -D3D11TextureData::CreateSimilar(ISurfaceAllocator* aAllocator, +D3D11TextureData::CreateSimilar(ClientIPCAllocator* aAllocator, TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const { @@ -413,7 +415,7 @@ D3D11TextureData::GetDXGIResource(IDXGIResource** aOutResource) } DXGIYCbCrTextureData* -DXGIYCbCrTextureData::Create(ISurfaceAllocator* aAllocator, +DXGIYCbCrTextureData::Create(ClientIPCAllocator* aAllocator, TextureFlags aFlags, IUnknown* aTextureY, IUnknown* aTextureCb, @@ -445,7 +447,7 @@ DXGIYCbCrTextureData::Create(ISurfaceAllocator* aAllocator, } DXGIYCbCrTextureData* -DXGIYCbCrTextureData::Create(ISurfaceAllocator* aAllocator, +DXGIYCbCrTextureData::Create(ClientIPCAllocator* aAllocator, TextureFlags aFlags, ID3D11Texture2D* aTextureY, ID3D11Texture2D* aTextureCb, @@ -507,7 +509,7 @@ DXGIYCbCrTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) } void -DXGIYCbCrTextureData::Deallocate(ISurfaceAllocator*) +DXGIYCbCrTextureData::Deallocate(ClientIPCAllocator*) { mHoldRefs[0] = nullptr; mHoldRefs[1] = nullptr; diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h index cb7b9dc503..3d28217a75 100644 --- a/gfx/layers/d3d11/TextureD3D11.h +++ b/gfx/layers/d3d11/TextureD3D11.h @@ -30,7 +30,7 @@ public: virtual bool SupportsMoz2D() const override { return true; } - virtual bool HasInternalBuffer() const override { return false; } + virtual bool HasIntermediateBuffer() const override { return false; } virtual bool HasSynchronization() const override { return mHasSynchronization; } @@ -76,7 +76,7 @@ public: virtual already_AddRefed BorrowDrawTarget() override; virtual TextureData* - CreateSimilar(ISurfaceAllocator* aAllocator, + CreateSimilar(ClientIPCAllocator* aAllocator, TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const override; @@ -85,7 +85,7 @@ public: ID3D11Texture2D* GetD3D11Texture() { return mTexture; } - virtual void Deallocate(ISurfaceAllocator* aAllocator) override; + virtual void Deallocate(ClientIPCAllocator* aAllocator) override; D3D11TextureData* AsD3D11TextureData() override { return this; @@ -107,13 +107,13 @@ already_AddRefed CreateD3D11extureClientWithDevice(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags, ID3D11Device* aDevice, - ISurfaceAllocator* aAllocator); + ClientIPCAllocator* aAllocator); class DXGIYCbCrTextureData : public TextureData { public: static DXGIYCbCrTextureData* - Create(ISurfaceAllocator* aAllocator, + Create(ClientIPCAllocator* aAllocator, TextureFlags aFlags, IUnknown* aTextureY, IUnknown* aTextureCb, @@ -126,7 +126,7 @@ public: const gfx::IntSize& aSizeCbCr); static DXGIYCbCrTextureData* - Create(ISurfaceAllocator* aAllocator, + Create(ClientIPCAllocator* aAllocator, TextureFlags aFlags, ID3D11Texture2D* aTextureCb, ID3D11Texture2D* aTextureY, @@ -142,7 +142,7 @@ public: virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override; // TODO - DXGIYCbCrTextureClient returned true but that looks like a mistake - virtual bool HasInternalBuffer() const override{ return false; } + virtual bool HasIntermediateBuffer() const override{ return false; } virtual gfx::IntSize GetSize() const override { return mSize; } @@ -156,9 +156,9 @@ public: // (ex. component alpha) because the underlying texture is always created by // an external producer. virtual DXGIYCbCrTextureData* - CreateSimilar(ISurfaceAllocator*, TextureFlags, TextureAllocationFlags) const override { return nullptr; } + CreateSimilar(ClientIPCAllocator*, TextureFlags, TextureAllocationFlags) const override { return nullptr; } - virtual void Deallocate(ISurfaceAllocator* aAllocator) override; + virtual void Deallocate(ClientIPCAllocator* aAllocator) override; virtual bool UpdateFromSurface(gfx::SourceSurface*) override { return false; } @@ -278,7 +278,7 @@ already_AddRefed CreateD3D11TextureClientWithDevice(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags, ID3D11Device* aDevice, - ISurfaceAllocator* aAllocator); + ClientIPCAllocator* aAllocator); /** diff --git a/gfx/layers/d3d9/TextureD3D9.cpp b/gfx/layers/d3d9/TextureD3D9.cpp index fdf97e3658..975167913b 100644 --- a/gfx/layers/d3d9/TextureD3D9.cpp +++ b/gfx/layers/d3d9/TextureD3D9.cpp @@ -576,7 +576,7 @@ D3D9TextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, } TextureData* -D3D9TextureData::CreateSimilar(ISurfaceAllocator*, TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const +D3D9TextureData::CreateSimilar(ClientIPCAllocator*, TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const { return D3D9TextureData::Create(mSize, mFormat, aAllocFlags); } diff --git a/gfx/layers/d3d9/TextureD3D9.h b/gfx/layers/d3d9/TextureD3D9.h index 4e341463a1..83ac94ad72 100644 --- a/gfx/layers/d3d9/TextureD3D9.h +++ b/gfx/layers/d3d9/TextureD3D9.h @@ -184,7 +184,7 @@ public: virtual bool SupportsMoz2D() const override { return true; } - virtual bool HasInternalBuffer() const override { return true; } + virtual bool HasIntermediateBuffer() const override { return true; } virtual bool Serialize(SurfaceDescriptor& aOutDescrptor) override; @@ -201,14 +201,14 @@ public: virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override; virtual TextureData* - CreateSimilar(ISurfaceAllocator* aAllocator, + CreateSimilar(ClientIPCAllocator* aAllocator, TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const override; static D3D9TextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureAllocationFlags aFlags); - virtual void Deallocate(ISurfaceAllocator* aAllocator) override {} + virtual void Deallocate(ClientIPCAllocator* aAllocator) override {} protected: D3D9TextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, @@ -246,9 +246,9 @@ public: virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override; - virtual bool HasInternalBuffer() const override { return false; } + virtual bool HasIntermediateBuffer() const override { return false; } - virtual void Deallocate(ISurfaceAllocator* aAllocator) override {} + virtual void Deallocate(ClientIPCAllocator* aAllocator) override {} IDirect3DDevice9* GetD3D9Device() { return mDevice; } IDirect3DTexture9* GetD3D9Texture() { return mTexture; } @@ -297,7 +297,7 @@ public: return nullptr; } - virtual bool HasInternalBuffer() const override { return true; } + virtual bool HasIntermediateBuffer() const override { return true; } protected: TextureHostD3D9(TextureFlags aFlags); diff --git a/gfx/layers/ipc/AsyncTransactionTracker.cpp b/gfx/layers/ipc/AsyncTransactionTracker.cpp index 9cb8fd5296..a81a755732 100755 --- a/gfx/layers/ipc/AsyncTransactionTracker.cpp +++ b/gfx/layers/ipc/AsyncTransactionTracker.cpp @@ -42,7 +42,9 @@ Mutex* AsyncTransactionTracker::sLock = nullptr; AsyncTransactionTracker::AsyncTransactionTracker(AsyncTransactionWaiter* aWaiter) : mSerial(GetNextSerial()) , mWaiter(aWaiter) +#ifdef DEBUG , mCompleted(false) +#endif { if (mWaiter) { mWaiter->IncrementWaitCount(); @@ -57,7 +59,9 @@ void AsyncTransactionTracker::NotifyComplete() { MOZ_ASSERT(!mCompleted); +#ifdef DEBUG mCompleted = true; +#endif Complete(); if (mWaiter) { mWaiter->DecrementWaitCount(); @@ -68,7 +72,9 @@ void AsyncTransactionTracker::NotifyCancel() { MOZ_ASSERT(!mCompleted); +#ifdef DEBUG mCompleted = true; +#endif Cancel(); if (mWaiter) { mWaiter->DecrementWaitCount(); diff --git a/gfx/layers/ipc/AsyncTransactionTracker.h b/gfx/layers/ipc/AsyncTransactionTracker.h index 67ce861776..f319e08ca0 100644 --- a/gfx/layers/ipc/AsyncTransactionTracker.h +++ b/gfx/layers/ipc/AsyncTransactionTracker.h @@ -131,7 +131,9 @@ protected: uint64_t mSerial; RefPtr mWaiter; - DebugOnly mCompleted; +#ifdef DEBUG + bool mCompleted; +#endif /** * gecko does not provide atomic operation for uint64_t. diff --git a/gfx/layers/ipc/CompositableForwarder.h b/gfx/layers/ipc/CompositableForwarder.h index dcefb0ce18..6be22f77e1 100644 --- a/gfx/layers/ipc/CompositableForwarder.h +++ b/gfx/layers/ipc/CompositableForwarder.h @@ -40,7 +40,7 @@ class PTextureChild; * additionally forward modifications of the Layer tree). * ImageBridgeChild is another CompositableForwarder. */ -class CompositableForwarder : public ISurfaceAllocator +class CompositableForwarder : public ClientIPCAllocator { public: @@ -144,8 +144,6 @@ public: return mTextureFactoryIdentifier.mMaxTextureSize; } - bool IsOnCompositorSide() const override { return false; } - /** * Returns the type of backend that is used off the main thread. * We only don't allow changing the backend type at runtime so this value can diff --git a/gfx/layers/ipc/CompositableTransactionParent.cpp b/gfx/layers/ipc/CompositableTransactionParent.cpp index ff5f887e33..c585680c51 100644 --- a/gfx/layers/ipc/CompositableTransactionParent.cpp +++ b/gfx/layers/ipc/CompositableTransactionParent.cpp @@ -144,7 +144,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation MOZ_ASSERT(tex.get()); compositable->RemoveTextureHost(tex); - if (!IsAsync() && ImageBridgeParent::GetInstance(GetChildProcessId())) { + if (!UsesImageBridge() && ImageBridgeParent::GetInstance(GetChildProcessId())) { // send FenceHandle if present via ImageBridge. ImageBridgeParent::AppendDeliverFenceMessage( GetChildProcessId(), @@ -195,7 +195,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation } compositable->UseTextureHost(textures); - if (IsAsync() && compositable->GetLayer()) { + if (UsesImageBridge() && compositable->GetLayer()) { ScheduleComposition(op); } break; @@ -209,7 +209,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation MOZ_ASSERT(texOnBlack && texOnWhite); compositable->UseComponentAlphaTextures(texOnBlack, texOnWhite); - if (IsAsync()) { + if (UsesImageBridge()) { ScheduleComposition(op); } break; diff --git a/gfx/layers/ipc/CompositableTransactionParent.h b/gfx/layers/ipc/CompositableTransactionParent.h index e98b244b3e..e6c8da760c 100644 --- a/gfx/layers/ipc/CompositableTransactionParent.h +++ b/gfx/layers/ipc/CompositableTransactionParent.h @@ -49,14 +49,6 @@ protected: bool ReceiveCompositableUpdate(const CompositableOperation& aEdit, EditReplyVector& replyv); - bool IsOnCompositorSide() const override { return true; } - - /** - * Return true if this protocol is asynchronous with respect to the content - * thread (ImageBridge for instance). - */ - virtual bool IsAsync() const { return false; } - virtual void ReplyRemoveTexture(const OpReplyRemoveTexture& aReply) {} std::vector mPendingAsyncMessage; diff --git a/gfx/layers/ipc/ISurfaceAllocator.cpp b/gfx/layers/ipc/ISurfaceAllocator.cpp index 94255a6441..4ac2a51d6b 100644 --- a/gfx/layers/ipc/ISurfaceAllocator.cpp +++ b/gfx/layers/ipc/ISurfaceAllocator.cpp @@ -6,27 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ISurfaceAllocator.h" -#include // for int32_t -#include "gfx2DGlue.h" // for IntSize -#include "gfxPlatform.h" // for gfxPlatform, gfxImageFormat -#include "gfxSharedImageSurface.h" // for gfxSharedImageSurface -#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc -#include "mozilla/Atomics.h" // for PrimitiveIntrinsics -#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc -#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc -#include "mozilla/layers/SharedBufferManagerChild.h" -#include "ShadowLayerUtils.h" -#include "mozilla/mozalloc.h" // for operator delete[], etc -#include "nsAutoPtr.h" // for nsRefPtr, getter_AddRefs, etc -#include "nsDebug.h" // for NS_RUNTIMEABORT -#include "nsXULAppAPI.h" // for XRE_GetProcessType, etc -#include "mozilla/ipc/Shmem.h" -#include "mozilla/layers/ImageDataSerializer.h" -#ifdef DEBUG -#include "prenv.h" -#endif - -using namespace mozilla::ipc; namespace mozilla { namespace layers { @@ -37,355 +16,7 @@ mozilla::Atomic GfxMemoryImageReporter::sAmount(0); mozilla::ipc::SharedMemory::SharedMemoryType OptimalShmemType() { - return mozilla::ipc::SharedMemory::TYPE_BASIC; -} - -bool -IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface) -{ - return aSurface.type() != SurfaceDescriptor::T__None && - aSurface.type() != SurfaceDescriptor::Tnull_t; -} - -ISurfaceAllocator::~ISurfaceAllocator() -{ - // Check if we're not leaking.. - MOZ_ASSERT(mUsedShmems.empty()); -} - -void -ISurfaceAllocator::Finalize() -{ - ShrinkShmemSectionHeap(); -} - -static inline uint8_t* -GetAddressFromDescriptor(const SurfaceDescriptor& aDescriptor) -{ - MOZ_ASSERT(IsSurfaceDescriptorValid(aDescriptor)); - MOZ_RELEASE_ASSERT(aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorBuffer); - - auto memOrShmem = aDescriptor.get_SurfaceDescriptorBuffer().data(); - if (memOrShmem.type() == MemoryOrShmem::TShmem) { - return memOrShmem.get_Shmem().get(); - } else { - return reinterpret_cast(memOrShmem.get_uintptr_t()); - } -} - -already_AddRefed -GetDrawTargetForDescriptor(const SurfaceDescriptor& aDescriptor, gfx::BackendType aBackend) -{ - uint8_t* data = GetAddressFromDescriptor(aDescriptor); - auto rgb = aDescriptor.get_SurfaceDescriptorBuffer().desc().get_RGBDescriptor(); - uint32_t stride = ImageDataSerializer::GetRGBStride(rgb); - return gfx::Factory::CreateDrawTargetForData(gfx::BackendType::CAIRO, - data, rgb.size(), - stride, rgb.format()); -} - -already_AddRefed -GetSurfaceForDescriptor(const SurfaceDescriptor& aDescriptor) -{ - uint8_t* data = GetAddressFromDescriptor(aDescriptor); - auto rgb = aDescriptor.get_SurfaceDescriptorBuffer().desc().get_RGBDescriptor(); - uint32_t stride = ImageDataSerializer::GetRGBStride(rgb); - return gfx::Factory::CreateWrappingDataSourceSurface(data, stride, rgb.size(), - rgb.format()); -} - -bool -ISurfaceAllocator::AllocSurfaceDescriptor(const gfx::IntSize& aSize, - gfxContentType aContent, - SurfaceDescriptor* aBuffer) -{ - if (!IPCOpen()) { - return false; - } - return AllocSurfaceDescriptorWithCaps(aSize, aContent, DEFAULT_BUFFER_CAPS, aBuffer); -} - -bool -ISurfaceAllocator::AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize, - gfxContentType aContent, - uint32_t aCaps, - SurfaceDescriptor* aBuffer) -{ - if (!IPCOpen()) { - return false; - } - gfx::SurfaceFormat format = - gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aContent); - size_t size = ImageDataSerializer::ComputeRGBBufferSize(aSize, format); - if (!size) { - return false; - } - - MemoryOrShmem bufferDesc; - if (IsSameProcess()) { - uint8_t* data = new (std::nothrow) uint8_t[size]; - if (!data) { - return false; - } - GfxMemoryImageReporter::DidAlloc(data); -#ifdef XP_MACOSX - // Workaround a bug in Quartz where drawing an a8 surface to another a8 - // surface with OP_SOURCE still requires the destination to be clear. - if (format == gfx::SurfaceFormat::A8) { - memset(data, 0, size); - } -#endif - bufferDesc = reinterpret_cast(data); - } else { - - mozilla::ipc::SharedMemory::SharedMemoryType shmemType = OptimalShmemType(); - mozilla::ipc::Shmem shmem; - if (!AllocUnsafeShmem(size, shmemType, &shmem)) { - return false; - } - - bufferDesc = shmem; - } - - // Use an intermediate buffer by default. Skipping the intermediate buffer is - // only possible in certain configurations so let's keep it simple here for now. - const bool hasIntermediateBuffer = true; - *aBuffer = SurfaceDescriptorBuffer(RGBDescriptor(aSize, format, hasIntermediateBuffer), - bufferDesc); - - return true; -} - -/* static */ bool -ISurfaceAllocator::IsShmem(SurfaceDescriptor* aSurface) -{ - return aSurface && (aSurface->type() == SurfaceDescriptor::TSurfaceDescriptorBuffer) - && (aSurface->get_SurfaceDescriptorBuffer().data().type() == MemoryOrShmem::TShmem); -} - -void -ISurfaceAllocator::DestroySharedSurface(SurfaceDescriptor* aSurface) -{ - MOZ_ASSERT(IPCOpen()); - if (!IPCOpen()) { - return; - } - - MOZ_ASSERT(aSurface); - if (!aSurface) { - return; - } - if (!IPCOpen()) { - return; - } - SurfaceDescriptorBuffer& desc = aSurface->get_SurfaceDescriptorBuffer(); - switch (desc.data().type()) { - case MemoryOrShmem::TShmem: { - DeallocShmem(desc.data().get_Shmem()); - break; - } - case MemoryOrShmem::Tuintptr_t: { - uint8_t* ptr = (uint8_t*)desc.data().get_uintptr_t(); - GfxMemoryImageReporter::WillFree(ptr); - delete [] ptr; - break; - } - default: - NS_RUNTIMEABORT("surface type not implemented!"); - } - *aSurface = SurfaceDescriptor(); -} - -// XXX - We should actually figure out the minimum shmem allocation size on -// a certain platform and use that. -const uint32_t sShmemPageSize = 4096; - -#ifdef DEBUG -const uint32_t sSupportedBlockSize = 4; -#endif - -enum AllocationStatus -{ - STATUS_ALLOCATED, - STATUS_FREED -}; - -struct ShmemSectionHeapHeader -{ - Atomic mTotalBlocks; - Atomic mAllocatedBlocks; -}; - -struct ShmemSectionHeapAllocation -{ - Atomic mStatus; - uint32_t mSize; -}; - -bool -ISurfaceAllocator::AllocShmemSection(size_t aSize, mozilla::layers::ShmemSection* aShmemSection) -{ - MOZ_ASSERT(IPCOpen()); - if (!IPCOpen()) { - return false; - } - // For now we only support sizes of 4. If we want to support different sizes - // some more complicated bookkeeping should be added. - MOZ_ASSERT(aSize == sSupportedBlockSize); - MOZ_ASSERT(aShmemSection); - - uint32_t allocationSize = (aSize + sizeof(ShmemSectionHeapAllocation)); - - for (size_t i = 0; i < mUsedShmems.size(); i++) { - ShmemSectionHeapHeader* header = mUsedShmems[i].get(); - if ((header->mAllocatedBlocks + 1) * allocationSize + sizeof(ShmemSectionHeapHeader) < sShmemPageSize) { - aShmemSection->shmem() = mUsedShmems[i]; - MOZ_ASSERT(mUsedShmems[i].IsWritable()); - break; - } - } - - if (!aShmemSection->shmem().IsWritable()) { - ipc::Shmem tmp; - if (!AllocUnsafeShmem(sShmemPageSize, ipc::SharedMemory::TYPE_BASIC, &tmp)) { - return false; - } - - ShmemSectionHeapHeader* header = tmp.get(); - header->mTotalBlocks = 0; - header->mAllocatedBlocks = 0; - - mUsedShmems.push_back(tmp); - aShmemSection->shmem() = tmp; - } - - MOZ_ASSERT(aShmemSection->shmem().IsWritable()); - - ShmemSectionHeapHeader* header = aShmemSection->shmem().get(); - uint8_t* heap = aShmemSection->shmem().get() + sizeof(ShmemSectionHeapHeader); - - ShmemSectionHeapAllocation* allocHeader = nullptr; - - if (header->mTotalBlocks > header->mAllocatedBlocks) { - // Search for the first available block. - for (size_t i = 0; i < header->mTotalBlocks; i++) { - allocHeader = reinterpret_cast(heap); - - if (allocHeader->mStatus == STATUS_FREED) { - break; - } - heap += allocationSize; - } - MOZ_ASSERT(allocHeader && allocHeader->mStatus == STATUS_FREED); - MOZ_ASSERT(allocHeader->mSize == sSupportedBlockSize); - } else { - heap += header->mTotalBlocks * allocationSize; - - header->mTotalBlocks++; - allocHeader = reinterpret_cast(heap); - allocHeader->mSize = aSize; - } - - MOZ_ASSERT(allocHeader); - header->mAllocatedBlocks++; - allocHeader->mStatus = STATUS_ALLOCATED; - - aShmemSection->size() = aSize; - aShmemSection->offset() = (heap + sizeof(ShmemSectionHeapAllocation)) - aShmemSection->shmem().get(); - ShrinkShmemSectionHeap(); - return true; -} - -void -ISurfaceAllocator::FreeShmemSection(mozilla::layers::ShmemSection& aShmemSection) -{ - MOZ_ASSERT(IPCOpen()); - if (!IPCOpen()) { - return; - } - - MOZ_ASSERT(aShmemSection.size() == sSupportedBlockSize); - MOZ_ASSERT(aShmemSection.offset() < sShmemPageSize - sSupportedBlockSize); - - ShmemSectionHeapAllocation* allocHeader = - reinterpret_cast(aShmemSection.shmem().get() + - aShmemSection.offset() - - sizeof(ShmemSectionHeapAllocation)); - - MOZ_ASSERT(allocHeader->mSize == aShmemSection.size()); - - DebugOnly success = allocHeader->mStatus.compareExchange(STATUS_ALLOCATED, STATUS_FREED); - // If this fails something really weird is going on. - MOZ_ASSERT(success); - - ShmemSectionHeapHeader* header = aShmemSection.shmem().get(); - header->mAllocatedBlocks--; - - ShrinkShmemSectionHeap(); -} - - -void -ISurfaceAllocator::ShrinkShmemSectionHeap() -{ - if (!IPCOpen()) { - return; - } - - // The loop will terminate as we either increase i, or decrease size - // every time through. - size_t i = 0; - while (i < mUsedShmems.size()) { - ShmemSectionHeapHeader* header = mUsedShmems[i].get(); - if (header->mAllocatedBlocks == 0) { - DeallocShmem(mUsedShmems[i]); - - // We don't particularly care about order, move the last one in the array - // to this position. - if (i < mUsedShmems.size() - 1) { - mUsedShmems[i] = mUsedShmems[mUsedShmems.size() - 1]; - } - mUsedShmems.pop_back(); - } else { - i++; - } - } -} - -bool -ISurfaceAllocator::AllocGrallocBuffer(const gfx::IntSize& aSize, - uint32_t aFormat, - uint32_t aUsage, - MaybeMagicGrallocBufferHandle* aHandle) -{ - MOZ_ASSERT(IPCOpen()); - if (!IPCOpen()) { - return false; - } - - return SharedBufferManagerChild::GetSingleton()->AllocGrallocBuffer(aSize, aFormat, aUsage, aHandle); -} - -void -ISurfaceAllocator::DeallocGrallocBuffer(MaybeMagicGrallocBufferHandle* aHandle) -{ - MOZ_ASSERT(IPCOpen()); - if (!IPCOpen()) { - return; - } - - SharedBufferManagerChild::GetSingleton()->DeallocGrallocBuffer(*aHandle); -} - -void -ISurfaceAllocator::DropGrallocBuffer(MaybeMagicGrallocBufferHandle* aHandle) -{ - MOZ_ASSERT(IPCOpen()); - if (!IPCOpen()) { - return; - } - - SharedBufferManagerChild::GetSingleton()->DropGrallocBuffer(*aHandle); + return ipc::SharedMemory::SharedMemoryType::TYPE_BASIC; } } // namespace layers diff --git a/gfx/layers/ipc/ISurfaceAllocator.h b/gfx/layers/ipc/ISurfaceAllocator.h index beca501b2b..ba87f972f3 100644 --- a/gfx/layers/ipc/ISurfaceAllocator.h +++ b/gfx/layers/ipc/ISurfaceAllocator.h @@ -16,11 +16,12 @@ #include "mozilla/Atomics.h" // for Atomic #include "mozilla/layers/LayersMessages.h" // for ShmemSection #include "LayersTypes.h" -#include +#include "gfxPrefs.h" #include "mozilla/layers/AtomicRefCountedWithFinalize.h" /* * FIXME [bjacob] *** PURE CRAZYNESS WARNING *** + * (I think that this doesn't apply anymore.) * * This #define is actually needed here, because subclasses of ISurfaceAllocator, * namely ShadowLayerForwarder, will or will not override AllocGrallocBuffer @@ -40,8 +41,13 @@ class DataSourceSurface; namespace layers { -class MaybeMagicGrallocBufferHandle; class CompositableForwarder; +class ShadowLayerForwarder; + +class ShmemAllocator; +class ShmemSectionAllocator; +class LegacySurfaceDescriptorAllocator; +class ClientIPCAllocator; enum BufferCapabilities { DEFAULT_BUFFER_CAPS = 0, @@ -59,12 +65,7 @@ class SurfaceDescriptor; mozilla::ipc::SharedMemory::SharedMemoryType OptimalShmemType(); -bool IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface); -bool IsSurfaceDescriptorOwned(const SurfaceDescriptor& aDescriptor); -bool ReleaseOwnedSurfaceDescriptor(const SurfaceDescriptor& aDescriptor); -already_AddRefed GetDrawTargetForDescriptor(const SurfaceDescriptor& aDescriptor, gfx::BackendType aBackend); -already_AddRefed GetSurfaceForDescriptor(const SurfaceDescriptor& aDescriptor); /** * An interface used to create and destroy surfaces that are shared with the * Compositor process (using shmem, or gralloc, or other platform specific memory) @@ -78,106 +79,106 @@ class ISurfaceAllocator : public AtomicRefCountedWithFinalize { public: MOZ_DECLARE_REFCOUNTED_TYPENAME(ISurfaceAllocator) - ISurfaceAllocator() - : mDefaultMessageLoop(MessageLoop::current()) - {} - void Finalize(); + // down-casting - /** - * Allocate shared memory that can be accessed by only one process at a time. - * Ownership of this memory is passed when the memory is sent in an IPDL - * message. - */ - virtual bool AllocShmem(size_t aSize, - mozilla::ipc::SharedMemory::SharedMemoryType aType, - mozilla::ipc::Shmem* aShmem) = 0; + virtual ShmemAllocator* AsShmemAllocator() { return nullptr; } - /** - * Allocate shared memory that can be accessed by both processes at the - * same time. Safety is left for the user of the memory to care about. - */ - virtual bool AllocUnsafeShmem(size_t aSize, - mozilla::ipc::SharedMemory::SharedMemoryType aType, - mozilla::ipc::Shmem* aShmem) = 0; - - /** - * Allocate memory in shared memory that can always be accessed by both - * processes at a time. Safety is left for the user of the memory to care - * about. - */ - bool AllocShmemSection(size_t aSize, - mozilla::layers::ShmemSection* aShmemSection); - - /** - * Deallocates a shmem section. - */ - void FreeShmemSection(mozilla::layers::ShmemSection& aShmemSection); - - /** - * Deallocate memory allocated by either AllocShmem or AllocUnsafeShmem. - */ - virtual void DeallocShmem(mozilla::ipc::Shmem& aShmem) = 0; - - // was AllocBuffer - virtual bool AllocSurfaceDescriptor(const gfx::IntSize& aSize, - gfxContentType aContent, - SurfaceDescriptor* aBuffer); - - // was AllocBufferWithCaps - virtual bool AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize, - gfxContentType aContent, - uint32_t aCaps, - SurfaceDescriptor* aBuffer); - - /** - * Returns the maximum texture size supported by the compositor. - */ - virtual int32_t GetMaxTextureSize() const { return INT32_MAX; } - - virtual void DestroySharedSurface(SurfaceDescriptor* aSurface); - - // method that does the actual allocation work - bool AllocGrallocBuffer(const gfx::IntSize& aSize, - uint32_t aFormat, - uint32_t aUsage, - MaybeMagicGrallocBufferHandle* aHandle); - - void DeallocGrallocBuffer(MaybeMagicGrallocBufferHandle* aHandle); - - void DropGrallocBuffer(MaybeMagicGrallocBufferHandle* aHandle); - - virtual bool IPCOpen() const { return true; } - virtual bool IsSameProcess() const = 0; - virtual base::ProcessId ParentPid() const { return base::ProcessId(); } - - virtual bool IsImageBridgeChild() const { return false; } - - virtual MessageLoop * GetMessageLoop() const - { - return mDefaultMessageLoop; - } - - // Returns true if aSurface wraps a Shmem. - static bool IsShmem(SurfaceDescriptor* aSurface); + virtual ShmemSectionAllocator* AsShmemSectionAllocator() { return nullptr; } virtual CompositableForwarder* AsCompositableForwarder() { return nullptr; } + + virtual ShadowLayerForwarder* AsLayerForwarder() { return nullptr; } + + virtual ClientIPCAllocator* AsClientAllocator() { return nullptr; } + + virtual LegacySurfaceDescriptorAllocator* + AsLegacySurfaceDescriptorAllocator() { return nullptr; } + + // ipc info + + virtual bool IPCOpen() const { return true; } + + virtual bool IsSameProcess() const = 0; + + virtual bool UsesImageBridge() const { return false; } + protected: + void Finalize() {} - virtual bool IsOnCompositorSide() const = 0; - - virtual ~ISurfaceAllocator(); - - void ShrinkShmemSectionHeap(); - - // This is used to implement an extremely simple & naive heap allocator. - std::vector mUsedShmems; - - MessageLoop* mDefaultMessageLoop; + virtual ~ISurfaceAllocator() {} friend class AtomicRefCountedWithFinalize; }; +/// Methods that are specific to the client/child side. +class ClientIPCAllocator : public ISurfaceAllocator +{ +public: + virtual ClientIPCAllocator* AsClientAllocator() override { return this; } + + virtual MessageLoop * GetMessageLoop() const = 0; + + virtual int32_t GetMaxTextureSize() const { return gfxPrefs::MaxTextureSize(); } +}; + +/// An allocator can provide shared memory. +/// +/// The allocated shmems can be deallocated on either process, as long as they +/// belong to the same channel. +class ShmemAllocator +{ +public: + virtual bool AllocShmem(size_t aSize, + mozilla::ipc::SharedMemory::SharedMemoryType aShmType, + mozilla::ipc::Shmem* aShmem) = 0; + virtual bool AllocUnsafeShmem(size_t aSize, + mozilla::ipc::SharedMemory::SharedMemoryType aShmType, + mozilla::ipc::Shmem* aShmem) = 0; + virtual void DeallocShmem(mozilla::ipc::Shmem& aShmem) = 0; +}; + +/// An allocator that can group allocations in bigger chunks of shared memory. +/// +/// The allocated shmem sections can only be deallocated by the same allocator +/// instance (and only in the child process). +class ShmemSectionAllocator +{ +public: + virtual bool AllocShmemSection(uint32_t aSize, ShmemSection* aShmemSection) = 0; + + virtual void DeallocShmemSection(ShmemSection& aShmemSection) = 0; + + virtual void MemoryPressure() {} +}; + +/// Some old stuff that's still around and used for screenshots. +/// +/// New code should not need this (see TextureClient). +class LegacySurfaceDescriptorAllocator +{ +public: + virtual bool AllocSurfaceDescriptor(const gfx::IntSize& aSize, + gfxContentType aContent, + SurfaceDescriptor* aBuffer) = 0; + + virtual bool AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize, + gfxContentType aContent, + uint32_t aCaps, + SurfaceDescriptor* aBuffer) = 0; + + virtual void DestroySurfaceDescriptor(SurfaceDescriptor* aSurface) = 0; +}; + +already_AddRefed +GetDrawTargetForDescriptor(const SurfaceDescriptor& aDescriptor, gfx::BackendType aBackend); + +already_AddRefed +GetSurfaceForDescriptor(const SurfaceDescriptor& aDescriptor); + +uint8_t* +GetAddressFromDescriptor(const SurfaceDescriptor& aDescriptor); + class GfxMemoryImageReporter final : public nsIMemoryReporter { ~GfxMemoryImageReporter() {} diff --git a/gfx/layers/ipc/ImageBridgeChild.cpp b/gfx/layers/ipc/ImageBridgeChild.cpp index c030a6db69..7591651c15 100644 --- a/gfx/layers/ipc/ImageBridgeChild.cpp +++ b/gfx/layers/ipc/ImageBridgeChild.cpp @@ -904,7 +904,8 @@ ImageBridgeChild::AllocShmem(size_t aSize, { MOZ_ASSERT(!mShuttingDown); if (InImageBridgeChildThread()) { - return PImageBridgeChild::AllocShmem(aSize, aType, aShmem); + return PImageBridgeChild::AllocShmem(aSize, aType, + aShmem); } else { return DispatchAllocShmemInternal(aSize, aType, aShmem, false); // false: unsafe } @@ -929,14 +930,15 @@ static void ProxyAllocShmemNow(AllocShmemParams* aParams, MOZ_ASSERT(aDone); MOZ_ASSERT(aBarrier); + auto shmAllocator = aParams->mAllocator->AsShmemAllocator(); if (aParams->mUnsafe) { - aParams->mSuccess = aParams->mAllocator->AllocUnsafeShmem(aParams->mSize, - aParams->mType, - aParams->mShmem); + aParams->mSuccess = shmAllocator->AllocUnsafeShmem(aParams->mSize, + aParams->mType, + aParams->mShmem); } else { - aParams->mSuccess = aParams->mAllocator->AllocShmem(aParams->mSize, - aParams->mType, - aParams->mShmem); + aParams->mSuccess = shmAllocator->AllocShmem(aParams->mSize, + aParams->mType, + aParams->mShmem); } ReentrantMonitorAutoEnter autoMon(*aBarrier); @@ -978,7 +980,7 @@ static void ProxyDeallocShmemNow(ISurfaceAllocator* aAllocator, MOZ_ASSERT(aDone); MOZ_ASSERT(aBarrier); - aAllocator->DeallocShmem(*aShmem); + aAllocator->AsShmemAllocator()->DeallocShmem(*aShmem); ReentrantMonitorAutoEnter autoMon(*aBarrier); *aDone = true; diff --git a/gfx/layers/ipc/ImageBridgeChild.h b/gfx/layers/ipc/ImageBridgeChild.h index 809a092314..9a412a17c2 100644 --- a/gfx/layers/ipc/ImageBridgeChild.h +++ b/gfx/layers/ipc/ImageBridgeChild.h @@ -104,11 +104,14 @@ bool InImageBridgeChildThread(); class ImageBridgeChild final : public PImageBridgeChild , public CompositableForwarder , public AsyncTransactionTrackersHolder + , public ShmemAllocator { friend class ImageContainer; typedef InfallibleTArray AsyncParentMessageArray; public: + virtual ShmemAllocator* AsShmemAllocator() override { return this; } + /** * Creates the image bridge with a dedicated thread for ImageBridgeChild. * @@ -236,7 +239,7 @@ public: virtual void Connect(CompositableClient* aCompositable, ImageContainer* aImageContainer) override; - virtual bool IsImageBridgeChild() const override { return true; } + virtual bool UsesImageBridge() const override { return true; } /** * See CompositableForwarder::UseTextures @@ -283,17 +286,12 @@ public: * call on the ImageBridgeChild thread. */ virtual bool AllocUnsafeShmem(size_t aSize, - mozilla::ipc::SharedMemory::SharedMemoryType aType, + mozilla::ipc::SharedMemory::SharedMemoryType aShmType, mozilla::ipc::Shmem* aShmem) override; - /** - * See ISurfaceAllocator.h - * Can be used from any thread. - * If used outside the ImageBridgeChild thread, it will proxy a synchronous - * call on the ImageBridgeChild thread. - */ virtual bool AllocShmem(size_t aSize, - mozilla::ipc::SharedMemory::SharedMemoryType aType, + mozilla::ipc::SharedMemory::SharedMemoryType aShmType, mozilla::ipc::Shmem* aShmem) override; + /** * See ISurfaceAllocator.h * Can be used from any thread. diff --git a/gfx/layers/ipc/ImageBridgeParent.cpp b/gfx/layers/ipc/ImageBridgeParent.cpp index 7494d412e7..e9522b919b 100644 --- a/gfx/layers/ipc/ImageBridgeParent.cpp +++ b/gfx/layers/ipc/ImageBridgeParent.cpp @@ -350,10 +350,6 @@ ImageBridgeParent::NotifyImageComposites(nsTArray& a return ok; } -MessageLoop * ImageBridgeParent::GetMessageLoop() const { - return mMessageLoop; -} - void ImageBridgeParent::DeferredDestroy() { @@ -399,8 +395,8 @@ ImageBridgeParent::OnChannelConnected(int32_t aPid) bool ImageBridgeParent::AllocShmem(size_t aSize, - ipc::SharedMemory::SharedMemoryType aType, - ipc::Shmem* aShmem) + ipc::SharedMemory::SharedMemoryType aType, + ipc::Shmem* aShmem) { if (mStopped) { return false; diff --git a/gfx/layers/ipc/ImageBridgeParent.h b/gfx/layers/ipc/ImageBridgeParent.h index 4e7980feb0..3ba8ac4b39 100644 --- a/gfx/layers/ipc/ImageBridgeParent.h +++ b/gfx/layers/ipc/ImageBridgeParent.h @@ -39,7 +39,8 @@ namespace layers { * interesting stuff is in ImageContainerParent. */ class ImageBridgeParent final : public PImageBridgeParent, - public CompositableParentManager + public CompositableParentManager, + public ShmemAllocator { public: typedef InfallibleTArray EditArray; @@ -50,6 +51,8 @@ public: ImageBridgeParent(MessageLoop* aLoop, Transport* aTransport, ProcessId aChildProcessId); ~ImageBridgeParent(); + virtual ShmemAllocator* AsShmemAllocator() override { return this; } + virtual void ActorDestroy(ActorDestroyReason aWhy) override; static PImageBridgeParent* @@ -72,8 +75,6 @@ public: EditReplyArray* aReply) override; virtual bool RecvUpdateNoSwap(EditArray&& aEdits, OpDestroyArray&& aToDestroy) override; - virtual bool IsAsync() const override { return true; } - PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo, PImageContainerParent* aImageContainer, uint64_t*) override; @@ -97,10 +98,9 @@ public: // Shutdown step 2 virtual bool RecvStop() override; - virtual MessageLoop* GetMessageLoop() const override; + MessageLoop* GetMessageLoop() const { return mMessageLoop; } - - // ISurfaceAllocator + // ShmemAllocator virtual bool AllocShmem(size_t aSize, ipc::SharedMemory::SharedMemoryType aType, @@ -143,6 +143,10 @@ public: base::ProcessHandle aPeerProcess, mozilla::ipc::ProtocolCloneContext* aCtx) override; + virtual bool UsesImageBridge() const override { return true; } + + virtual bool IPCOpen() const override { return !mStopped; } + protected: void OnChannelConnected(int32_t pid) override; diff --git a/gfx/layers/ipc/LayerTransactionParent.h b/gfx/layers/ipc/LayerTransactionParent.h index 0eab5cd98a..7da152fe1a 100644 --- a/gfx/layers/ipc/LayerTransactionParent.h +++ b/gfx/layers/ipc/LayerTransactionParent.h @@ -36,7 +36,8 @@ class CompositableParent; class ShadowLayersManager; class LayerTransactionParent final : public PLayerTransactionParent, - public CompositableParentManager + public CompositableParentManager, + public ShmemAllocator { typedef mozilla::layout::RenderFrameParent RenderFrameParent; typedef InfallibleTArray EditArray; @@ -61,7 +62,8 @@ public: uint64_t GetId() const { return mId; } Layer* GetRoot() const { return mRoot; } - // ISurfaceAllocator + virtual ShmemAllocator* AsShmemAllocator() override { return this; } + virtual bool AllocShmem(size_t aSize, ipc::SharedMemory::SharedMemoryType aType, ipc::Shmem* aShmem) override; diff --git a/gfx/layers/ipc/LayersSurfaces.ipdlh b/gfx/layers/ipc/LayersSurfaces.ipdlh index 9167f5af8a..0f679fbd13 100644 --- a/gfx/layers/ipc/LayersSurfaces.ipdlh +++ b/gfx/layers/ipc/LayersSurfaces.ipdlh @@ -101,7 +101,7 @@ struct SurfaceDescriptorGralloc { struct RGBDescriptor { IntSize size; SurfaceFormat format; - bool hasInternalBuffer; + bool hasIntermediateBuffer; }; struct YCbCrDescriptor { diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp index 658042a77c..6487ca2224 100644 --- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -15,16 +15,18 @@ #include "ShadowLayerChild.h" // for ShadowLayerChild #include "gfx2DGlue.h" // for Moz2D transition helpers #include "gfxPlatform.h" // for gfxImageFormat, gfxPlatform -#include "gfxSharedImageSurface.h" // for gfxSharedImageSurface +//#include "gfxSharedImageSurface.h" // for gfxSharedImageSurface #include "ipc/IPCMessageUtils.h" // for gfxContentType, null_t #include "IPDLActor.h" #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/layers/CompositableClient.h" // for CompositableClient, etc +#include "mozilla/layers/ImageDataSerializer.h" #include "mozilla/layers/LayersMessages.h" // for Edit, etc #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc #include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG #include "mozilla/layers/LayerTransactionChild.h" +#include "mozilla/layers/SharedBufferManagerChild.h" #include "ShadowLayerUtils.h" #include "mozilla/layers/TextureClient.h" // for TextureClient #include "mozilla/mozalloc.h" // for operator new, etc @@ -197,6 +199,164 @@ struct AutoTxnEnd { Transaction* mTxn; }; + +// XXX - We should actually figure out the minimum shmem allocation size on +// a certain platform and use that. +const uint32_t sShmemPageSize = 4096; + +#ifdef DEBUG +const uint32_t sSupportedBlockSize = 4; +#endif + +FixedSizeSmallShmemSectionAllocator::FixedSizeSmallShmemSectionAllocator(ShmemAllocator* aShmProvider) +: mShmProvider(aShmProvider) +{ + MOZ_ASSERT(mShmProvider); +} + +FixedSizeSmallShmemSectionAllocator::~FixedSizeSmallShmemSectionAllocator() +{ + ShrinkShmemSectionHeap(); + // Check if we're not leaking.. + MOZ_ASSERT(mUsedShmems.empty()); +} + +bool +FixedSizeSmallShmemSectionAllocator::AllocShmemSection(uint32_t aSize, ShmemSection* aShmemSection) +{ + // For now we only support sizes of 4. If we want to support different sizes + // some more complicated bookkeeping should be added. + MOZ_ASSERT(aSize == sSupportedBlockSize); + MOZ_ASSERT(aShmemSection); + + uint32_t allocationSize = (aSize + sizeof(ShmemSectionHeapAllocation)); + + for (size_t i = 0; i < mUsedShmems.size(); i++) { + ShmemSectionHeapHeader* header = mUsedShmems[i].get(); + if ((header->mAllocatedBlocks + 1) * allocationSize + sizeof(ShmemSectionHeapHeader) < sShmemPageSize) { + aShmemSection->shmem() = mUsedShmems[i]; + MOZ_ASSERT(mUsedShmems[i].IsWritable()); + break; + } + } + + if (!aShmemSection->shmem().IsWritable()) { + ipc::Shmem tmp; + if (!mShmProvider->AllocUnsafeShmem(sShmemPageSize, OptimalShmemType(), &tmp)) { + return false; + } + + ShmemSectionHeapHeader* header = tmp.get(); + header->mTotalBlocks = 0; + header->mAllocatedBlocks = 0; + + mUsedShmems.push_back(tmp); + aShmemSection->shmem() = tmp; + } + + MOZ_ASSERT(aShmemSection->shmem().IsWritable()); + + ShmemSectionHeapHeader* header = aShmemSection->shmem().get(); + uint8_t* heap = aShmemSection->shmem().get() + sizeof(ShmemSectionHeapHeader); + + ShmemSectionHeapAllocation* allocHeader = nullptr; + + if (header->mTotalBlocks > header->mAllocatedBlocks) { + // Search for the first available block. + for (size_t i = 0; i < header->mTotalBlocks; i++) { + allocHeader = reinterpret_cast(heap); + + if (allocHeader->mStatus == STATUS_FREED) { + break; + } + heap += allocationSize; + } + MOZ_ASSERT(allocHeader && allocHeader->mStatus == STATUS_FREED); + MOZ_ASSERT(allocHeader->mSize == sSupportedBlockSize); + } else { + heap += header->mTotalBlocks * allocationSize; + + header->mTotalBlocks++; + allocHeader = reinterpret_cast(heap); + allocHeader->mSize = aSize; + } + + MOZ_ASSERT(allocHeader); + header->mAllocatedBlocks++; + allocHeader->mStatus = STATUS_ALLOCATED; + + aShmemSection->size() = aSize; + aShmemSection->offset() = (heap + sizeof(ShmemSectionHeapAllocation)) - aShmemSection->shmem().get(); + ShrinkShmemSectionHeap(); + return true; +} + +void +FixedSizeSmallShmemSectionAllocator::FreeShmemSection(mozilla::layers::ShmemSection& aShmemSection) +{ + MOZ_ASSERT(aShmemSection.size() == sSupportedBlockSize); + MOZ_ASSERT(aShmemSection.offset() < sShmemPageSize - sSupportedBlockSize); + + ShmemSectionHeapAllocation* allocHeader = + reinterpret_cast(aShmemSection.shmem().get() + + aShmemSection.offset() - + sizeof(ShmemSectionHeapAllocation)); + + MOZ_ASSERT(allocHeader->mSize == aShmemSection.size()); + + DebugOnly success = allocHeader->mStatus.compareExchange(STATUS_ALLOCATED, STATUS_FREED); + // If this fails something really weird is going on. + MOZ_ASSERT(success); + + ShmemSectionHeapHeader* header = aShmemSection.shmem().get(); + header->mAllocatedBlocks--; +} + +void +FixedSizeSmallShmemSectionAllocator::DeallocShmemSection(mozilla::layers::ShmemSection& aShmemSection) +{ + FreeShmemSection(aShmemSection); + ShrinkShmemSectionHeap(); +} + + +void +FixedSizeSmallShmemSectionAllocator::ShrinkShmemSectionHeap() +{ + // The loop will terminate as we either increase i, or decrease size + // every time through. + size_t i = 0; + while (i < mUsedShmems.size()) { + ShmemSectionHeapHeader* header = mUsedShmems[i].get(); + if (header->mAllocatedBlocks == 0) { + mShmProvider->DeallocShmem(mUsedShmems[i]); + + // We don't particularly care about order, move the last one in the array + // to this position. + if (i < mUsedShmems.size() - 1) { + mUsedShmems[i] = mUsedShmems[mUsedShmems.size() - 1]; + } + mUsedShmems.pop_back(); + } else { + i++; + } + } +} + +FixedSizeSmallShmemSectionAllocator* +ShadowLayerForwarder::GetTileLockAllocator() +{ + MOZ_ASSERT(IPCOpen()); + if (!IPCOpen()) { + return nullptr; + } + + if (!mSectionAllocator) { + mSectionAllocator = new FixedSizeSmallShmemSectionAllocator(this); + } + return mSectionAllocator; +} + void CompositableForwarder::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier) { @@ -206,10 +366,12 @@ CompositableForwarder::IdentifyTextureHost(const TextureFactoryIdentifier& aIden } ShadowLayerForwarder::ShadowLayerForwarder() - : mDiagnosticTypes(DiagnosticTypes::NO_DIAGNOSTIC) + : mMessageLoop(MessageLoop::current()) + , mDiagnosticTypes(DiagnosticTypes::NO_DIAGNOSTIC) , mIsFirstPaint(false) , mWindowOverlayChanged(false) , mPaintSyncId(0) + , mSectionAllocator(nullptr) { mTxn = new Transaction(); } @@ -225,6 +387,10 @@ ShadowLayerForwarder::~ShadowLayerForwarder() mShadowManager->SetForwarder(nullptr); mShadowManager->Destroy(); } + + if (mSectionAllocator) { + delete mSectionAllocator; + } } void @@ -415,7 +581,7 @@ ShadowLayerForwarder::UseTextures(CompositableClient* aCompositable, t.mTimeStamp, t.mPictureRect, t.mFrameID, t.mProducerID, t.mInputFrameID)); if ((t.mTextureClient->GetFlags() & TextureFlags::IMMEDIATE_UPLOAD) - && t.mTextureClient->HasInternalBuffer()) { + && t.mTextureClient->HasIntermediateBuffer()) { // We use IMMEDIATE_UPLOAD when we want to be sure that the upload cannot // race with updates on the main thread. In this case we want the transaction @@ -754,41 +920,40 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray* aReplies, } bool -ShadowLayerForwarder::AllocShmem(size_t aSize, - ipc::SharedMemory::SharedMemoryType aType, - ipc::Shmem* aShmem) +ShadowLayerForwarder::AllocUnsafeShmem(size_t aSize, + ipc::SharedMemory::SharedMemoryType aShmType, + ipc::Shmem* aShmem) { MOZ_ASSERT(HasShadowManager(), "no shadow manager"); - if (!HasShadowManager() || - !mShadowManager->IPCOpen()) { + if (!IPCOpen()) { return false; } ShmemAllocated(mShadowManager); - return mShadowManager->AllocShmem(aSize, aType, aShmem); + return mShadowManager->AllocUnsafeShmem(aSize, aShmType, aShmem); } + bool -ShadowLayerForwarder::AllocUnsafeShmem(size_t aSize, - ipc::SharedMemory::SharedMemoryType aType, - ipc::Shmem* aShmem) +ShadowLayerForwarder::AllocShmem(size_t aSize, + ipc::SharedMemory::SharedMemoryType aShmType, + ipc::Shmem* aShmem) { MOZ_ASSERT(HasShadowManager(), "no shadow manager"); - if (!HasShadowManager() || - !mShadowManager->IPCOpen()) { + if (!IPCOpen()) { return false; } + ShmemAllocated(mShadowManager); - return mShadowManager->AllocUnsafeShmem(aSize, aType, aShmem); + return mShadowManager->AllocShmem(aSize, aShmType, aShmem); } + void ShadowLayerForwarder::DeallocShmem(ipc::Shmem& aShmem) { MOZ_ASSERT(HasShadowManager(), "no shadow manager"); - if (!HasShadowManager() || - !mShadowManager->IPCOpen()) { - return; + if (HasShadowManager() && mShadowManager->IPCOpen()) { + mShadowManager->DeallocShmem(aShmem); } - mShadowManager->DeallocShmem(aShmem); } bool @@ -807,7 +972,7 @@ ShadowLayerForwarder::IsSameProcess() const } base::ProcessId -ShadowLayerForwarder::ParentPid() const +ShadowLayerForwarder::GetParentPid() const { if (!HasShadowManager() || !mShadowManager->IPCOpen()) { return base::ProcessId(); @@ -947,5 +1112,142 @@ void ShadowLayerForwarder::SendPendingAsyncMessges() mShadowManager->SendChildAsyncMessages(replies); } +bool +IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface) +{ + return aSurface.type() != SurfaceDescriptor::T__None && + aSurface.type() != SurfaceDescriptor::Tnull_t; +} + +uint8_t* +GetAddressFromDescriptor(const SurfaceDescriptor& aDescriptor) +{ + MOZ_ASSERT(IsSurfaceDescriptorValid(aDescriptor)); + MOZ_RELEASE_ASSERT(aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorBuffer); + + auto memOrShmem = aDescriptor.get_SurfaceDescriptorBuffer().data(); + if (memOrShmem.type() == MemoryOrShmem::TShmem) { + return memOrShmem.get_Shmem().get(); + } else { + return reinterpret_cast(memOrShmem.get_uintptr_t()); + } +} + +already_AddRefed +GetSurfaceForDescriptor(const SurfaceDescriptor& aDescriptor) +{ + uint8_t* data = GetAddressFromDescriptor(aDescriptor); + auto rgb = aDescriptor.get_SurfaceDescriptorBuffer().desc().get_RGBDescriptor(); + uint32_t stride = ImageDataSerializer::GetRGBStride(rgb); + return gfx::Factory::CreateWrappingDataSourceSurface(data, stride, rgb.size(), + rgb.format()); +} + +already_AddRefed +GetDrawTargetForDescriptor(const SurfaceDescriptor& aDescriptor, gfx::BackendType aBackend) +{ + uint8_t* data = GetAddressFromDescriptor(aDescriptor); + auto rgb = aDescriptor.get_SurfaceDescriptorBuffer().desc().get_RGBDescriptor(); + uint32_t stride = ImageDataSerializer::GetRGBStride(rgb); + return gfx::Factory::CreateDrawTargetForData(gfx::BackendType::CAIRO, + data, rgb.size(), + stride, rgb.format()); +} + +bool +ShadowLayerForwarder::AllocSurfaceDescriptor(const gfx::IntSize& aSize, + gfxContentType aContent, + SurfaceDescriptor* aBuffer) +{ + if (!IPCOpen()) { + return false; + } + return AllocSurfaceDescriptorWithCaps(aSize, aContent, DEFAULT_BUFFER_CAPS, aBuffer); +} + +bool +ShadowLayerForwarder::AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize, + gfxContentType aContent, + uint32_t aCaps, + SurfaceDescriptor* aBuffer) +{ + if (!IPCOpen()) { + return false; + } + gfx::SurfaceFormat format = + gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aContent); + size_t size = ImageDataSerializer::ComputeRGBBufferSize(aSize, format); + if (!size) { + return false; + } + + MemoryOrShmem bufferDesc; + if (IsSameProcess()) { + uint8_t* data = new (std::nothrow) uint8_t[size]; + if (!data) { + return false; + } + GfxMemoryImageReporter::DidAlloc(data); +#ifdef XP_MACOSX + // Workaround a bug in Quartz where drawing an a8 surface to another a8 + // surface with OP_SOURCE still requires the destination to be clear. + if (format == gfx::SurfaceFormat::A8) { + memset(data, 0, size); + } +#endif + bufferDesc = reinterpret_cast(data); + } else { + + mozilla::ipc::Shmem shmem; + if (!AllocUnsafeShmem(size, OptimalShmemType(), &shmem)) { + return false; + } + + bufferDesc = shmem; + } + + // Use an intermediate buffer by default. Skipping the intermediate buffer is + // only possible in certain configurations so let's keep it simple here for now. + const bool hasIntermediateBuffer = true; + *aBuffer = SurfaceDescriptorBuffer(RGBDescriptor(aSize, format, hasIntermediateBuffer), + bufferDesc); + + return true; +} + +/* static */ bool +ShadowLayerForwarder::IsShmem(SurfaceDescriptor* aSurface) +{ + return aSurface && (aSurface->type() == SurfaceDescriptor::TSurfaceDescriptorBuffer) + && (aSurface->get_SurfaceDescriptorBuffer().data().type() == MemoryOrShmem::TShmem); +} + +void +ShadowLayerForwarder::DestroySurfaceDescriptor(SurfaceDescriptor* aSurface) +{ + MOZ_ASSERT(aSurface); + MOZ_ASSERT(IPCOpen()); + if (!IPCOpen() || !aSurface) { + return; + } + + SurfaceDescriptorBuffer& desc = aSurface->get_SurfaceDescriptorBuffer(); + switch (desc.data().type()) { + case MemoryOrShmem::TShmem: { + DeallocShmem(desc.data().get_Shmem()); + break; + } + case MemoryOrShmem::Tuintptr_t: { + uint8_t* ptr = (uint8_t*)desc.data().get_uintptr_t(); + GfxMemoryImageReporter::WillFree(ptr); + delete [] ptr; + break; + } + default: + NS_RUNTIMEABORT("surface type not implemented!"); + } + *aSurface = SurfaceDescriptor(); +} + } // namespace layers } // namespace mozilla diff --git a/gfx/layers/ipc/ShadowLayers.h b/gfx/layers/ipc/ShadowLayers.h index 79aa191c2d..c69bfb8d5e 100644 --- a/gfx/layers/ipc/ShadowLayers.h +++ b/gfx/layers/ipc/ShadowLayers.h @@ -22,11 +22,13 @@ #include "nsRegion.h" // for nsIntRegion #include "nsTArrayForwardDeclare.h" // for InfallibleTArray #include "nsIWidget.h" +#include namespace mozilla { namespace layers { class EditReply; +class FixedSizeSmallShmemSectionAllocator; class ImageContainer; class Layer; class PLayerChild; @@ -39,7 +41,6 @@ class ThebesBuffer; class ThebesBufferData; class Transaction; - /** * We want to share layer trees across thread contexts and address * spaces for several reasons; chief among them @@ -114,12 +115,23 @@ class Transaction; */ class ShadowLayerForwarder final : public CompositableForwarder + , public ShmemAllocator + , public LegacySurfaceDescriptorAllocator { friend class ClientLayerManager; public: virtual ~ShadowLayerForwarder(); + virtual ShmemAllocator* AsShmemAllocator() override { return this; } + + virtual ShadowLayerForwarder* AsLayerForwarder() override { return this; } + + virtual LegacySurfaceDescriptorAllocator* + AsLegacySurfaceDescriptorAllocator() override { return this; } + + FixedSizeSmallShmemSectionAllocator* GetTileLockAllocator(); + /** * Setup the IPDL actor for aCompositable to be part of layers * transactions. @@ -322,7 +334,7 @@ public: * buffer, and the double-buffer pair is gone. */ - // ISurfaceAllocator + virtual bool AllocUnsafeShmem(size_t aSize, mozilla::ipc::SharedMemory::SharedMemoryType aType, mozilla::ipc::Shmem* aShmem) override; @@ -332,8 +344,12 @@ public: virtual void DeallocShmem(mozilla::ipc::Shmem& aShmem) override; virtual bool IPCOpen() const override; + virtual bool IsSameProcess() const override; - virtual base::ProcessId ParentPid() const override; + + virtual MessageLoop* GetMessageLoop() const override { return mMessageLoop; } + + base::ProcessId GetParentPid() const; /** * Construct a shadow of |aLayer| on the "other side", at the @@ -350,6 +366,20 @@ public: static void PlatformSyncBeforeUpdate(); + virtual bool AllocSurfaceDescriptor(const gfx::IntSize& aSize, + gfxContentType aContent, + SurfaceDescriptor* aBuffer) override; + + virtual bool AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize, + gfxContentType aContent, + uint32_t aCaps, + SurfaceDescriptor* aBuffer) override; + + virtual void DestroySurfaceDescriptor(SurfaceDescriptor* aSurface) override; + + // Returns true if aSurface wraps a Shmem. + static bool IsShmem(SurfaceDescriptor* aSurface); + protected: ShadowLayerForwarder(); @@ -366,12 +396,14 @@ protected: private: Transaction* mTxn; + MessageLoop* mMessageLoop; std::vector mPendingAsyncMessages; DiagnosticTypes mDiagnosticTypes; bool mIsFirstPaint; bool mWindowOverlayChanged; int32_t mPaintSyncId; InfallibleTArray mPluginWindowData; + FixedSizeSmallShmemSectionAllocator* mSectionAllocator; }; class CompositableClient; @@ -408,6 +440,50 @@ protected: PLayerChild* mShadow; }; +/// A simple shmem section allocator that can only allocate small +/// fixed size elements (only intended to be used to store tile +/// copy-on-write locks for now). +class FixedSizeSmallShmemSectionAllocator final : public ShmemSectionAllocator +{ +public: + enum AllocationStatus + { + STATUS_ALLOCATED, + STATUS_FREED + }; + + struct ShmemSectionHeapHeader + { + Atomic mTotalBlocks; + Atomic mAllocatedBlocks; + }; + + struct ShmemSectionHeapAllocation + { + Atomic mStatus; + uint32_t mSize; + }; + + explicit FixedSizeSmallShmemSectionAllocator(ShmemAllocator* aShmProvider); + + ~FixedSizeSmallShmemSectionAllocator(); + + virtual bool AllocShmemSection(uint32_t aSize, ShmemSection* aShmemSection) override; + + virtual void DeallocShmemSection(ShmemSection& aShmemSection) override; + + virtual void MemoryPressure() override { ShrinkShmemSectionHeap(); } + + // can be called on the compositor process. + static void FreeShmemSection(ShmemSection& aShmemSection); + + void ShrinkShmemSectionHeap(); + +protected: + std::vector mUsedShmems; + ShmemAllocator* mShmProvider; +}; + } // namespace layers } // namespace mozilla diff --git a/gfx/layers/opengl/GrallocTextureClient.cpp b/gfx/layers/opengl/GrallocTextureClient.cpp index fbb7ba7c4e..9fb316d1ce 100644 --- a/gfx/layers/opengl/GrallocTextureClient.cpp +++ b/gfx/layers/opengl/GrallocTextureClient.cpp @@ -11,6 +11,7 @@ #include "mozilla/layers/CompositableForwarder.h" #include "mozilla/layers/ISurfaceAllocator.h" #include "mozilla/layers/ShadowLayerUtilsGralloc.h" +#include "mozilla/layers/SharedBufferManagerChild.h" #include "gfx2DGlue.h" #include "gfxPrefs.h" // for gfxPrefs #include "SharedSurfaceGralloc.h" @@ -109,11 +110,11 @@ GrallocTextureData::~GrallocTextureData() } void -GrallocTextureData::Deallocate(ISurfaceAllocator* aAllocator) +GrallocTextureData::Deallocate(ClientIPCAllocator* aAllocator) { MOZ_ASSERT(aAllocator); - if (aAllocator) { - aAllocator->DeallocGrallocBuffer(&mGrallocHandle); + if (aAllocator && aAllocator->IPCOpen()) { + SharedBufferManagerChild::GetSingleton()->DeallocGrallocBuffer(mGrallocHandle); } mGrallocHandle = null_t(); @@ -121,11 +122,11 @@ GrallocTextureData::Deallocate(ISurfaceAllocator* aAllocator) } void -GrallocTextureData::Forget(ISurfaceAllocator* aAllocator) +GrallocTextureData::Forget(ClientIPCAllocator* aAllocator) { MOZ_ASSERT(aAllocator); - if (aAllocator) { - aAllocator->DropGrallocBuffer(&mGrallocHandle); + if (aAllocator && aAllocator->IPCOpen()) { + SharedBufferManagerChild::GetSingleton()->DropGrallocBuffer(mGrallocHandle); } mGrallocHandle = null_t(); @@ -278,12 +279,12 @@ GrallocTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface) GrallocTextureData* GrallocTextureData::Create(gfx::IntSize aSize, AndroidFormat aAndroidFormat, gfx::BackendType aMoz2dBackend, uint32_t aUsage, - ISurfaceAllocator* aAllocator) + ClientIPCAllocator* aAllocator) { - if (!aAllocator) { + if (!aAllocator || !aAllocator->IPCOpen()) { return nullptr; } - int32_t maxSize = aAllocator->GetMaxTextureSize(); + int32_t maxSize = aAllocator->AsClientAllocator()->GetMaxTextureSize(); if (aSize.width > maxSize || aSize.height > maxSize) { return nullptr; } @@ -313,7 +314,7 @@ GrallocTextureData::Create(gfx::IntSize aSize, AndroidFormat aAndroidFormat, } MaybeMagicGrallocBufferHandle handle; - if (!aAllocator->AllocGrallocBuffer(aSize, aAndroidFormat, aUsage, &handle)) { + if (!SharedBufferManagerChild::GetSingleton()->AllocGrallocBuffer(aSize, aAndroidFormat, aUsage, &handle)) { return nullptr; } @@ -333,7 +334,7 @@ GrallocTextureData::Create(gfx::IntSize aSize, AndroidFormat aAndroidFormat, GrallocTextureData* GrallocTextureData::CreateForDrawing(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::BackendType aMoz2dBackend, - ISurfaceAllocator* aAllocator) + ClientIPCAllocator* aAllocator) { if (DisableGralloc(aFormat, aSize)) { return nullptr; @@ -385,7 +386,7 @@ GrallocTextureData::GetTextureFlags() const // static GrallocTextureData* GrallocTextureData::CreateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize, - ISurfaceAllocator* aAllocator) + ClientIPCAllocator* aAllocator) { MOZ_ASSERT(aYSize.width == aCbCrSize.width * 2); MOZ_ASSERT(aYSize.height == aCbCrSize.height * 2); @@ -398,7 +399,7 @@ GrallocTextureData::CreateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize, // static GrallocTextureData* GrallocTextureData::CreateForGLRendering(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, - ISurfaceAllocator* aAllocator) + ClientIPCAllocator* aAllocator) { if (aFormat == gfx::SurfaceFormat::YUV) { return nullptr; @@ -434,7 +435,7 @@ GrallocTextureData::TextureClientFromSharedSurface(gl::SharedSurface* abstractSu } TextureData* -GrallocTextureData::CreateSimilar(ISurfaceAllocator* aAllocator, +GrallocTextureData::CreateSimilar(ClientIPCAllocator* aAllocator, TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const { diff --git a/gfx/layers/opengl/GrallocTextureClient.h b/gfx/layers/opengl/GrallocTextureClient.h index 5d409f404f..82bd191221 100644 --- a/gfx/layers/opengl/GrallocTextureClient.h +++ b/gfx/layers/opengl/GrallocTextureClient.h @@ -8,7 +8,6 @@ #ifdef MOZ_WIDGET_GONK #include "mozilla/layers/TextureClient.h" -#include "mozilla/layers/ISurfaceAllocator.h" // For IsSurfaceDescriptorValid #include "mozilla/layers/FenceUtils.h" // for FenceHandle #include "mozilla/layers/ShadowLayerUtilsGralloc.h" #include @@ -58,34 +57,34 @@ public: virtual bool SupportsMoz2D() const override { return true; } - virtual bool HasInternalBuffer() const override { return false; } + virtual bool HasIntermediateBuffer() const override { return false; } virtual bool HasSynchronization() const override { return true; } - virtual void Deallocate(ISurfaceAllocator*) override; + virtual void Deallocate(ClientIPCAllocator*) override; - virtual void Forget(ISurfaceAllocator*) override; + virtual void Forget(ClientIPCAllocator*) override; static GrallocTextureData* CreateForDrawing(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::BackendType aMoz2dBackend, - ISurfaceAllocator* aAllocator); + ClientIPCAllocator* aAllocator); static GrallocTextureData* CreateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize, - ISurfaceAllocator* aAllocator); + ClientIPCAllocator* aAllocator); static GrallocTextureData* CreateForGLRendering(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, - ISurfaceAllocator* aAllocator); + ClientIPCAllocator* aAllocator); static GrallocTextureData* Create(gfx::IntSize aSize, AndroidFormat aFormat, gfx::BackendType aMoz2DBackend, uint32_t aUsage, - ISurfaceAllocator* aAllocator); + ClientIPCAllocator* aAllocator); static already_AddRefed TextureClientFromSharedSurface(gl::SharedSurface* abstractSurf, TextureFlags flags); virtual TextureData* - CreateSimilar(ISurfaceAllocator* aAllocator, + CreateSimilar(ClientIPCAllocator* aAllocator, TextureFlags aFlags = TextureFlags::DEFAULT, TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; diff --git a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h index e05ee5b19b..de2559c56b 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h +++ b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h @@ -30,11 +30,11 @@ public: virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override; - virtual bool HasInternalBuffer() const override { return false; } + virtual bool HasIntermediateBuffer() const override { return false; } - virtual void Deallocate(ISurfaceAllocator* aAllocator) override { mSurface = nullptr; } + virtual void Deallocate(ClientIPCAllocator*) override { mSurface = nullptr; } - virtual void Forget(ISurfaceAllocator* aAllocator) override { mSurface = nullptr; } + virtual void Forget(ClientIPCAllocator*) override { mSurface = nullptr; } // For debugging purposes only. already_AddRefed GetAsSurface(); diff --git a/gfx/layers/opengl/TextureClientOGL.cpp b/gfx/layers/opengl/TextureClientOGL.cpp index ebda6feb3c..05e5d46a5a 100644 --- a/gfx/layers/opengl/TextureClientOGL.cpp +++ b/gfx/layers/opengl/TextureClientOGL.cpp @@ -29,7 +29,7 @@ EGLImageTextureData::EGLImageTextureData(EGLImageImage* aImage, gfx::IntSize aSi already_AddRefed EGLImageTextureData::CreateTextureClient(EGLImageImage* aImage, gfx::IntSize aSize, - ISurfaceAllocator* aAllocator, TextureFlags aFlags) + ClientIPCAllocator* aAllocator, TextureFlags aFlags) { MOZ_ASSERT(XRE_IsParentProcess(), "Can't pass an `EGLImage` between processes."); @@ -71,7 +71,7 @@ already_AddRefed AndroidSurfaceTextureData::CreateTextureClient(AndroidSurfaceTexture* aSurfTex, gfx::IntSize aSize, gl::OriginPos aOriginPos, - ISurfaceAllocator* aAllocator, + ClientIPCAllocator* aAllocator, TextureFlags aFlags) { MOZ_ASSERT(XRE_IsParentProcess(), diff --git a/gfx/layers/opengl/TextureClientOGL.h b/gfx/layers/opengl/TextureClientOGL.h index 002eb418ae..57bf7ba5bd 100644 --- a/gfx/layers/opengl/TextureClientOGL.h +++ b/gfx/layers/opengl/TextureClientOGL.h @@ -26,17 +26,17 @@ public: static already_AddRefed CreateTextureClient(EGLImageImage* aImage, gfx::IntSize aSize, - ISurfaceAllocator* aAllocator, TextureFlags aFlags); + ClientIPCAllocator* aAllocator, TextureFlags aFlags); - virtual bool HasInternalBuffer() const override { return false; } + virtual bool HasIntermediateBuffer() const override { return false; } virtual gfx::IntSize GetSize() const override { return mSize; } virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override; - virtual void Deallocate(ISurfaceAllocator*) override { mImage = nullptr; } + virtual void Deallocate(ClientIPCAllocator*) override { mImage = nullptr; } - virtual void Forget(ISurfaceAllocator*) override { mImage = nullptr; } + virtual void Forget(ClientIPCAllocator*) override { mImage = nullptr; } // Unused functions. virtual bool Lock(OpenMode, FenceHandle*) override { return true; } @@ -64,12 +64,12 @@ public: CreateTextureClient(gl::AndroidSurfaceTexture* aSurfTex, gfx::IntSize aSize, gl::OriginPos aOriginPos, - ISurfaceAllocator* aAllocator, + ClientIPCAllocator* aAllocator, TextureFlags aFlags); ~AndroidSurfaceTextureData(); - virtual bool HasInternalBuffer() const override { return false; } + virtual bool HasIntermediateBuffer() const override { return false; } virtual gfx::IntSize GetSize() const override { return mSize; } @@ -86,7 +86,7 @@ public: } // Our data is always owned externally. - virtual void Deallocate(ISurfaceAllocator*) override {} + virtual void Deallocate(ClientIPCAllocator*) override {} protected: AndroidSurfaceTextureData(gl::AndroidSurfaceTexture* aSurfTex, diff --git a/gfx/thebes/gfxContext.cpp b/gfx/thebes/gfxContext.cpp index 4a75e3810f..fc3b298d13 100644 --- a/gfx/thebes/gfxContext.cpp +++ b/gfx/thebes/gfxContext.cpp @@ -818,7 +818,9 @@ gfxContext::PushGroupForBlendBack(gfxContentType content, Float aOpacity, Source CurrentState().mBlendOpacity = aOpacity; CurrentState().mBlendMask = aMask; +#ifdef DEBUG CurrentState().mWasPushedForBlendBack = true; +#endif CurrentState().mBlendMaskTransform = aMaskTransform; } } @@ -870,7 +872,9 @@ gfxContext::PushGroupAndCopyBackground(gfxContentType content, Float aOpacity, S CurrentState().mBlendOpacity = aOpacity; CurrentState().mBlendMask = aMask; +#ifdef DEBUG CurrentState().mWasPushedForBlendBack = true; +#endif CurrentState().mBlendMaskTransform = aMaskTransform; Point offset = CurrentState().deviceOffset - oldDeviceOffset; @@ -918,7 +922,9 @@ gfxContext::PushGroupAndCopyBackground(gfxContentType content, Float aOpacity, S mDT->SetTransform(GetDTTransform()); CurrentState().mBlendOpacity = aOpacity; CurrentState().mBlendMask = aMask; +#ifdef DEBUG CurrentState().mWasPushedForBlendBack = true; +#endif CurrentState().mBlendMaskTransform = aMaskTransform; } } diff --git a/gfx/thebes/gfxContext.h b/gfx/thebes/gfxContext.h index c51f96d239..1b0e8f1797 100644 --- a/gfx/thebes/gfxContext.h +++ b/gfx/thebes/gfxContext.h @@ -506,7 +506,9 @@ private: mozilla::gfx::Float mBlendOpacity; RefPtr mBlendMask; Matrix mBlendMaskTransform; - mozilla::DebugOnly mWasPushedForBlendBack; +#ifdef DEBUG + bool mWasPushedForBlendBack; +#endif }; // This ensures mPath contains a valid path (in user space!) diff --git a/gfx/thebes/gfxReusableSharedImageSurfaceWrapper.cpp b/gfx/thebes/gfxReusableSharedImageSurfaceWrapper.cpp index 28ac7c877d..03b25f0180 100644 --- a/gfx/thebes/gfxReusableSharedImageSurfaceWrapper.cpp +++ b/gfx/thebes/gfxReusableSharedImageSurfaceWrapper.cpp @@ -38,7 +38,7 @@ gfxReusableSharedImageSurfaceWrapper::ReadUnlock() MOZ_ASSERT(readCount >= 0, "Read count should not be negative"); if (readCount == 0) { - mAllocator->DeallocShmem(mSurface->GetShmem()); + mAllocator->AsShmemAllocator()->DeallocShmem(mSurface->GetShmem()); } } @@ -56,7 +56,7 @@ gfxReusableSharedImageSurfaceWrapper::GetWritable(gfxImageSurface** aSurface) // Something else is reading the surface, copy it RefPtr copySurface = - gfxSharedImageSurface::CreateUnsafe(mAllocator.get(), mSurface->GetSize(), mSurface->Format()); + gfxSharedImageSurface::CreateUnsafe(mAllocator->AsShmemAllocator(), mSurface->GetSize(), mSurface->Format()); copySurface->CopyFrom(mSurface); *aSurface = copySurface; diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 5330160b88..0742e5cc93 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -351,6 +351,7 @@ pref("media.use-blank-decoder", false); pref("media.wmf.enabled", true); pref("media.wmf.decoder.thread-count", -1); pref("media.wmf.low-latency.enabled", false); +pref("media.wmf.skip-blacklist", false); #endif #if defined(MOZ_FFMPEG) pref("media.ffmpeg.enabled", true); diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index 858eb3a119..ff14e50fc9 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -2109,7 +2109,7 @@ nsIWidget::SnapshotWidgetOnScreen() RefPtr dt = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(size, gfx::SurfaceFormat::B8G8R8A8); if (!snapshot || !dt) { - forwarder->DestroySharedSurface(&surface); + forwarder->DestroySurfaceDescriptor(&surface); return nullptr; } @@ -2118,7 +2118,7 @@ nsIWidget::SnapshotWidgetOnScreen() gfx::Rect(gfx::Point(), gfx::Size(size)), gfx::DrawSurfaceOptions(gfx::Filter::POINT)); - forwarder->DestroySharedSurface(&surface); + forwarder->DestroySurfaceDescriptor(&surface); return dt->Snapshot(); }