1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/ipc/SharedDIBWin.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,141 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "SharedDIBWin.h" 1.10 +#include "gfxAlphaRecovery.h" 1.11 +#include "nsMathUtils.h" 1.12 +#include "nsDebug.h" 1.13 + 1.14 +namespace mozilla { 1.15 +namespace gfx { 1.16 + 1.17 +static const uint32_t kBytesPerPixel = 4; 1.18 +static const uint32_t kByteAlign = 1 << gfxAlphaRecovery::GoodAlignmentLog2(); 1.19 +static const uint32_t kHeaderBytes = 1.20 + (sizeof(BITMAPV4HEADER) + kByteAlign - 1) & ~(kByteAlign - 1); 1.21 + 1.22 +SharedDIBWin::SharedDIBWin() : 1.23 + mSharedHdc(nullptr) 1.24 + , mSharedBmp(nullptr) 1.25 + , mOldObj(nullptr) 1.26 +{ 1.27 +} 1.28 + 1.29 +SharedDIBWin::~SharedDIBWin() 1.30 +{ 1.31 + Close(); 1.32 +} 1.33 + 1.34 +nsresult 1.35 +SharedDIBWin::Close() 1.36 +{ 1.37 + if (mSharedHdc && mOldObj) 1.38 + ::SelectObject(mSharedHdc, mOldObj); 1.39 + 1.40 + if (mSharedHdc) 1.41 + ::DeleteObject(mSharedHdc); 1.42 + 1.43 + if (mSharedBmp) 1.44 + ::DeleteObject(mSharedBmp); 1.45 + 1.46 + mSharedHdc = nullptr; 1.47 + mOldObj = mSharedBmp = nullptr; 1.48 + 1.49 + SharedDIB::Close(); 1.50 + 1.51 + return NS_OK; 1.52 +} 1.53 + 1.54 +nsresult 1.55 +SharedDIBWin::Create(HDC aHdc, uint32_t aWidth, uint32_t aHeight, 1.56 + bool aTransparent) 1.57 +{ 1.58 + Close(); 1.59 + 1.60 + // create the offscreen shared dib 1.61 + BITMAPV4HEADER bmih; 1.62 + uint32_t size = SetupBitmapHeader(aWidth, aHeight, aTransparent, &bmih); 1.63 + 1.64 + nsresult rv = SharedDIB::Create(size); 1.65 + if (NS_FAILED(rv)) 1.66 + return rv; 1.67 + 1.68 + if (NS_FAILED(SetupSurface(aHdc, &bmih))) { 1.69 + Close(); 1.70 + return NS_ERROR_FAILURE; 1.71 + } 1.72 + 1.73 + return NS_OK; 1.74 +} 1.75 + 1.76 +nsresult 1.77 +SharedDIBWin::Attach(Handle aHandle, uint32_t aWidth, uint32_t aHeight, 1.78 + bool aTransparent) 1.79 +{ 1.80 + Close(); 1.81 + 1.82 + BITMAPV4HEADER bmih; 1.83 + SetupBitmapHeader(aWidth, aHeight, aTransparent, &bmih); 1.84 + 1.85 + nsresult rv = SharedDIB::Attach(aHandle, 0); 1.86 + if (NS_FAILED(rv)) 1.87 + return rv; 1.88 + 1.89 + if (NS_FAILED(SetupSurface(nullptr, &bmih))) { 1.90 + Close(); 1.91 + return NS_ERROR_FAILURE; 1.92 + } 1.93 + 1.94 + return NS_OK; 1.95 +} 1.96 + 1.97 +uint32_t 1.98 +SharedDIBWin::SetupBitmapHeader(uint32_t aWidth, uint32_t aHeight, 1.99 + bool aTransparent, BITMAPV4HEADER *aHeader) 1.100 +{ 1.101 + // D3D cannot handle an offscreen memory that pitch (SysMemPitch) is negative. 1.102 + // So we create top-to-bottom DIB. 1.103 + memset((void*)aHeader, 0, sizeof(BITMAPV4HEADER)); 1.104 + aHeader->bV4Size = sizeof(BITMAPV4HEADER); 1.105 + aHeader->bV4Width = aWidth; 1.106 + aHeader->bV4Height = -LONG(aHeight); // top-to-buttom DIB 1.107 + aHeader->bV4Planes = 1; 1.108 + aHeader->bV4BitCount = 32; 1.109 + aHeader->bV4V4Compression = BI_BITFIELDS; 1.110 + aHeader->bV4RedMask = 0x00FF0000; 1.111 + aHeader->bV4GreenMask = 0x0000FF00; 1.112 + aHeader->bV4BlueMask = 0x000000FF; 1.113 + 1.114 + if (aTransparent) 1.115 + aHeader->bV4AlphaMask = 0xFF000000; 1.116 + 1.117 + return (kHeaderBytes + (-aHeader->bV4Height * aHeader->bV4Width * kBytesPerPixel)); 1.118 +} 1.119 + 1.120 +nsresult 1.121 +SharedDIBWin::SetupSurface(HDC aHdc, BITMAPV4HEADER *aHdr) 1.122 +{ 1.123 + mSharedHdc = ::CreateCompatibleDC(aHdc); 1.124 + 1.125 + if (!mSharedHdc) 1.126 + return NS_ERROR_FAILURE; 1.127 + 1.128 + mSharedBmp = ::CreateDIBSection(mSharedHdc, 1.129 + (BITMAPINFO*)aHdr, 1.130 + DIB_RGB_COLORS, 1.131 + &mBitmapBits, 1.132 + mShMem->handle(), 1.133 + kHeaderBytes); 1.134 + if (!mSharedBmp) 1.135 + return NS_ERROR_FAILURE; 1.136 + 1.137 + mOldObj = SelectObject(mSharedHdc, mSharedBmp); 1.138 + 1.139 + return NS_OK; 1.140 +} 1.141 + 1.142 + 1.143 +} // gfx 1.144 +} // mozilla