michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/gfx/2D.h" michael@0: #include "mozilla/gfx/Point.h" michael@0: #include "mozilla/RefPtr.h" michael@0: #include "mozilla/layers/PLayerTransaction.h" michael@0: #include "gfxSharedImageSurface.h" michael@0: michael@0: #include "ImageLayerD3D9.h" michael@0: #include "ThebesLayerD3D9.h" michael@0: #include "gfxPlatform.h" michael@0: #include "gfx2DGlue.h" michael@0: #include "yuv_convert.h" michael@0: #include "nsIServiceManager.h" michael@0: #include "nsIConsoleService.h" michael@0: #include "Nv3DVUtils.h" michael@0: #include "D3D9SurfaceImage.h" michael@0: michael@0: namespace mozilla { michael@0: namespace layers { michael@0: michael@0: using namespace mozilla::gfx; michael@0: michael@0: static inline _D3DFORMAT michael@0: D3dFormatForSurfaceFormat(SurfaceFormat aFormat) michael@0: { michael@0: if (aFormat == SurfaceFormat::A8) { michael@0: return D3DFMT_A8; michael@0: } michael@0: michael@0: return D3DFMT_A8R8G8B8; michael@0: } michael@0: michael@0: static already_AddRefed michael@0: DataToTexture(IDirect3DDevice9 *aDevice, michael@0: unsigned char *aData, michael@0: int aStride, michael@0: const IntSize &aSize, michael@0: _D3DFORMAT aFormat) michael@0: { michael@0: nsRefPtr texture; michael@0: nsRefPtr deviceEx; michael@0: aDevice->QueryInterface(IID_IDirect3DDevice9Ex, michael@0: (void**)getter_AddRefs(deviceEx)); michael@0: michael@0: nsRefPtr surface; michael@0: D3DLOCKED_RECT lockedRect; michael@0: if (deviceEx) { michael@0: // D3D9Ex doesn't support managed textures. We could use dynamic textures michael@0: // here but since Images are immutable that probably isn't such a great michael@0: // idea. michael@0: if (FAILED(aDevice-> michael@0: CreateTexture(aSize.width, aSize.height, michael@0: 1, 0, aFormat, D3DPOOL_DEFAULT, michael@0: getter_AddRefs(texture), nullptr))) michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: nsRefPtr tmpTexture; michael@0: if (FAILED(aDevice-> michael@0: CreateTexture(aSize.width, aSize.height, michael@0: 1, 0, aFormat, D3DPOOL_SYSTEMMEM, michael@0: getter_AddRefs(tmpTexture), nullptr))) michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: tmpTexture->GetSurfaceLevel(0, getter_AddRefs(surface)); michael@0: surface->LockRect(&lockedRect, nullptr, 0); michael@0: NS_ASSERTION(lockedRect.pBits, "Could not lock surface"); michael@0: } else { michael@0: if (FAILED(aDevice-> michael@0: CreateTexture(aSize.width, aSize.height, michael@0: 1, 0, aFormat, D3DPOOL_MANAGED, michael@0: getter_AddRefs(texture), nullptr))) michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: /* lock the entire texture */ michael@0: texture->LockRect(0, &lockedRect, nullptr, 0); michael@0: } michael@0: michael@0: uint32_t width = aSize.width; michael@0: if (aFormat == D3DFMT_A8R8G8B8) { michael@0: width *= 4; michael@0: } michael@0: for (int y = 0; y < aSize.height; y++) { michael@0: memcpy((char*)lockedRect.pBits + lockedRect.Pitch * y, michael@0: aData + aStride * y, michael@0: width); michael@0: } michael@0: michael@0: if (deviceEx) { michael@0: surface->UnlockRect(); michael@0: nsRefPtr dstSurface; michael@0: texture->GetSurfaceLevel(0, getter_AddRefs(dstSurface)); michael@0: aDevice->UpdateSurface(surface, nullptr, dstSurface, nullptr); michael@0: } else { michael@0: texture->UnlockRect(0); michael@0: } michael@0: michael@0: return texture.forget(); michael@0: } michael@0: michael@0: static already_AddRefed michael@0: OpenSharedTexture(const D3DSURFACE_DESC& aDesc, michael@0: HANDLE aShareHandle, michael@0: IDirect3DDevice9 *aDevice) michael@0: { michael@0: MOZ_ASSERT(aDesc.Format == D3DFMT_X8R8G8B8); michael@0: michael@0: // Open the frame from DXVA's device in our device using the resource michael@0: // sharing handle. michael@0: nsRefPtr sharedTexture; michael@0: HRESULT hr = aDevice->CreateTexture(aDesc.Width, michael@0: aDesc.Height, michael@0: 1, michael@0: D3DUSAGE_RENDERTARGET, michael@0: D3DFMT_X8R8G8B8, michael@0: D3DPOOL_DEFAULT, michael@0: getter_AddRefs(sharedTexture), michael@0: &aShareHandle); michael@0: if (FAILED(hr)) { michael@0: NS_WARNING("Failed to open shared texture on our device"); michael@0: } michael@0: return sharedTexture.forget(); michael@0: } michael@0: michael@0: static already_AddRefed michael@0: SurfaceToTexture(IDirect3DDevice9 *aDevice, michael@0: SourceSurface *aSurface, michael@0: const IntSize &aSize) michael@0: { michael@0: RefPtr dataSurface = aSurface->GetDataSurface(); michael@0: if (!dataSurface) { michael@0: return nullptr; michael@0: } michael@0: DataSourceSurface::MappedSurface map; michael@0: if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map)) { michael@0: return nullptr; michael@0: } michael@0: nsRefPtr texture = michael@0: DataToTexture(aDevice, map.mData, map.mStride, aSize, michael@0: D3dFormatForSurfaceFormat(dataSurface->GetFormat())); michael@0: dataSurface->Unmap(); michael@0: return texture.forget(); michael@0: } michael@0: michael@0: static void AllocateTexturesYCbCr(PlanarYCbCrImage *aImage, michael@0: IDirect3DDevice9 *aDevice, michael@0: LayerManagerD3D9 *aManager) michael@0: { michael@0: nsAutoPtr backendData( michael@0: new PlanarYCbCrD3D9BackendData); michael@0: michael@0: const PlanarYCbCrData *data = aImage->GetData(); michael@0: michael@0: D3DLOCKED_RECT lockrectY; michael@0: D3DLOCKED_RECT lockrectCb; michael@0: D3DLOCKED_RECT lockrectCr; michael@0: uint8_t* src; michael@0: uint8_t* dest; michael@0: michael@0: nsRefPtr tmpSurfaceY; michael@0: nsRefPtr tmpSurfaceCb; michael@0: nsRefPtr tmpSurfaceCr; michael@0: michael@0: nsRefPtr deviceEx; michael@0: aDevice->QueryInterface(IID_IDirect3DDevice9Ex, michael@0: getter_AddRefs(deviceEx)); michael@0: michael@0: bool isD3D9Ex = deviceEx; michael@0: michael@0: if (isD3D9Ex) { michael@0: nsRefPtr tmpYTexture; michael@0: nsRefPtr tmpCbTexture; michael@0: nsRefPtr tmpCrTexture; michael@0: // D3D9Ex does not support the managed pool, could use dynamic textures michael@0: // here. But since an Image is immutable static textures are probably a michael@0: // better idea. michael@0: michael@0: HRESULT hr; michael@0: hr = aDevice->CreateTexture(data->mYSize.width, data->mYSize.height, michael@0: 1, 0, D3DFMT_A8, D3DPOOL_DEFAULT, michael@0: getter_AddRefs(backendData->mYTexture), nullptr); michael@0: if (!FAILED(hr)) { michael@0: hr = aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height, michael@0: 1, 0, D3DFMT_A8, D3DPOOL_DEFAULT, michael@0: getter_AddRefs(backendData->mCbTexture), nullptr); michael@0: } michael@0: if (!FAILED(hr)) { michael@0: hr = aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height, michael@0: 1, 0, D3DFMT_A8, D3DPOOL_DEFAULT, michael@0: getter_AddRefs(backendData->mCrTexture), nullptr); michael@0: } michael@0: if (!FAILED(hr)) { michael@0: hr = aDevice->CreateTexture(data->mYSize.width, data->mYSize.height, michael@0: 1, 0, D3DFMT_A8, D3DPOOL_SYSTEMMEM, michael@0: getter_AddRefs(tmpYTexture), nullptr); michael@0: } michael@0: if (!FAILED(hr)) { michael@0: hr = aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height, michael@0: 1, 0, D3DFMT_A8, D3DPOOL_SYSTEMMEM, michael@0: getter_AddRefs(tmpCbTexture), nullptr); michael@0: } michael@0: if (!FAILED(hr)) { michael@0: hr = aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height, michael@0: 1, 0, D3DFMT_A8, D3DPOOL_SYSTEMMEM, michael@0: getter_AddRefs(tmpCrTexture), nullptr); michael@0: } michael@0: michael@0: if (FAILED(hr)) { michael@0: aManager->ReportFailure(NS_LITERAL_CSTRING("PlanarYCbCrImageD3D9::AllocateTextures(): Failed to create texture (isD3D9Ex)"), michael@0: hr); michael@0: return; michael@0: } michael@0: michael@0: tmpYTexture->GetSurfaceLevel(0, getter_AddRefs(tmpSurfaceY)); michael@0: tmpCbTexture->GetSurfaceLevel(0, getter_AddRefs(tmpSurfaceCb)); michael@0: tmpCrTexture->GetSurfaceLevel(0, getter_AddRefs(tmpSurfaceCr)); michael@0: tmpSurfaceY->LockRect(&lockrectY, nullptr, 0); michael@0: tmpSurfaceCb->LockRect(&lockrectCb, nullptr, 0); michael@0: tmpSurfaceCr->LockRect(&lockrectCr, nullptr, 0); michael@0: } else { michael@0: HRESULT hr; michael@0: hr = aDevice->CreateTexture(data->mYSize.width, data->mYSize.height, michael@0: 1, 0, D3DFMT_A8, D3DPOOL_MANAGED, michael@0: getter_AddRefs(backendData->mYTexture), nullptr); michael@0: if (!FAILED(hr)) { michael@0: aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height, michael@0: 1, 0, D3DFMT_A8, D3DPOOL_MANAGED, michael@0: getter_AddRefs(backendData->mCbTexture), nullptr); michael@0: } michael@0: if (!FAILED(hr)) { michael@0: aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height, michael@0: 1, 0, D3DFMT_A8, D3DPOOL_MANAGED, michael@0: getter_AddRefs(backendData->mCrTexture), nullptr); michael@0: } michael@0: michael@0: if (FAILED(hr)) { michael@0: aManager->ReportFailure(NS_LITERAL_CSTRING("PlanarYCbCrImageD3D9::AllocateTextures(): Failed to create texture (!isD3D9Ex)"), michael@0: hr); michael@0: return; michael@0: } michael@0: michael@0: /* lock the entire texture */ michael@0: backendData->mYTexture->LockRect(0, &lockrectY, nullptr, 0); michael@0: backendData->mCbTexture->LockRect(0, &lockrectCb, nullptr, 0); michael@0: backendData->mCrTexture->LockRect(0, &lockrectCr, nullptr, 0); michael@0: } michael@0: michael@0: src = data->mYChannel; michael@0: //FIX cast michael@0: dest = (uint8_t*)lockrectY.pBits; michael@0: michael@0: // copy over data michael@0: for (int h=0; hmYSize.height; h++) { michael@0: memcpy(dest, src, data->mYSize.width); michael@0: dest += lockrectY.Pitch; michael@0: src += data->mYStride; michael@0: } michael@0: michael@0: src = data->mCbChannel; michael@0: //FIX cast michael@0: dest = (uint8_t*)lockrectCb.pBits; michael@0: michael@0: // copy over data michael@0: for (int h=0; hmCbCrSize.height; h++) { michael@0: memcpy(dest, src, data->mCbCrSize.width); michael@0: dest += lockrectCb.Pitch; michael@0: src += data->mCbCrStride; michael@0: } michael@0: michael@0: src = data->mCrChannel; michael@0: //FIX cast michael@0: dest = (uint8_t*)lockrectCr.pBits; michael@0: michael@0: // copy over data michael@0: for (int h=0; hmCbCrSize.height; h++) { michael@0: memcpy(dest, src, data->mCbCrSize.width); michael@0: dest += lockrectCr.Pitch; michael@0: src += data->mCbCrStride; michael@0: } michael@0: michael@0: if (isD3D9Ex) { michael@0: tmpSurfaceY->UnlockRect(); michael@0: tmpSurfaceCb->UnlockRect(); michael@0: tmpSurfaceCr->UnlockRect(); michael@0: nsRefPtr dstSurface; michael@0: backendData->mYTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface)); michael@0: aDevice->UpdateSurface(tmpSurfaceY, nullptr, dstSurface, nullptr); michael@0: backendData->mCbTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface)); michael@0: aDevice->UpdateSurface(tmpSurfaceCb, nullptr, dstSurface, nullptr); michael@0: backendData->mCrTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface)); michael@0: aDevice->UpdateSurface(tmpSurfaceCr, nullptr, dstSurface, nullptr); michael@0: } else { michael@0: backendData->mYTexture->UnlockRect(0); michael@0: backendData->mCbTexture->UnlockRect(0); michael@0: backendData->mCrTexture->UnlockRect(0); michael@0: } michael@0: michael@0: aImage->SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9, backendData.forget()); michael@0: } michael@0: michael@0: Layer* michael@0: ImageLayerD3D9::GetLayer() michael@0: { michael@0: return this; michael@0: } michael@0: michael@0: /* michael@0: * Returns a texture which backs aImage michael@0: * Will only work if aImage is a cairo or remote image. michael@0: * Returns nullptr if unsuccessful. michael@0: * If successful, aHasAlpha will be set to true if the texture has an michael@0: * alpha component, false otherwise. michael@0: */ michael@0: IDirect3DTexture9* michael@0: ImageLayerD3D9::GetTexture(Image *aImage, bool& aHasAlpha) michael@0: { michael@0: NS_ASSERTION(aImage, "Null image."); michael@0: michael@0: if (aImage->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP) { michael@0: RemoteBitmapImage *remoteImage = michael@0: static_cast(aImage); michael@0: michael@0: if (!aImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9)) { michael@0: nsAutoPtr dat(new TextureD3D9BackendData()); michael@0: dat->mTexture = DataToTexture(device(), remoteImage->mData, remoteImage->mStride, remoteImage->mSize, D3DFMT_A8R8G8B8); michael@0: if (dat->mTexture) { michael@0: aImage->SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9, dat.forget()); michael@0: } michael@0: } michael@0: michael@0: aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32; michael@0: } else if (aImage->GetFormat() == ImageFormat::CAIRO_SURFACE) { michael@0: CairoImage *cairoImage = michael@0: static_cast(aImage); michael@0: michael@0: RefPtr surf = cairoImage->GetAsSourceSurface(); michael@0: if (!surf) { michael@0: return nullptr; michael@0: } michael@0: michael@0: if (!aImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9)) { michael@0: nsAutoPtr dat(new TextureD3D9BackendData()); michael@0: dat->mTexture = SurfaceToTexture(device(), surf, cairoImage->GetSize()); michael@0: if (dat->mTexture) { michael@0: aImage->SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9, dat.forget()); michael@0: } michael@0: } michael@0: michael@0: aHasAlpha = surf->GetFormat() == SurfaceFormat::B8G8R8A8; michael@0: } else if (aImage->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE) { michael@0: if (!aImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9)) { michael@0: // The texture in which the frame is stored belongs to DXVA's D3D9 device. michael@0: // We need to open it on our device before we can use it. michael@0: nsAutoPtr backendData(new TextureD3D9BackendData()); michael@0: D3D9SurfaceImage* image = static_cast(aImage); michael@0: backendData->mTexture = OpenSharedTexture(image->GetDesc(), image->GetShareHandle(), device()); michael@0: if (backendData->mTexture) { michael@0: aImage->SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9, backendData.forget()); michael@0: } michael@0: } michael@0: aHasAlpha = false; michael@0: } else { michael@0: NS_WARNING("Inappropriate image type."); michael@0: return nullptr; michael@0: } michael@0: michael@0: TextureD3D9BackendData *data = michael@0: static_cast(aImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9)); michael@0: michael@0: if (!data) { michael@0: return nullptr; michael@0: } michael@0: michael@0: nsRefPtr dev; michael@0: data->mTexture->GetDevice(getter_AddRefs(dev)); michael@0: if (dev != device()) { michael@0: return nullptr; michael@0: } michael@0: michael@0: return data->mTexture; michael@0: } michael@0: michael@0: void michael@0: ImageLayerD3D9::RenderLayer() michael@0: { michael@0: ImageContainer *container = GetContainer(); michael@0: if (!container || mD3DManager->CompositingDisabled()) { michael@0: return; michael@0: } michael@0: michael@0: AutoLockImage autoLock(container); michael@0: michael@0: Image *image = autoLock.GetImage(); michael@0: if (!image) { michael@0: return; michael@0: } michael@0: michael@0: SetShaderTransformAndOpacity(); michael@0: michael@0: gfx::IntSize size = image->GetSize(); michael@0: michael@0: if (image->GetFormat() == ImageFormat::CAIRO_SURFACE || michael@0: image->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP || michael@0: image->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE) michael@0: { michael@0: NS_ASSERTION(image->GetFormat() != ImageFormat::CAIRO_SURFACE || michael@0: !static_cast(image)->mSourceSurface || michael@0: static_cast(image)->mSourceSurface->GetFormat() != SurfaceFormat::A8, michael@0: "Image layer has alpha image"); michael@0: michael@0: bool hasAlpha = false; michael@0: nsRefPtr texture = GetTexture(image, hasAlpha); michael@0: michael@0: device()->SetVertexShaderConstantF(CBvLayerQuad, michael@0: ShaderConstantRect(0, michael@0: 0, michael@0: size.width, michael@0: size.height), michael@0: 1); michael@0: michael@0: if (hasAlpha) { michael@0: mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER, GetMaskLayer()); michael@0: } else { michael@0: mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER, GetMaskLayer()); michael@0: } michael@0: michael@0: if (mFilter == GraphicsFilter::FILTER_NEAREST) { michael@0: device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); michael@0: device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); michael@0: } michael@0: device()->SetTexture(0, texture); michael@0: michael@0: image = nullptr; michael@0: autoLock.Unlock(); michael@0: michael@0: device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); michael@0: if (mFilter == GraphicsFilter::FILTER_NEAREST) { michael@0: device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); michael@0: device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); michael@0: } michael@0: } else { michael@0: PlanarYCbCrImage *yuvImage = michael@0: static_cast(image); michael@0: michael@0: if (!yuvImage->IsValid()) { michael@0: return; michael@0: } michael@0: michael@0: if (!yuvImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9)) { michael@0: AllocateTexturesYCbCr(yuvImage, device(), mD3DManager); michael@0: } michael@0: michael@0: PlanarYCbCrD3D9BackendData *data = michael@0: static_cast(yuvImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9)); michael@0: michael@0: if (!data) { michael@0: return; michael@0: } michael@0: michael@0: nsRefPtr dev; michael@0: data->mYTexture->GetDevice(getter_AddRefs(dev)); michael@0: if (dev != device()) { michael@0: return; michael@0: } michael@0: michael@0: device()->SetVertexShaderConstantF(CBvLayerQuad, michael@0: ShaderConstantRect(0, michael@0: 0, michael@0: size.width, michael@0: size.height), michael@0: 1); michael@0: michael@0: device()->SetVertexShaderConstantF(CBvTextureCoords, michael@0: ShaderConstantRect( michael@0: (float)yuvImage->GetData()->mPicX / yuvImage->GetData()->mYSize.width, michael@0: (float)yuvImage->GetData()->mPicY / yuvImage->GetData()->mYSize.height, michael@0: (float)yuvImage->GetData()->mPicSize.width / yuvImage->GetData()->mYSize.width, michael@0: (float)yuvImage->GetData()->mPicSize.height / yuvImage->GetData()->mYSize.height michael@0: ), michael@0: 1); michael@0: michael@0: mD3DManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER, GetMaskLayer()); michael@0: michael@0: /* michael@0: * Send 3d control data and metadata michael@0: */ michael@0: if (mD3DManager->GetNv3DVUtils()) { michael@0: Nv_Stereo_Mode mode; michael@0: switch (yuvImage->GetData()->mStereoMode) { michael@0: case StereoMode::LEFT_RIGHT: michael@0: mode = NV_STEREO_MODE_LEFT_RIGHT; michael@0: break; michael@0: case StereoMode::RIGHT_LEFT: michael@0: mode = NV_STEREO_MODE_RIGHT_LEFT; michael@0: break; michael@0: case StereoMode::BOTTOM_TOP: michael@0: mode = NV_STEREO_MODE_BOTTOM_TOP; michael@0: break; michael@0: case StereoMode::TOP_BOTTOM: michael@0: mode = NV_STEREO_MODE_TOP_BOTTOM; michael@0: break; michael@0: case StereoMode::MONO: michael@0: mode = NV_STEREO_MODE_MONO; michael@0: break; michael@0: } michael@0: michael@0: // Send control data even in mono case so driver knows to leave stereo mode. michael@0: mD3DManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE); michael@0: michael@0: if (yuvImage->GetData()->mStereoMode != StereoMode::MONO) { michael@0: mD3DManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE); michael@0: michael@0: nsRefPtr renderTarget; michael@0: device()->GetRenderTarget(0, getter_AddRefs(renderTarget)); michael@0: mD3DManager->GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)yuvImage->GetSize().width, michael@0: (unsigned int)yuvImage->GetSize().height, (HANDLE)(data->mYTexture), (HANDLE)(renderTarget)); michael@0: } michael@0: } michael@0: michael@0: // Linear scaling is default here, adhering to mFilter is difficult since michael@0: // presumably even with point filtering we'll still want chroma upsampling michael@0: // to be linear. In the current approach we can't. michael@0: device()->SetTexture(0, data->mYTexture); michael@0: device()->SetTexture(1, data->mCbTexture); michael@0: device()->SetTexture(2, data->mCrTexture); michael@0: michael@0: image = nullptr; michael@0: data = nullptr; michael@0: autoLock.Unlock(); michael@0: michael@0: device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); michael@0: michael@0: device()->SetVertexShaderConstantF(CBvTextureCoords, michael@0: ShaderConstantRect(0, 0, 1.0f, 1.0f), 1); michael@0: } michael@0: michael@0: GetContainer()->NotifyPaintedImage(image); michael@0: } michael@0: michael@0: already_AddRefed michael@0: ImageLayerD3D9::GetAsTexture(gfx::IntSize* aSize) michael@0: { michael@0: if (!GetContainer()) { michael@0: return nullptr; michael@0: } michael@0: michael@0: AutoLockImage autoLock(GetContainer()); michael@0: michael@0: Image *image = autoLock.GetImage(); michael@0: michael@0: if (!image) { michael@0: return nullptr; michael@0: } michael@0: michael@0: if (image->GetFormat() != ImageFormat::CAIRO_SURFACE && michael@0: image->GetFormat() != ImageFormat::REMOTE_IMAGE_BITMAP) { michael@0: return nullptr; michael@0: } michael@0: michael@0: bool dontCare; michael@0: *aSize = image->GetSize(); michael@0: nsRefPtr result = GetTexture(image, dontCare); michael@0: return result.forget(); michael@0: } michael@0: michael@0: } /* layers */ michael@0: } /* mozilla */