Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
michael@0 | 2 | * This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #include "ImageLayerD3D10.h" |
michael@0 | 7 | #include "gfxD2DSurface.h" |
michael@0 | 8 | #include "gfxWindowsSurface.h" |
michael@0 | 9 | #include "yuv_convert.h" |
michael@0 | 10 | #include "../d3d9/Nv3DVUtils.h" |
michael@0 | 11 | #include "D3D9SurfaceImage.h" |
michael@0 | 12 | #include "mozilla/gfx/Point.h" |
michael@0 | 13 | #include "gfx2DGlue.h" |
michael@0 | 14 | |
michael@0 | 15 | #include "gfxWindowsPlatform.h" |
michael@0 | 16 | |
michael@0 | 17 | using namespace mozilla::gfx; |
michael@0 | 18 | |
michael@0 | 19 | namespace mozilla { |
michael@0 | 20 | namespace layers { |
michael@0 | 21 | |
michael@0 | 22 | static already_AddRefed<ID3D10Texture2D> |
michael@0 | 23 | DataToTexture(ID3D10Device *aDevice, |
michael@0 | 24 | unsigned char *data, |
michael@0 | 25 | int stride, |
michael@0 | 26 | const IntSize &aSize) |
michael@0 | 27 | { |
michael@0 | 28 | D3D10_SUBRESOURCE_DATA srdata; |
michael@0 | 29 | |
michael@0 | 30 | CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, |
michael@0 | 31 | aSize.width, |
michael@0 | 32 | aSize.height, |
michael@0 | 33 | 1, 1); |
michael@0 | 34 | desc.Usage = D3D10_USAGE_IMMUTABLE; |
michael@0 | 35 | |
michael@0 | 36 | srdata.pSysMem = data; |
michael@0 | 37 | srdata.SysMemPitch = stride; |
michael@0 | 38 | |
michael@0 | 39 | nsRefPtr<ID3D10Texture2D> texture; |
michael@0 | 40 | HRESULT hr = aDevice->CreateTexture2D(&desc, &srdata, getter_AddRefs(texture)); |
michael@0 | 41 | |
michael@0 | 42 | if (FAILED(hr)) { |
michael@0 | 43 | LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("Failed to create texture for data"), |
michael@0 | 44 | hr); |
michael@0 | 45 | } |
michael@0 | 46 | |
michael@0 | 47 | return texture.forget(); |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | static already_AddRefed<ID3D10Texture2D> |
michael@0 | 51 | SurfaceToTexture(ID3D10Device *aDevice, |
michael@0 | 52 | SourceSurface *aSurface, |
michael@0 | 53 | const IntSize &aSize) |
michael@0 | 54 | { |
michael@0 | 55 | if (!aSurface) { |
michael@0 | 56 | return nullptr; |
michael@0 | 57 | } |
michael@0 | 58 | |
michael@0 | 59 | void *nativeSurf = |
michael@0 | 60 | aSurface->GetNativeSurface(NativeSurfaceType::D3D10_TEXTURE); |
michael@0 | 61 | if (nativeSurf) { |
michael@0 | 62 | nsRefPtr<ID3D10Texture2D> texture = |
michael@0 | 63 | static_cast<ID3D10Texture2D*>(nativeSurf); |
michael@0 | 64 | ID3D10Device *dev; |
michael@0 | 65 | texture->GetDevice(&dev); |
michael@0 | 66 | if (dev == aDevice) { |
michael@0 | 67 | return texture.forget(); |
michael@0 | 68 | } |
michael@0 | 69 | } |
michael@0 | 70 | RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface(); |
michael@0 | 71 | if (!dataSurface) { |
michael@0 | 72 | return nullptr; |
michael@0 | 73 | } |
michael@0 | 74 | DataSourceSurface::MappedSurface map; |
michael@0 | 75 | if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map)) { |
michael@0 | 76 | return nullptr; |
michael@0 | 77 | } |
michael@0 | 78 | nsRefPtr<ID3D10Texture2D> texture = |
michael@0 | 79 | DataToTexture(aDevice, map.mData, map.mStride, aSize); |
michael@0 | 80 | dataSurface->Unmap(); |
michael@0 | 81 | return texture.forget(); |
michael@0 | 82 | } |
michael@0 | 83 | |
michael@0 | 84 | Layer* |
michael@0 | 85 | ImageLayerD3D10::GetLayer() |
michael@0 | 86 | { |
michael@0 | 87 | return this; |
michael@0 | 88 | } |
michael@0 | 89 | |
michael@0 | 90 | /** |
michael@0 | 91 | * Returns a shader resource view for a Cairo or remote image. |
michael@0 | 92 | * Returns nullptr if unsuccessful. |
michael@0 | 93 | * If successful, aHasAlpha will be true iff the resulting texture |
michael@0 | 94 | * has an alpha component. |
michael@0 | 95 | */ |
michael@0 | 96 | ID3D10ShaderResourceView* |
michael@0 | 97 | ImageLayerD3D10::GetImageSRView(Image* aImage, bool& aHasAlpha, IDXGIKeyedMutex **aMutex) |
michael@0 | 98 | { |
michael@0 | 99 | NS_ASSERTION(aImage, "Null image."); |
michael@0 | 100 | |
michael@0 | 101 | if (aImage->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP) { |
michael@0 | 102 | RemoteBitmapImage *remoteImage = |
michael@0 | 103 | static_cast<RemoteBitmapImage*>(aImage); |
michael@0 | 104 | |
michael@0 | 105 | if (!aImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10)) { |
michael@0 | 106 | nsAutoPtr<TextureD3D10BackendData> dat(new TextureD3D10BackendData()); |
michael@0 | 107 | dat->mTexture = DataToTexture(device(), remoteImage->mData, remoteImage->mStride, remoteImage->mSize); |
michael@0 | 108 | |
michael@0 | 109 | if (dat->mTexture) { |
michael@0 | 110 | device()->CreateShaderResourceView(dat->mTexture, nullptr, getter_AddRefs(dat->mSRView)); |
michael@0 | 111 | aImage->SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10, dat.forget()); |
michael@0 | 112 | } |
michael@0 | 113 | } |
michael@0 | 114 | |
michael@0 | 115 | aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32; |
michael@0 | 116 | } else if (aImage->GetFormat() == ImageFormat::REMOTE_IMAGE_DXGI_TEXTURE) { |
michael@0 | 117 | RemoteDXGITextureImage *remoteImage = |
michael@0 | 118 | static_cast<RemoteDXGITextureImage*>(aImage); |
michael@0 | 119 | |
michael@0 | 120 | remoteImage->GetD3D10TextureBackendData(device()); |
michael@0 | 121 | |
michael@0 | 122 | aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32; |
michael@0 | 123 | } else if (aImage->GetFormat() == ImageFormat::CAIRO_SURFACE) { |
michael@0 | 124 | CairoImage *cairoImage = |
michael@0 | 125 | static_cast<CairoImage*>(aImage); |
michael@0 | 126 | |
michael@0 | 127 | RefPtr<SourceSurface> surf = cairoImage->GetAsSourceSurface(); |
michael@0 | 128 | if (!surf) { |
michael@0 | 129 | return nullptr; |
michael@0 | 130 | } |
michael@0 | 131 | |
michael@0 | 132 | if (!aImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10)) { |
michael@0 | 133 | nsAutoPtr<TextureD3D10BackendData> dat(new TextureD3D10BackendData()); |
michael@0 | 134 | dat->mTexture = SurfaceToTexture(device(), surf, cairoImage->GetSize()); |
michael@0 | 135 | |
michael@0 | 136 | if (dat->mTexture) { |
michael@0 | 137 | device()->CreateShaderResourceView(dat->mTexture, nullptr, getter_AddRefs(dat->mSRView)); |
michael@0 | 138 | aImage->SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10, dat.forget()); |
michael@0 | 139 | } |
michael@0 | 140 | } |
michael@0 | 141 | |
michael@0 | 142 | aHasAlpha = surf->GetFormat() == SurfaceFormat::B8G8R8A8; |
michael@0 | 143 | } else if (aImage->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE) { |
michael@0 | 144 | if (!aImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10)) { |
michael@0 | 145 | // Use resource sharing to open the D3D9 texture as a D3D10 texture, |
michael@0 | 146 | HRESULT hr; |
michael@0 | 147 | D3D9SurfaceImage* d3dImage = reinterpret_cast<D3D9SurfaceImage*>(aImage); |
michael@0 | 148 | nsRefPtr<ID3D10Texture2D> texture; |
michael@0 | 149 | hr = device()->OpenSharedResource(d3dImage->GetShareHandle(), |
michael@0 | 150 | IID_ID3D10Texture2D, |
michael@0 | 151 | (void**)getter_AddRefs(texture)); |
michael@0 | 152 | NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); |
michael@0 | 153 | |
michael@0 | 154 | nsAutoPtr<TextureD3D10BackendData> dat(new TextureD3D10BackendData()); |
michael@0 | 155 | dat->mTexture = texture; |
michael@0 | 156 | |
michael@0 | 157 | hr = device()->CreateShaderResourceView(dat->mTexture, nullptr, getter_AddRefs(dat->mSRView)); |
michael@0 | 158 | NS_ENSURE_TRUE(SUCCEEDED(hr) && dat->mSRView, nullptr); |
michael@0 | 159 | |
michael@0 | 160 | aImage->SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10, dat.forget()); |
michael@0 | 161 | } |
michael@0 | 162 | aHasAlpha = false; |
michael@0 | 163 | } else { |
michael@0 | 164 | NS_WARNING("Incorrect image type."); |
michael@0 | 165 | return nullptr; |
michael@0 | 166 | } |
michael@0 | 167 | |
michael@0 | 168 | TextureD3D10BackendData *data = |
michael@0 | 169 | static_cast<TextureD3D10BackendData*>(aImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10)); |
michael@0 | 170 | |
michael@0 | 171 | if (!data) { |
michael@0 | 172 | return nullptr; |
michael@0 | 173 | } |
michael@0 | 174 | |
michael@0 | 175 | if (aMutex && |
michael@0 | 176 | SUCCEEDED(data->mTexture->QueryInterface(IID_IDXGIKeyedMutex, (void**)aMutex))) { |
michael@0 | 177 | if (FAILED((*aMutex)->AcquireSync(0, 0))) { |
michael@0 | 178 | NS_WARNING("Failed to acquire sync on keyed mutex, plugin forgot to release?"); |
michael@0 | 179 | return nullptr; |
michael@0 | 180 | } |
michael@0 | 181 | } |
michael@0 | 182 | |
michael@0 | 183 | nsRefPtr<ID3D10Device> dev; |
michael@0 | 184 | data->mTexture->GetDevice(getter_AddRefs(dev)); |
michael@0 | 185 | if (dev != device()) { |
michael@0 | 186 | return nullptr; |
michael@0 | 187 | } |
michael@0 | 188 | |
michael@0 | 189 | return data->mSRView; |
michael@0 | 190 | } |
michael@0 | 191 | |
michael@0 | 192 | void |
michael@0 | 193 | ImageLayerD3D10::RenderLayer() |
michael@0 | 194 | { |
michael@0 | 195 | ImageContainer *container = GetContainer(); |
michael@0 | 196 | if (!container) { |
michael@0 | 197 | return; |
michael@0 | 198 | } |
michael@0 | 199 | |
michael@0 | 200 | AutoLockImage autoLock(container); |
michael@0 | 201 | |
michael@0 | 202 | Image *image = autoLock.GetImage(); |
michael@0 | 203 | if (!image) { |
michael@0 | 204 | return; |
michael@0 | 205 | } |
michael@0 | 206 | |
michael@0 | 207 | IntSize size = image->GetSize(); |
michael@0 | 208 | |
michael@0 | 209 | SetEffectTransformAndOpacity(); |
michael@0 | 210 | |
michael@0 | 211 | ID3D10EffectTechnique *technique; |
michael@0 | 212 | nsRefPtr<IDXGIKeyedMutex> keyedMutex; |
michael@0 | 213 | |
michael@0 | 214 | if (image->GetFormat() == ImageFormat::CAIRO_SURFACE || |
michael@0 | 215 | image->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP || |
michael@0 | 216 | image->GetFormat() == ImageFormat::REMOTE_IMAGE_DXGI_TEXTURE || |
michael@0 | 217 | image->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE) { |
michael@0 | 218 | NS_ASSERTION(image->GetFormat() != ImageFormat::CAIRO_SURFACE || |
michael@0 | 219 | !static_cast<CairoImage*>(image)->mSourceSurface || |
michael@0 | 220 | static_cast<CairoImage*>(image)->mSourceSurface->GetFormat() != SurfaceFormat::A8, |
michael@0 | 221 | "Image layer has alpha image"); |
michael@0 | 222 | bool hasAlpha = false; |
michael@0 | 223 | |
michael@0 | 224 | nsRefPtr<ID3D10ShaderResourceView> srView = GetImageSRView(image, hasAlpha, getter_AddRefs(keyedMutex)); |
michael@0 | 225 | if (!srView) { |
michael@0 | 226 | return; |
michael@0 | 227 | } |
michael@0 | 228 | |
michael@0 | 229 | uint8_t shaderFlags = SHADER_PREMUL; |
michael@0 | 230 | shaderFlags |= LoadMaskTexture(); |
michael@0 | 231 | shaderFlags |= hasAlpha |
michael@0 | 232 | ? SHADER_RGBA : SHADER_RGB; |
michael@0 | 233 | shaderFlags |= mFilter == GraphicsFilter::FILTER_NEAREST |
michael@0 | 234 | ? SHADER_POINT : SHADER_LINEAR; |
michael@0 | 235 | technique = SelectShader(shaderFlags); |
michael@0 | 236 | |
michael@0 | 237 | |
michael@0 | 238 | effect()->GetVariableByName("tRGB")->AsShaderResource()->SetResource(srView); |
michael@0 | 239 | |
michael@0 | 240 | effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector( |
michael@0 | 241 | ShaderConstantRectD3D10( |
michael@0 | 242 | (float)0, |
michael@0 | 243 | (float)0, |
michael@0 | 244 | (float)size.width, |
michael@0 | 245 | (float)size.height) |
michael@0 | 246 | ); |
michael@0 | 247 | } else if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) { |
michael@0 | 248 | PlanarYCbCrImage *yuvImage = |
michael@0 | 249 | static_cast<PlanarYCbCrImage*>(image); |
michael@0 | 250 | |
michael@0 | 251 | if (!yuvImage->IsValid()) { |
michael@0 | 252 | return; |
michael@0 | 253 | } |
michael@0 | 254 | |
michael@0 | 255 | if (!yuvImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10)) { |
michael@0 | 256 | AllocateTexturesYCbCr(yuvImage); |
michael@0 | 257 | } |
michael@0 | 258 | |
michael@0 | 259 | PlanarYCbCrD3D10BackendData *data = |
michael@0 | 260 | static_cast<PlanarYCbCrD3D10BackendData*>(yuvImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10)); |
michael@0 | 261 | |
michael@0 | 262 | if (!data) { |
michael@0 | 263 | return; |
michael@0 | 264 | } |
michael@0 | 265 | |
michael@0 | 266 | nsRefPtr<ID3D10Device> dev; |
michael@0 | 267 | data->mYTexture->GetDevice(getter_AddRefs(dev)); |
michael@0 | 268 | if (dev != device()) { |
michael@0 | 269 | return; |
michael@0 | 270 | } |
michael@0 | 271 | |
michael@0 | 272 | // TODO: At some point we should try to deal with mFilter here, you don't |
michael@0 | 273 | // really want to use point filtering in the case of NEAREST, since that |
michael@0 | 274 | // would also use point filtering for Chroma upsampling. Where most likely |
michael@0 | 275 | // the user would only want point filtering for final RGB image upsampling. |
michael@0 | 276 | |
michael@0 | 277 | technique = SelectShader(SHADER_YCBCR | LoadMaskTexture()); |
michael@0 | 278 | |
michael@0 | 279 | effect()->GetVariableByName("tY")->AsShaderResource()->SetResource(data->mYView); |
michael@0 | 280 | effect()->GetVariableByName("tCb")->AsShaderResource()->SetResource(data->mCbView); |
michael@0 | 281 | effect()->GetVariableByName("tCr")->AsShaderResource()->SetResource(data->mCrView); |
michael@0 | 282 | |
michael@0 | 283 | /* |
michael@0 | 284 | * Send 3d control data and metadata to NV3DVUtils |
michael@0 | 285 | */ |
michael@0 | 286 | if (GetNv3DVUtils()) { |
michael@0 | 287 | Nv_Stereo_Mode mode; |
michael@0 | 288 | switch (yuvImage->GetData()->mStereoMode) { |
michael@0 | 289 | case StereoMode::LEFT_RIGHT: |
michael@0 | 290 | mode = NV_STEREO_MODE_LEFT_RIGHT; |
michael@0 | 291 | break; |
michael@0 | 292 | case StereoMode::RIGHT_LEFT: |
michael@0 | 293 | mode = NV_STEREO_MODE_RIGHT_LEFT; |
michael@0 | 294 | break; |
michael@0 | 295 | case StereoMode::BOTTOM_TOP: |
michael@0 | 296 | mode = NV_STEREO_MODE_BOTTOM_TOP; |
michael@0 | 297 | break; |
michael@0 | 298 | case StereoMode::TOP_BOTTOM: |
michael@0 | 299 | mode = NV_STEREO_MODE_TOP_BOTTOM; |
michael@0 | 300 | break; |
michael@0 | 301 | case StereoMode::MONO: |
michael@0 | 302 | mode = NV_STEREO_MODE_MONO; |
michael@0 | 303 | break; |
michael@0 | 304 | } |
michael@0 | 305 | |
michael@0 | 306 | // Send control data even in mono case so driver knows to leave stereo mode. |
michael@0 | 307 | GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE); |
michael@0 | 308 | |
michael@0 | 309 | if (yuvImage->GetData()->mStereoMode != StereoMode::MONO) { |
michael@0 | 310 | // Dst resource is optional |
michael@0 | 311 | GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)yuvImage->GetData()->mYSize.width, |
michael@0 | 312 | (unsigned int)yuvImage->GetData()->mYSize.height, (HANDLE)(data->mYTexture), (HANDLE)(nullptr)); |
michael@0 | 313 | } |
michael@0 | 314 | } |
michael@0 | 315 | |
michael@0 | 316 | effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector( |
michael@0 | 317 | ShaderConstantRectD3D10( |
michael@0 | 318 | (float)0, |
michael@0 | 319 | (float)0, |
michael@0 | 320 | (float)size.width, |
michael@0 | 321 | (float)size.height) |
michael@0 | 322 | ); |
michael@0 | 323 | |
michael@0 | 324 | effect()->GetVariableByName("vTextureCoords")->AsVector()->SetFloatVector( |
michael@0 | 325 | ShaderConstantRectD3D10( |
michael@0 | 326 | (float)yuvImage->GetData()->mPicX / yuvImage->GetData()->mYSize.width, |
michael@0 | 327 | (float)yuvImage->GetData()->mPicY / yuvImage->GetData()->mYSize.height, |
michael@0 | 328 | (float)yuvImage->GetData()->mPicSize.width / yuvImage->GetData()->mYSize.width, |
michael@0 | 329 | (float)yuvImage->GetData()->mPicSize.height / yuvImage->GetData()->mYSize.height) |
michael@0 | 330 | ); |
michael@0 | 331 | } |
michael@0 | 332 | |
michael@0 | 333 | bool resetTexCoords = image->GetFormat() == ImageFormat::PLANAR_YCBCR; |
michael@0 | 334 | image = nullptr; |
michael@0 | 335 | autoLock.Unlock(); |
michael@0 | 336 | |
michael@0 | 337 | technique->GetPassByIndex(0)->Apply(0); |
michael@0 | 338 | device()->Draw(4, 0); |
michael@0 | 339 | |
michael@0 | 340 | if (keyedMutex) { |
michael@0 | 341 | keyedMutex->ReleaseSync(0); |
michael@0 | 342 | } |
michael@0 | 343 | |
michael@0 | 344 | if (resetTexCoords) { |
michael@0 | 345 | effect()->GetVariableByName("vTextureCoords")->AsVector()-> |
michael@0 | 346 | SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f)); |
michael@0 | 347 | } |
michael@0 | 348 | |
michael@0 | 349 | GetContainer()->NotifyPaintedImage(image); |
michael@0 | 350 | } |
michael@0 | 351 | |
michael@0 | 352 | void ImageLayerD3D10::AllocateTexturesYCbCr(PlanarYCbCrImage *aImage) |
michael@0 | 353 | { |
michael@0 | 354 | nsAutoPtr<PlanarYCbCrD3D10BackendData> backendData( |
michael@0 | 355 | new PlanarYCbCrD3D10BackendData); |
michael@0 | 356 | |
michael@0 | 357 | const PlanarYCbCrData *data = aImage->GetData(); |
michael@0 | 358 | |
michael@0 | 359 | D3D10_SUBRESOURCE_DATA dataY; |
michael@0 | 360 | D3D10_SUBRESOURCE_DATA dataCb; |
michael@0 | 361 | D3D10_SUBRESOURCE_DATA dataCr; |
michael@0 | 362 | CD3D10_TEXTURE2D_DESC descY(DXGI_FORMAT_A8_UNORM, |
michael@0 | 363 | data->mYSize.width, |
michael@0 | 364 | data->mYSize.height, 1, 1); |
michael@0 | 365 | CD3D10_TEXTURE2D_DESC descCbCr(DXGI_FORMAT_A8_UNORM, |
michael@0 | 366 | data->mCbCrSize.width, |
michael@0 | 367 | data->mCbCrSize.height, 1, 1); |
michael@0 | 368 | |
michael@0 | 369 | descY.Usage = descCbCr.Usage = D3D10_USAGE_IMMUTABLE; |
michael@0 | 370 | |
michael@0 | 371 | dataY.pSysMem = data->mYChannel; |
michael@0 | 372 | dataY.SysMemPitch = data->mYStride; |
michael@0 | 373 | dataCb.pSysMem = data->mCbChannel; |
michael@0 | 374 | dataCb.SysMemPitch = data->mCbCrStride; |
michael@0 | 375 | dataCr.pSysMem = data->mCrChannel; |
michael@0 | 376 | dataCr.SysMemPitch = data->mCbCrStride; |
michael@0 | 377 | |
michael@0 | 378 | HRESULT hr = device()->CreateTexture2D(&descY, &dataY, getter_AddRefs(backendData->mYTexture)); |
michael@0 | 379 | if (!FAILED(hr)) { |
michael@0 | 380 | hr = device()->CreateTexture2D(&descCbCr, &dataCb, getter_AddRefs(backendData->mCbTexture)); |
michael@0 | 381 | } |
michael@0 | 382 | if (!FAILED(hr)) { |
michael@0 | 383 | hr = device()->CreateTexture2D(&descCbCr, &dataCr, getter_AddRefs(backendData->mCrTexture)); |
michael@0 | 384 | } |
michael@0 | 385 | if (FAILED(hr)) { |
michael@0 | 386 | LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("PlanarYCbCrImageD3D10::AllocateTextures(): Failed to create texture"), |
michael@0 | 387 | hr); |
michael@0 | 388 | return; |
michael@0 | 389 | } |
michael@0 | 390 | device()->CreateShaderResourceView(backendData->mYTexture, nullptr, getter_AddRefs(backendData->mYView)); |
michael@0 | 391 | device()->CreateShaderResourceView(backendData->mCbTexture, nullptr, getter_AddRefs(backendData->mCbView)); |
michael@0 | 392 | device()->CreateShaderResourceView(backendData->mCrTexture, nullptr, getter_AddRefs(backendData->mCrView)); |
michael@0 | 393 | |
michael@0 | 394 | aImage->SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10, backendData.forget()); |
michael@0 | 395 | } |
michael@0 | 396 | |
michael@0 | 397 | already_AddRefed<ID3D10ShaderResourceView> |
michael@0 | 398 | ImageLayerD3D10::GetAsTexture(gfx::IntSize* aSize) |
michael@0 | 399 | { |
michael@0 | 400 | if (!GetContainer()) { |
michael@0 | 401 | return nullptr; |
michael@0 | 402 | } |
michael@0 | 403 | |
michael@0 | 404 | AutoLockImage autoLock(GetContainer()); |
michael@0 | 405 | |
michael@0 | 406 | Image *image = autoLock.GetImage(); |
michael@0 | 407 | if (!image) { |
michael@0 | 408 | return nullptr; |
michael@0 | 409 | } |
michael@0 | 410 | |
michael@0 | 411 | if (image->GetFormat() != ImageFormat::CAIRO_SURFACE) { |
michael@0 | 412 | return nullptr; |
michael@0 | 413 | } |
michael@0 | 414 | |
michael@0 | 415 | *aSize = image->GetSize(); |
michael@0 | 416 | bool dontCare; |
michael@0 | 417 | nsRefPtr<ID3D10ShaderResourceView> result = GetImageSRView(image, dontCare); |
michael@0 | 418 | return result.forget(); |
michael@0 | 419 | } |
michael@0 | 420 | |
michael@0 | 421 | TemporaryRef<gfx::SourceSurface> |
michael@0 | 422 | RemoteDXGITextureImage::GetAsSourceSurface() |
michael@0 | 423 | { |
michael@0 | 424 | nsRefPtr<ID3D10Device1> device = |
michael@0 | 425 | gfxWindowsPlatform::GetPlatform()->GetD3D10Device(); |
michael@0 | 426 | if (!device) { |
michael@0 | 427 | NS_WARNING("Cannot readback from shared texture because no D3D10 device is available."); |
michael@0 | 428 | return nullptr; |
michael@0 | 429 | } |
michael@0 | 430 | |
michael@0 | 431 | TextureD3D10BackendData* data = GetD3D10TextureBackendData(device); |
michael@0 | 432 | |
michael@0 | 433 | if (!data) { |
michael@0 | 434 | return nullptr; |
michael@0 | 435 | } |
michael@0 | 436 | |
michael@0 | 437 | nsRefPtr<IDXGIKeyedMutex> keyedMutex; |
michael@0 | 438 | |
michael@0 | 439 | if (FAILED(data->mTexture->QueryInterface(IID_IDXGIKeyedMutex, getter_AddRefs(keyedMutex)))) { |
michael@0 | 440 | NS_WARNING("Failed to QueryInterface for IDXGIKeyedMutex, strange."); |
michael@0 | 441 | return nullptr; |
michael@0 | 442 | } |
michael@0 | 443 | |
michael@0 | 444 | if (FAILED(keyedMutex->AcquireSync(0, 0))) { |
michael@0 | 445 | NS_WARNING("Failed to acquire sync for keyedMutex, plugin failed to release?"); |
michael@0 | 446 | return nullptr; |
michael@0 | 447 | } |
michael@0 | 448 | |
michael@0 | 449 | D3D10_TEXTURE2D_DESC desc; |
michael@0 | 450 | |
michael@0 | 451 | data->mTexture->GetDesc(&desc); |
michael@0 | 452 | |
michael@0 | 453 | desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ; |
michael@0 | 454 | desc.BindFlags = 0; |
michael@0 | 455 | desc.MiscFlags = 0; |
michael@0 | 456 | desc.Usage = D3D10_USAGE_STAGING; |
michael@0 | 457 | |
michael@0 | 458 | nsRefPtr<ID3D10Texture2D> softTexture; |
michael@0 | 459 | HRESULT hr = device->CreateTexture2D(&desc, nullptr, getter_AddRefs(softTexture)); |
michael@0 | 460 | |
michael@0 | 461 | if (FAILED(hr)) { |
michael@0 | 462 | NS_WARNING("Failed to create 2D staging texture."); |
michael@0 | 463 | return nullptr; |
michael@0 | 464 | } |
michael@0 | 465 | |
michael@0 | 466 | device->CopyResource(softTexture, data->mTexture); |
michael@0 | 467 | keyedMutex->ReleaseSync(0); |
michael@0 | 468 | |
michael@0 | 469 | RefPtr<gfx::DataSourceSurface> surface |
michael@0 | 470 | = gfx::Factory::CreateDataSourceSurface(mSize, |
michael@0 | 471 | mFormat == RemoteImageData::BGRX32 |
michael@0 | 472 | ? gfx::SurfaceFormat::B8G8R8X8 |
michael@0 | 473 | : gfx::SurfaceFormat::B8G8R8A8); |
michael@0 | 474 | |
michael@0 | 475 | if (!surface) { |
michael@0 | 476 | NS_WARNING("Failed to create SourceSurface for DXGI texture."); |
michael@0 | 477 | return nullptr; |
michael@0 | 478 | } |
michael@0 | 479 | |
michael@0 | 480 | gfx::DataSourceSurface::MappedSurface mappedSurface; |
michael@0 | 481 | if (!surface->Map(gfx::DataSourceSurface::WRITE, &mappedSurface)) { |
michael@0 | 482 | NS_WARNING("Failed to map source surface"); |
michael@0 | 483 | return nullptr; |
michael@0 | 484 | } |
michael@0 | 485 | |
michael@0 | 486 | D3D10_MAPPED_TEXTURE2D mapped; |
michael@0 | 487 | softTexture->Map(0, D3D10_MAP_READ, 0, &mapped); |
michael@0 | 488 | |
michael@0 | 489 | for (int y = 0; y < mSize.height; y++) { |
michael@0 | 490 | memcpy(mappedSurface.mData + mappedSurface.mStride * y, |
michael@0 | 491 | (unsigned char*)(mapped.pData) + mapped.RowPitch * y, |
michael@0 | 492 | mSize.width * 4); |
michael@0 | 493 | } |
michael@0 | 494 | |
michael@0 | 495 | softTexture->Unmap(0); |
michael@0 | 496 | surface->Unmap(); |
michael@0 | 497 | |
michael@0 | 498 | return surface; |
michael@0 | 499 | } |
michael@0 | 500 | |
michael@0 | 501 | TextureD3D10BackendData* |
michael@0 | 502 | RemoteDXGITextureImage::GetD3D10TextureBackendData(ID3D10Device *aDevice) |
michael@0 | 503 | { |
michael@0 | 504 | if (GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10)) { |
michael@0 | 505 | TextureD3D10BackendData *data = |
michael@0 | 506 | static_cast<TextureD3D10BackendData*>(GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10)); |
michael@0 | 507 | |
michael@0 | 508 | nsRefPtr<ID3D10Device> device; |
michael@0 | 509 | data->mTexture->GetDevice(getter_AddRefs(device)); |
michael@0 | 510 | |
michael@0 | 511 | if (device == aDevice) { |
michael@0 | 512 | return data; |
michael@0 | 513 | } |
michael@0 | 514 | } |
michael@0 | 515 | nsRefPtr<ID3D10Texture2D> texture; |
michael@0 | 516 | aDevice->OpenSharedResource(mHandle, __uuidof(ID3D10Texture2D), getter_AddRefs(texture)); |
michael@0 | 517 | |
michael@0 | 518 | if (!texture) { |
michael@0 | 519 | NS_WARNING("Failed to get texture for shared texture handle."); |
michael@0 | 520 | return nullptr; |
michael@0 | 521 | } |
michael@0 | 522 | |
michael@0 | 523 | nsAutoPtr<TextureD3D10BackendData> data(new TextureD3D10BackendData()); |
michael@0 | 524 | |
michael@0 | 525 | data->mTexture = texture; |
michael@0 | 526 | |
michael@0 | 527 | aDevice->CreateShaderResourceView(texture, nullptr, getter_AddRefs(data->mSRView)); |
michael@0 | 528 | |
michael@0 | 529 | SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10, data); |
michael@0 | 530 | |
michael@0 | 531 | return data.forget(); |
michael@0 | 532 | } |
michael@0 | 533 | |
michael@0 | 534 | } /* layers */ |
michael@0 | 535 | } /* mozilla */ |