|
1 /* -*- Mode: C++; tab-width: 2; 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 "SharedDIBWin.h" |
|
7 #include "gfxAlphaRecovery.h" |
|
8 #include "nsMathUtils.h" |
|
9 #include "nsDebug.h" |
|
10 |
|
11 namespace mozilla { |
|
12 namespace gfx { |
|
13 |
|
14 static const uint32_t kBytesPerPixel = 4; |
|
15 static const uint32_t kByteAlign = 1 << gfxAlphaRecovery::GoodAlignmentLog2(); |
|
16 static const uint32_t kHeaderBytes = |
|
17 (sizeof(BITMAPV4HEADER) + kByteAlign - 1) & ~(kByteAlign - 1); |
|
18 |
|
19 SharedDIBWin::SharedDIBWin() : |
|
20 mSharedHdc(nullptr) |
|
21 , mSharedBmp(nullptr) |
|
22 , mOldObj(nullptr) |
|
23 { |
|
24 } |
|
25 |
|
26 SharedDIBWin::~SharedDIBWin() |
|
27 { |
|
28 Close(); |
|
29 } |
|
30 |
|
31 nsresult |
|
32 SharedDIBWin::Close() |
|
33 { |
|
34 if (mSharedHdc && mOldObj) |
|
35 ::SelectObject(mSharedHdc, mOldObj); |
|
36 |
|
37 if (mSharedHdc) |
|
38 ::DeleteObject(mSharedHdc); |
|
39 |
|
40 if (mSharedBmp) |
|
41 ::DeleteObject(mSharedBmp); |
|
42 |
|
43 mSharedHdc = nullptr; |
|
44 mOldObj = mSharedBmp = nullptr; |
|
45 |
|
46 SharedDIB::Close(); |
|
47 |
|
48 return NS_OK; |
|
49 } |
|
50 |
|
51 nsresult |
|
52 SharedDIBWin::Create(HDC aHdc, uint32_t aWidth, uint32_t aHeight, |
|
53 bool aTransparent) |
|
54 { |
|
55 Close(); |
|
56 |
|
57 // create the offscreen shared dib |
|
58 BITMAPV4HEADER bmih; |
|
59 uint32_t size = SetupBitmapHeader(aWidth, aHeight, aTransparent, &bmih); |
|
60 |
|
61 nsresult rv = SharedDIB::Create(size); |
|
62 if (NS_FAILED(rv)) |
|
63 return rv; |
|
64 |
|
65 if (NS_FAILED(SetupSurface(aHdc, &bmih))) { |
|
66 Close(); |
|
67 return NS_ERROR_FAILURE; |
|
68 } |
|
69 |
|
70 return NS_OK; |
|
71 } |
|
72 |
|
73 nsresult |
|
74 SharedDIBWin::Attach(Handle aHandle, uint32_t aWidth, uint32_t aHeight, |
|
75 bool aTransparent) |
|
76 { |
|
77 Close(); |
|
78 |
|
79 BITMAPV4HEADER bmih; |
|
80 SetupBitmapHeader(aWidth, aHeight, aTransparent, &bmih); |
|
81 |
|
82 nsresult rv = SharedDIB::Attach(aHandle, 0); |
|
83 if (NS_FAILED(rv)) |
|
84 return rv; |
|
85 |
|
86 if (NS_FAILED(SetupSurface(nullptr, &bmih))) { |
|
87 Close(); |
|
88 return NS_ERROR_FAILURE; |
|
89 } |
|
90 |
|
91 return NS_OK; |
|
92 } |
|
93 |
|
94 uint32_t |
|
95 SharedDIBWin::SetupBitmapHeader(uint32_t aWidth, uint32_t aHeight, |
|
96 bool aTransparent, BITMAPV4HEADER *aHeader) |
|
97 { |
|
98 // D3D cannot handle an offscreen memory that pitch (SysMemPitch) is negative. |
|
99 // So we create top-to-bottom DIB. |
|
100 memset((void*)aHeader, 0, sizeof(BITMAPV4HEADER)); |
|
101 aHeader->bV4Size = sizeof(BITMAPV4HEADER); |
|
102 aHeader->bV4Width = aWidth; |
|
103 aHeader->bV4Height = -LONG(aHeight); // top-to-buttom DIB |
|
104 aHeader->bV4Planes = 1; |
|
105 aHeader->bV4BitCount = 32; |
|
106 aHeader->bV4V4Compression = BI_BITFIELDS; |
|
107 aHeader->bV4RedMask = 0x00FF0000; |
|
108 aHeader->bV4GreenMask = 0x0000FF00; |
|
109 aHeader->bV4BlueMask = 0x000000FF; |
|
110 |
|
111 if (aTransparent) |
|
112 aHeader->bV4AlphaMask = 0xFF000000; |
|
113 |
|
114 return (kHeaderBytes + (-aHeader->bV4Height * aHeader->bV4Width * kBytesPerPixel)); |
|
115 } |
|
116 |
|
117 nsresult |
|
118 SharedDIBWin::SetupSurface(HDC aHdc, BITMAPV4HEADER *aHdr) |
|
119 { |
|
120 mSharedHdc = ::CreateCompatibleDC(aHdc); |
|
121 |
|
122 if (!mSharedHdc) |
|
123 return NS_ERROR_FAILURE; |
|
124 |
|
125 mSharedBmp = ::CreateDIBSection(mSharedHdc, |
|
126 (BITMAPINFO*)aHdr, |
|
127 DIB_RGB_COLORS, |
|
128 &mBitmapBits, |
|
129 mShMem->handle(), |
|
130 kHeaderBytes); |
|
131 if (!mSharedBmp) |
|
132 return NS_ERROR_FAILURE; |
|
133 |
|
134 mOldObj = SelectObject(mSharedHdc, mSharedBmp); |
|
135 |
|
136 return NS_OK; |
|
137 } |
|
138 |
|
139 |
|
140 } // gfx |
|
141 } // mozilla |