|
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 * This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "mozilla/gfx/2D.h" |
|
7 #include "mozilla/gfx/Point.h" |
|
8 #include "mozilla/RefPtr.h" |
|
9 #include "mozilla/layers/PLayerTransaction.h" |
|
10 #include "gfxSharedImageSurface.h" |
|
11 |
|
12 #include "ImageLayerD3D9.h" |
|
13 #include "ThebesLayerD3D9.h" |
|
14 #include "gfxPlatform.h" |
|
15 #include "gfx2DGlue.h" |
|
16 #include "yuv_convert.h" |
|
17 #include "nsIServiceManager.h" |
|
18 #include "nsIConsoleService.h" |
|
19 #include "Nv3DVUtils.h" |
|
20 #include "D3D9SurfaceImage.h" |
|
21 |
|
22 namespace mozilla { |
|
23 namespace layers { |
|
24 |
|
25 using namespace mozilla::gfx; |
|
26 |
|
27 static inline _D3DFORMAT |
|
28 D3dFormatForSurfaceFormat(SurfaceFormat aFormat) |
|
29 { |
|
30 if (aFormat == SurfaceFormat::A8) { |
|
31 return D3DFMT_A8; |
|
32 } |
|
33 |
|
34 return D3DFMT_A8R8G8B8; |
|
35 } |
|
36 |
|
37 static already_AddRefed<IDirect3DTexture9> |
|
38 DataToTexture(IDirect3DDevice9 *aDevice, |
|
39 unsigned char *aData, |
|
40 int aStride, |
|
41 const IntSize &aSize, |
|
42 _D3DFORMAT aFormat) |
|
43 { |
|
44 nsRefPtr<IDirect3DTexture9> texture; |
|
45 nsRefPtr<IDirect3DDevice9Ex> deviceEx; |
|
46 aDevice->QueryInterface(IID_IDirect3DDevice9Ex, |
|
47 (void**)getter_AddRefs(deviceEx)); |
|
48 |
|
49 nsRefPtr<IDirect3DSurface9> surface; |
|
50 D3DLOCKED_RECT lockedRect; |
|
51 if (deviceEx) { |
|
52 // D3D9Ex doesn't support managed textures. We could use dynamic textures |
|
53 // here but since Images are immutable that probably isn't such a great |
|
54 // idea. |
|
55 if (FAILED(aDevice-> |
|
56 CreateTexture(aSize.width, aSize.height, |
|
57 1, 0, aFormat, D3DPOOL_DEFAULT, |
|
58 getter_AddRefs(texture), nullptr))) |
|
59 { |
|
60 return nullptr; |
|
61 } |
|
62 |
|
63 nsRefPtr<IDirect3DTexture9> tmpTexture; |
|
64 if (FAILED(aDevice-> |
|
65 CreateTexture(aSize.width, aSize.height, |
|
66 1, 0, aFormat, D3DPOOL_SYSTEMMEM, |
|
67 getter_AddRefs(tmpTexture), nullptr))) |
|
68 { |
|
69 return nullptr; |
|
70 } |
|
71 |
|
72 tmpTexture->GetSurfaceLevel(0, getter_AddRefs(surface)); |
|
73 surface->LockRect(&lockedRect, nullptr, 0); |
|
74 NS_ASSERTION(lockedRect.pBits, "Could not lock surface"); |
|
75 } else { |
|
76 if (FAILED(aDevice-> |
|
77 CreateTexture(aSize.width, aSize.height, |
|
78 1, 0, aFormat, D3DPOOL_MANAGED, |
|
79 getter_AddRefs(texture), nullptr))) |
|
80 { |
|
81 return nullptr; |
|
82 } |
|
83 |
|
84 /* lock the entire texture */ |
|
85 texture->LockRect(0, &lockedRect, nullptr, 0); |
|
86 } |
|
87 |
|
88 uint32_t width = aSize.width; |
|
89 if (aFormat == D3DFMT_A8R8G8B8) { |
|
90 width *= 4; |
|
91 } |
|
92 for (int y = 0; y < aSize.height; y++) { |
|
93 memcpy((char*)lockedRect.pBits + lockedRect.Pitch * y, |
|
94 aData + aStride * y, |
|
95 width); |
|
96 } |
|
97 |
|
98 if (deviceEx) { |
|
99 surface->UnlockRect(); |
|
100 nsRefPtr<IDirect3DSurface9> dstSurface; |
|
101 texture->GetSurfaceLevel(0, getter_AddRefs(dstSurface)); |
|
102 aDevice->UpdateSurface(surface, nullptr, dstSurface, nullptr); |
|
103 } else { |
|
104 texture->UnlockRect(0); |
|
105 } |
|
106 |
|
107 return texture.forget(); |
|
108 } |
|
109 |
|
110 static already_AddRefed<IDirect3DTexture9> |
|
111 OpenSharedTexture(const D3DSURFACE_DESC& aDesc, |
|
112 HANDLE aShareHandle, |
|
113 IDirect3DDevice9 *aDevice) |
|
114 { |
|
115 MOZ_ASSERT(aDesc.Format == D3DFMT_X8R8G8B8); |
|
116 |
|
117 // Open the frame from DXVA's device in our device using the resource |
|
118 // sharing handle. |
|
119 nsRefPtr<IDirect3DTexture9> sharedTexture; |
|
120 HRESULT hr = aDevice->CreateTexture(aDesc.Width, |
|
121 aDesc.Height, |
|
122 1, |
|
123 D3DUSAGE_RENDERTARGET, |
|
124 D3DFMT_X8R8G8B8, |
|
125 D3DPOOL_DEFAULT, |
|
126 getter_AddRefs(sharedTexture), |
|
127 &aShareHandle); |
|
128 if (FAILED(hr)) { |
|
129 NS_WARNING("Failed to open shared texture on our device"); |
|
130 } |
|
131 return sharedTexture.forget(); |
|
132 } |
|
133 |
|
134 static already_AddRefed<IDirect3DTexture9> |
|
135 SurfaceToTexture(IDirect3DDevice9 *aDevice, |
|
136 SourceSurface *aSurface, |
|
137 const IntSize &aSize) |
|
138 { |
|
139 RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface(); |
|
140 if (!dataSurface) { |
|
141 return nullptr; |
|
142 } |
|
143 DataSourceSurface::MappedSurface map; |
|
144 if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map)) { |
|
145 return nullptr; |
|
146 } |
|
147 nsRefPtr<IDirect3DTexture9> texture = |
|
148 DataToTexture(aDevice, map.mData, map.mStride, aSize, |
|
149 D3dFormatForSurfaceFormat(dataSurface->GetFormat())); |
|
150 dataSurface->Unmap(); |
|
151 return texture.forget(); |
|
152 } |
|
153 |
|
154 static void AllocateTexturesYCbCr(PlanarYCbCrImage *aImage, |
|
155 IDirect3DDevice9 *aDevice, |
|
156 LayerManagerD3D9 *aManager) |
|
157 { |
|
158 nsAutoPtr<PlanarYCbCrD3D9BackendData> backendData( |
|
159 new PlanarYCbCrD3D9BackendData); |
|
160 |
|
161 const PlanarYCbCrData *data = aImage->GetData(); |
|
162 |
|
163 D3DLOCKED_RECT lockrectY; |
|
164 D3DLOCKED_RECT lockrectCb; |
|
165 D3DLOCKED_RECT lockrectCr; |
|
166 uint8_t* src; |
|
167 uint8_t* dest; |
|
168 |
|
169 nsRefPtr<IDirect3DSurface9> tmpSurfaceY; |
|
170 nsRefPtr<IDirect3DSurface9> tmpSurfaceCb; |
|
171 nsRefPtr<IDirect3DSurface9> tmpSurfaceCr; |
|
172 |
|
173 nsRefPtr<IDirect3DDevice9Ex> deviceEx; |
|
174 aDevice->QueryInterface(IID_IDirect3DDevice9Ex, |
|
175 getter_AddRefs(deviceEx)); |
|
176 |
|
177 bool isD3D9Ex = deviceEx; |
|
178 |
|
179 if (isD3D9Ex) { |
|
180 nsRefPtr<IDirect3DTexture9> tmpYTexture; |
|
181 nsRefPtr<IDirect3DTexture9> tmpCbTexture; |
|
182 nsRefPtr<IDirect3DTexture9> tmpCrTexture; |
|
183 // D3D9Ex does not support the managed pool, could use dynamic textures |
|
184 // here. But since an Image is immutable static textures are probably a |
|
185 // better idea. |
|
186 |
|
187 HRESULT hr; |
|
188 hr = aDevice->CreateTexture(data->mYSize.width, data->mYSize.height, |
|
189 1, 0, D3DFMT_A8, D3DPOOL_DEFAULT, |
|
190 getter_AddRefs(backendData->mYTexture), nullptr); |
|
191 if (!FAILED(hr)) { |
|
192 hr = aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height, |
|
193 1, 0, D3DFMT_A8, D3DPOOL_DEFAULT, |
|
194 getter_AddRefs(backendData->mCbTexture), nullptr); |
|
195 } |
|
196 if (!FAILED(hr)) { |
|
197 hr = aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height, |
|
198 1, 0, D3DFMT_A8, D3DPOOL_DEFAULT, |
|
199 getter_AddRefs(backendData->mCrTexture), nullptr); |
|
200 } |
|
201 if (!FAILED(hr)) { |
|
202 hr = aDevice->CreateTexture(data->mYSize.width, data->mYSize.height, |
|
203 1, 0, D3DFMT_A8, D3DPOOL_SYSTEMMEM, |
|
204 getter_AddRefs(tmpYTexture), nullptr); |
|
205 } |
|
206 if (!FAILED(hr)) { |
|
207 hr = aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height, |
|
208 1, 0, D3DFMT_A8, D3DPOOL_SYSTEMMEM, |
|
209 getter_AddRefs(tmpCbTexture), nullptr); |
|
210 } |
|
211 if (!FAILED(hr)) { |
|
212 hr = aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height, |
|
213 1, 0, D3DFMT_A8, D3DPOOL_SYSTEMMEM, |
|
214 getter_AddRefs(tmpCrTexture), nullptr); |
|
215 } |
|
216 |
|
217 if (FAILED(hr)) { |
|
218 aManager->ReportFailure(NS_LITERAL_CSTRING("PlanarYCbCrImageD3D9::AllocateTextures(): Failed to create texture (isD3D9Ex)"), |
|
219 hr); |
|
220 return; |
|
221 } |
|
222 |
|
223 tmpYTexture->GetSurfaceLevel(0, getter_AddRefs(tmpSurfaceY)); |
|
224 tmpCbTexture->GetSurfaceLevel(0, getter_AddRefs(tmpSurfaceCb)); |
|
225 tmpCrTexture->GetSurfaceLevel(0, getter_AddRefs(tmpSurfaceCr)); |
|
226 tmpSurfaceY->LockRect(&lockrectY, nullptr, 0); |
|
227 tmpSurfaceCb->LockRect(&lockrectCb, nullptr, 0); |
|
228 tmpSurfaceCr->LockRect(&lockrectCr, nullptr, 0); |
|
229 } else { |
|
230 HRESULT hr; |
|
231 hr = aDevice->CreateTexture(data->mYSize.width, data->mYSize.height, |
|
232 1, 0, D3DFMT_A8, D3DPOOL_MANAGED, |
|
233 getter_AddRefs(backendData->mYTexture), nullptr); |
|
234 if (!FAILED(hr)) { |
|
235 aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height, |
|
236 1, 0, D3DFMT_A8, D3DPOOL_MANAGED, |
|
237 getter_AddRefs(backendData->mCbTexture), nullptr); |
|
238 } |
|
239 if (!FAILED(hr)) { |
|
240 aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height, |
|
241 1, 0, D3DFMT_A8, D3DPOOL_MANAGED, |
|
242 getter_AddRefs(backendData->mCrTexture), nullptr); |
|
243 } |
|
244 |
|
245 if (FAILED(hr)) { |
|
246 aManager->ReportFailure(NS_LITERAL_CSTRING("PlanarYCbCrImageD3D9::AllocateTextures(): Failed to create texture (!isD3D9Ex)"), |
|
247 hr); |
|
248 return; |
|
249 } |
|
250 |
|
251 /* lock the entire texture */ |
|
252 backendData->mYTexture->LockRect(0, &lockrectY, nullptr, 0); |
|
253 backendData->mCbTexture->LockRect(0, &lockrectCb, nullptr, 0); |
|
254 backendData->mCrTexture->LockRect(0, &lockrectCr, nullptr, 0); |
|
255 } |
|
256 |
|
257 src = data->mYChannel; |
|
258 //FIX cast |
|
259 dest = (uint8_t*)lockrectY.pBits; |
|
260 |
|
261 // copy over data |
|
262 for (int h=0; h<data->mYSize.height; h++) { |
|
263 memcpy(dest, src, data->mYSize.width); |
|
264 dest += lockrectY.Pitch; |
|
265 src += data->mYStride; |
|
266 } |
|
267 |
|
268 src = data->mCbChannel; |
|
269 //FIX cast |
|
270 dest = (uint8_t*)lockrectCb.pBits; |
|
271 |
|
272 // copy over data |
|
273 for (int h=0; h<data->mCbCrSize.height; h++) { |
|
274 memcpy(dest, src, data->mCbCrSize.width); |
|
275 dest += lockrectCb.Pitch; |
|
276 src += data->mCbCrStride; |
|
277 } |
|
278 |
|
279 src = data->mCrChannel; |
|
280 //FIX cast |
|
281 dest = (uint8_t*)lockrectCr.pBits; |
|
282 |
|
283 // copy over data |
|
284 for (int h=0; h<data->mCbCrSize.height; h++) { |
|
285 memcpy(dest, src, data->mCbCrSize.width); |
|
286 dest += lockrectCr.Pitch; |
|
287 src += data->mCbCrStride; |
|
288 } |
|
289 |
|
290 if (isD3D9Ex) { |
|
291 tmpSurfaceY->UnlockRect(); |
|
292 tmpSurfaceCb->UnlockRect(); |
|
293 tmpSurfaceCr->UnlockRect(); |
|
294 nsRefPtr<IDirect3DSurface9> dstSurface; |
|
295 backendData->mYTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface)); |
|
296 aDevice->UpdateSurface(tmpSurfaceY, nullptr, dstSurface, nullptr); |
|
297 backendData->mCbTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface)); |
|
298 aDevice->UpdateSurface(tmpSurfaceCb, nullptr, dstSurface, nullptr); |
|
299 backendData->mCrTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface)); |
|
300 aDevice->UpdateSurface(tmpSurfaceCr, nullptr, dstSurface, nullptr); |
|
301 } else { |
|
302 backendData->mYTexture->UnlockRect(0); |
|
303 backendData->mCbTexture->UnlockRect(0); |
|
304 backendData->mCrTexture->UnlockRect(0); |
|
305 } |
|
306 |
|
307 aImage->SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9, backendData.forget()); |
|
308 } |
|
309 |
|
310 Layer* |
|
311 ImageLayerD3D9::GetLayer() |
|
312 { |
|
313 return this; |
|
314 } |
|
315 |
|
316 /* |
|
317 * Returns a texture which backs aImage |
|
318 * Will only work if aImage is a cairo or remote image. |
|
319 * Returns nullptr if unsuccessful. |
|
320 * If successful, aHasAlpha will be set to true if the texture has an |
|
321 * alpha component, false otherwise. |
|
322 */ |
|
323 IDirect3DTexture9* |
|
324 ImageLayerD3D9::GetTexture(Image *aImage, bool& aHasAlpha) |
|
325 { |
|
326 NS_ASSERTION(aImage, "Null image."); |
|
327 |
|
328 if (aImage->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP) { |
|
329 RemoteBitmapImage *remoteImage = |
|
330 static_cast<RemoteBitmapImage*>(aImage); |
|
331 |
|
332 if (!aImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9)) { |
|
333 nsAutoPtr<TextureD3D9BackendData> dat(new TextureD3D9BackendData()); |
|
334 dat->mTexture = DataToTexture(device(), remoteImage->mData, remoteImage->mStride, remoteImage->mSize, D3DFMT_A8R8G8B8); |
|
335 if (dat->mTexture) { |
|
336 aImage->SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9, dat.forget()); |
|
337 } |
|
338 } |
|
339 |
|
340 aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32; |
|
341 } else if (aImage->GetFormat() == ImageFormat::CAIRO_SURFACE) { |
|
342 CairoImage *cairoImage = |
|
343 static_cast<CairoImage*>(aImage); |
|
344 |
|
345 RefPtr<SourceSurface> surf = cairoImage->GetAsSourceSurface(); |
|
346 if (!surf) { |
|
347 return nullptr; |
|
348 } |
|
349 |
|
350 if (!aImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9)) { |
|
351 nsAutoPtr<TextureD3D9BackendData> dat(new TextureD3D9BackendData()); |
|
352 dat->mTexture = SurfaceToTexture(device(), surf, cairoImage->GetSize()); |
|
353 if (dat->mTexture) { |
|
354 aImage->SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9, dat.forget()); |
|
355 } |
|
356 } |
|
357 |
|
358 aHasAlpha = surf->GetFormat() == SurfaceFormat::B8G8R8A8; |
|
359 } else if (aImage->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE) { |
|
360 if (!aImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9)) { |
|
361 // The texture in which the frame is stored belongs to DXVA's D3D9 device. |
|
362 // We need to open it on our device before we can use it. |
|
363 nsAutoPtr<TextureD3D9BackendData> backendData(new TextureD3D9BackendData()); |
|
364 D3D9SurfaceImage* image = static_cast<D3D9SurfaceImage*>(aImage); |
|
365 backendData->mTexture = OpenSharedTexture(image->GetDesc(), image->GetShareHandle(), device()); |
|
366 if (backendData->mTexture) { |
|
367 aImage->SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9, backendData.forget()); |
|
368 } |
|
369 } |
|
370 aHasAlpha = false; |
|
371 } else { |
|
372 NS_WARNING("Inappropriate image type."); |
|
373 return nullptr; |
|
374 } |
|
375 |
|
376 TextureD3D9BackendData *data = |
|
377 static_cast<TextureD3D9BackendData*>(aImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9)); |
|
378 |
|
379 if (!data) { |
|
380 return nullptr; |
|
381 } |
|
382 |
|
383 nsRefPtr<IDirect3DDevice9> dev; |
|
384 data->mTexture->GetDevice(getter_AddRefs(dev)); |
|
385 if (dev != device()) { |
|
386 return nullptr; |
|
387 } |
|
388 |
|
389 return data->mTexture; |
|
390 } |
|
391 |
|
392 void |
|
393 ImageLayerD3D9::RenderLayer() |
|
394 { |
|
395 ImageContainer *container = GetContainer(); |
|
396 if (!container || mD3DManager->CompositingDisabled()) { |
|
397 return; |
|
398 } |
|
399 |
|
400 AutoLockImage autoLock(container); |
|
401 |
|
402 Image *image = autoLock.GetImage(); |
|
403 if (!image) { |
|
404 return; |
|
405 } |
|
406 |
|
407 SetShaderTransformAndOpacity(); |
|
408 |
|
409 gfx::IntSize size = image->GetSize(); |
|
410 |
|
411 if (image->GetFormat() == ImageFormat::CAIRO_SURFACE || |
|
412 image->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP || |
|
413 image->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE) |
|
414 { |
|
415 NS_ASSERTION(image->GetFormat() != ImageFormat::CAIRO_SURFACE || |
|
416 !static_cast<CairoImage*>(image)->mSourceSurface || |
|
417 static_cast<CairoImage*>(image)->mSourceSurface->GetFormat() != SurfaceFormat::A8, |
|
418 "Image layer has alpha image"); |
|
419 |
|
420 bool hasAlpha = false; |
|
421 nsRefPtr<IDirect3DTexture9> texture = GetTexture(image, hasAlpha); |
|
422 |
|
423 device()->SetVertexShaderConstantF(CBvLayerQuad, |
|
424 ShaderConstantRect(0, |
|
425 0, |
|
426 size.width, |
|
427 size.height), |
|
428 1); |
|
429 |
|
430 if (hasAlpha) { |
|
431 mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER, GetMaskLayer()); |
|
432 } else { |
|
433 mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER, GetMaskLayer()); |
|
434 } |
|
435 |
|
436 if (mFilter == GraphicsFilter::FILTER_NEAREST) { |
|
437 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); |
|
438 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); |
|
439 } |
|
440 device()->SetTexture(0, texture); |
|
441 |
|
442 image = nullptr; |
|
443 autoLock.Unlock(); |
|
444 |
|
445 device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); |
|
446 if (mFilter == GraphicsFilter::FILTER_NEAREST) { |
|
447 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); |
|
448 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); |
|
449 } |
|
450 } else { |
|
451 PlanarYCbCrImage *yuvImage = |
|
452 static_cast<PlanarYCbCrImage*>(image); |
|
453 |
|
454 if (!yuvImage->IsValid()) { |
|
455 return; |
|
456 } |
|
457 |
|
458 if (!yuvImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9)) { |
|
459 AllocateTexturesYCbCr(yuvImage, device(), mD3DManager); |
|
460 } |
|
461 |
|
462 PlanarYCbCrD3D9BackendData *data = |
|
463 static_cast<PlanarYCbCrD3D9BackendData*>(yuvImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9)); |
|
464 |
|
465 if (!data) { |
|
466 return; |
|
467 } |
|
468 |
|
469 nsRefPtr<IDirect3DDevice9> dev; |
|
470 data->mYTexture->GetDevice(getter_AddRefs(dev)); |
|
471 if (dev != device()) { |
|
472 return; |
|
473 } |
|
474 |
|
475 device()->SetVertexShaderConstantF(CBvLayerQuad, |
|
476 ShaderConstantRect(0, |
|
477 0, |
|
478 size.width, |
|
479 size.height), |
|
480 1); |
|
481 |
|
482 device()->SetVertexShaderConstantF(CBvTextureCoords, |
|
483 ShaderConstantRect( |
|
484 (float)yuvImage->GetData()->mPicX / yuvImage->GetData()->mYSize.width, |
|
485 (float)yuvImage->GetData()->mPicY / yuvImage->GetData()->mYSize.height, |
|
486 (float)yuvImage->GetData()->mPicSize.width / yuvImage->GetData()->mYSize.width, |
|
487 (float)yuvImage->GetData()->mPicSize.height / yuvImage->GetData()->mYSize.height |
|
488 ), |
|
489 1); |
|
490 |
|
491 mD3DManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER, GetMaskLayer()); |
|
492 |
|
493 /* |
|
494 * Send 3d control data and metadata |
|
495 */ |
|
496 if (mD3DManager->GetNv3DVUtils()) { |
|
497 Nv_Stereo_Mode mode; |
|
498 switch (yuvImage->GetData()->mStereoMode) { |
|
499 case StereoMode::LEFT_RIGHT: |
|
500 mode = NV_STEREO_MODE_LEFT_RIGHT; |
|
501 break; |
|
502 case StereoMode::RIGHT_LEFT: |
|
503 mode = NV_STEREO_MODE_RIGHT_LEFT; |
|
504 break; |
|
505 case StereoMode::BOTTOM_TOP: |
|
506 mode = NV_STEREO_MODE_BOTTOM_TOP; |
|
507 break; |
|
508 case StereoMode::TOP_BOTTOM: |
|
509 mode = NV_STEREO_MODE_TOP_BOTTOM; |
|
510 break; |
|
511 case StereoMode::MONO: |
|
512 mode = NV_STEREO_MODE_MONO; |
|
513 break; |
|
514 } |
|
515 |
|
516 // Send control data even in mono case so driver knows to leave stereo mode. |
|
517 mD3DManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE); |
|
518 |
|
519 if (yuvImage->GetData()->mStereoMode != StereoMode::MONO) { |
|
520 mD3DManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE); |
|
521 |
|
522 nsRefPtr<IDirect3DSurface9> renderTarget; |
|
523 device()->GetRenderTarget(0, getter_AddRefs(renderTarget)); |
|
524 mD3DManager->GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)yuvImage->GetSize().width, |
|
525 (unsigned int)yuvImage->GetSize().height, (HANDLE)(data->mYTexture), (HANDLE)(renderTarget)); |
|
526 } |
|
527 } |
|
528 |
|
529 // Linear scaling is default here, adhering to mFilter is difficult since |
|
530 // presumably even with point filtering we'll still want chroma upsampling |
|
531 // to be linear. In the current approach we can't. |
|
532 device()->SetTexture(0, data->mYTexture); |
|
533 device()->SetTexture(1, data->mCbTexture); |
|
534 device()->SetTexture(2, data->mCrTexture); |
|
535 |
|
536 image = nullptr; |
|
537 data = nullptr; |
|
538 autoLock.Unlock(); |
|
539 |
|
540 device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); |
|
541 |
|
542 device()->SetVertexShaderConstantF(CBvTextureCoords, |
|
543 ShaderConstantRect(0, 0, 1.0f, 1.0f), 1); |
|
544 } |
|
545 |
|
546 GetContainer()->NotifyPaintedImage(image); |
|
547 } |
|
548 |
|
549 already_AddRefed<IDirect3DTexture9> |
|
550 ImageLayerD3D9::GetAsTexture(gfx::IntSize* aSize) |
|
551 { |
|
552 if (!GetContainer()) { |
|
553 return nullptr; |
|
554 } |
|
555 |
|
556 AutoLockImage autoLock(GetContainer()); |
|
557 |
|
558 Image *image = autoLock.GetImage(); |
|
559 |
|
560 if (!image) { |
|
561 return nullptr; |
|
562 } |
|
563 |
|
564 if (image->GetFormat() != ImageFormat::CAIRO_SURFACE && |
|
565 image->GetFormat() != ImageFormat::REMOTE_IMAGE_BITMAP) { |
|
566 return nullptr; |
|
567 } |
|
568 |
|
569 bool dontCare; |
|
570 *aSize = image->GetSize(); |
|
571 nsRefPtr<IDirect3DTexture9> result = GetTexture(image, dontCare); |
|
572 return result.forget(); |
|
573 } |
|
574 |
|
575 } /* layers */ |
|
576 } /* mozilla */ |