Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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/. */
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"
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"
22 namespace mozilla {
23 namespace layers {
25 using namespace mozilla::gfx;
27 static inline _D3DFORMAT
28 D3dFormatForSurfaceFormat(SurfaceFormat aFormat)
29 {
30 if (aFormat == SurfaceFormat::A8) {
31 return D3DFMT_A8;
32 }
34 return D3DFMT_A8R8G8B8;
35 }
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));
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 }
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 }
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 }
84 /* lock the entire texture */
85 texture->LockRect(0, &lockedRect, nullptr, 0);
86 }
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 }
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 }
107 return texture.forget();
108 }
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);
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 }
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 }
154 static void AllocateTexturesYCbCr(PlanarYCbCrImage *aImage,
155 IDirect3DDevice9 *aDevice,
156 LayerManagerD3D9 *aManager)
157 {
158 nsAutoPtr<PlanarYCbCrD3D9BackendData> backendData(
159 new PlanarYCbCrD3D9BackendData);
161 const PlanarYCbCrData *data = aImage->GetData();
163 D3DLOCKED_RECT lockrectY;
164 D3DLOCKED_RECT lockrectCb;
165 D3DLOCKED_RECT lockrectCr;
166 uint8_t* src;
167 uint8_t* dest;
169 nsRefPtr<IDirect3DSurface9> tmpSurfaceY;
170 nsRefPtr<IDirect3DSurface9> tmpSurfaceCb;
171 nsRefPtr<IDirect3DSurface9> tmpSurfaceCr;
173 nsRefPtr<IDirect3DDevice9Ex> deviceEx;
174 aDevice->QueryInterface(IID_IDirect3DDevice9Ex,
175 getter_AddRefs(deviceEx));
177 bool isD3D9Ex = deviceEx;
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.
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 }
217 if (FAILED(hr)) {
218 aManager->ReportFailure(NS_LITERAL_CSTRING("PlanarYCbCrImageD3D9::AllocateTextures(): Failed to create texture (isD3D9Ex)"),
219 hr);
220 return;
221 }
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 }
245 if (FAILED(hr)) {
246 aManager->ReportFailure(NS_LITERAL_CSTRING("PlanarYCbCrImageD3D9::AllocateTextures(): Failed to create texture (!isD3D9Ex)"),
247 hr);
248 return;
249 }
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 }
257 src = data->mYChannel;
258 //FIX cast
259 dest = (uint8_t*)lockrectY.pBits;
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 }
268 src = data->mCbChannel;
269 //FIX cast
270 dest = (uint8_t*)lockrectCb.pBits;
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 }
279 src = data->mCrChannel;
280 //FIX cast
281 dest = (uint8_t*)lockrectCr.pBits;
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 }
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 }
307 aImage->SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9, backendData.forget());
308 }
310 Layer*
311 ImageLayerD3D9::GetLayer()
312 {
313 return this;
314 }
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.");
328 if (aImage->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP) {
329 RemoteBitmapImage *remoteImage =
330 static_cast<RemoteBitmapImage*>(aImage);
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 }
340 aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
341 } else if (aImage->GetFormat() == ImageFormat::CAIRO_SURFACE) {
342 CairoImage *cairoImage =
343 static_cast<CairoImage*>(aImage);
345 RefPtr<SourceSurface> surf = cairoImage->GetAsSourceSurface();
346 if (!surf) {
347 return nullptr;
348 }
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 }
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 }
376 TextureD3D9BackendData *data =
377 static_cast<TextureD3D9BackendData*>(aImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9));
379 if (!data) {
380 return nullptr;
381 }
383 nsRefPtr<IDirect3DDevice9> dev;
384 data->mTexture->GetDevice(getter_AddRefs(dev));
385 if (dev != device()) {
386 return nullptr;
387 }
389 return data->mTexture;
390 }
392 void
393 ImageLayerD3D9::RenderLayer()
394 {
395 ImageContainer *container = GetContainer();
396 if (!container || mD3DManager->CompositingDisabled()) {
397 return;
398 }
400 AutoLockImage autoLock(container);
402 Image *image = autoLock.GetImage();
403 if (!image) {
404 return;
405 }
407 SetShaderTransformAndOpacity();
409 gfx::IntSize size = image->GetSize();
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");
420 bool hasAlpha = false;
421 nsRefPtr<IDirect3DTexture9> texture = GetTexture(image, hasAlpha);
423 device()->SetVertexShaderConstantF(CBvLayerQuad,
424 ShaderConstantRect(0,
425 0,
426 size.width,
427 size.height),
428 1);
430 if (hasAlpha) {
431 mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER, GetMaskLayer());
432 } else {
433 mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER, GetMaskLayer());
434 }
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);
442 image = nullptr;
443 autoLock.Unlock();
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);
454 if (!yuvImage->IsValid()) {
455 return;
456 }
458 if (!yuvImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9)) {
459 AllocateTexturesYCbCr(yuvImage, device(), mD3DManager);
460 }
462 PlanarYCbCrD3D9BackendData *data =
463 static_cast<PlanarYCbCrD3D9BackendData*>(yuvImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D9));
465 if (!data) {
466 return;
467 }
469 nsRefPtr<IDirect3DDevice9> dev;
470 data->mYTexture->GetDevice(getter_AddRefs(dev));
471 if (dev != device()) {
472 return;
473 }
475 device()->SetVertexShaderConstantF(CBvLayerQuad,
476 ShaderConstantRect(0,
477 0,
478 size.width,
479 size.height),
480 1);
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);
491 mD3DManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER, GetMaskLayer());
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 }
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);
519 if (yuvImage->GetData()->mStereoMode != StereoMode::MONO) {
520 mD3DManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE);
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 }
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);
536 image = nullptr;
537 data = nullptr;
538 autoLock.Unlock();
540 device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
542 device()->SetVertexShaderConstantF(CBvTextureCoords,
543 ShaderConstantRect(0, 0, 1.0f, 1.0f), 1);
544 }
546 GetContainer()->NotifyPaintedImage(image);
547 }
549 already_AddRefed<IDirect3DTexture9>
550 ImageLayerD3D9::GetAsTexture(gfx::IntSize* aSize)
551 {
552 if (!GetContainer()) {
553 return nullptr;
554 }
556 AutoLockImage autoLock(GetContainer());
558 Image *image = autoLock.GetImage();
560 if (!image) {
561 return nullptr;
562 }
564 if (image->GetFormat() != ImageFormat::CAIRO_SURFACE &&
565 image->GetFormat() != ImageFormat::REMOTE_IMAGE_BITMAP) {
566 return nullptr;
567 }
569 bool dontCare;
570 *aSize = image->GetSize();
571 nsRefPtr<IDirect3DTexture9> result = GetTexture(image, dontCare);
572 return result.forget();
573 }
575 } /* layers */
576 } /* mozilla */