// static PLDHashOperator nsWindowBase::CancelTouchPoints(const unsigned int& aPointerId, nsAutoPtr<PointerInfo>& aInfo, void* aUserArg) { nsWindowBase* self = static_cast<nsWindowBase*>(aUserArg); self->InjectTouchPoint(aInfo.get()->mPointerId, aInfo.get()->mPosition, POINTER_FLAG_CANCELED); return (PLDHashOperator)(PL_DHASH_NEXT|PL_DHASH_REMOVE); }
bool RestyleTracker::GetRestyleData(Element* aElement, nsAutoPtr<RestyleData>& aData) { NS_PRECONDITION(aElement->GetCrossShadowCurrentDoc() == Document(), "Unexpected document; this will lead to incorrect behavior!"); if (!aElement->HasFlag(RestyleBit())) { NS_ASSERTION(!aElement->HasFlag(RootBit()), "Bogus root bit?"); return false; } mPendingRestyles.RemoveAndForget(aElement, aData); NS_ASSERTION(aData.get(), "Must have data if restyle bit is set"); if (aData->mRestyleHint & eRestyle_LaterSiblings) { // Someone readded the eRestyle_LaterSiblings hint for this // element. Leave it around for now, but remove the other restyle // hints and the change hint for it. Also unset its root bit, // since it's no longer a root with the new restyle data. NS_ASSERTION(aData->mDescendants.IsEmpty(), "expected descendants to be handled by now"); RestyleData* newData = new RestyleData; newData->mChangeHint = nsChangeHint(0); newData->mRestyleHint = eRestyle_LaterSiblings; mPendingRestyles.Put(aElement, newData); aElement->UnsetFlags(RootBit()); aData->mRestyleHint = nsRestyleHint(aData->mRestyleHint & ~eRestyle_LaterSiblings); } else { aElement->UnsetFlags(mRestyleBits); } return true; }
static size_t SizeOfCategoryManagerTableEntryExcludingThis(nsDepCharHashKey::KeyType aKey, const nsAutoPtr<CategoryNode> &aData, MallocSizeOf aMallocSizeOf, void* aUserArg) { // We don't measure the string pointed to by aKey because it's a non-owning // pointer. return aData.get()->SizeOfExcludingThis(aMallocSizeOf); }
PLDHashOperator SpdyStream::hdrHashEnumerate(const nsACString &key, nsAutoPtr<nsCString> &value, void *closure) { SpdyStream *self = static_cast<SpdyStream *>(closure); self->CompressToFrame(key); self->CompressToFrame(value.get()); return PL_DHASH_NEXT; }
nsresult RilSocketIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) { MOZ_ASSERT(aBuffer); if (!mBuffer) { mBuffer = new UnixSocketRawData(MAX_READ_SIZE); } *aBuffer = mBuffer.get(); return NS_OK; }
nsresult DaemonSocketIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) { MOZ_ASSERT(aBuffer); if (!mPDU) { /* There's only one PDU for receiving. We reuse it every time. */ mPDU = new DaemonSocketPDU(DaemonSocketPDU::MAX_PAYLOAD_LENGTH); } *aBuffer = mPDU.get(); return NS_OK; }
bool RestyleTracker::GetRestyleData(Element* aElement, nsAutoPtr<RestyleData>& aData) { NS_PRECONDITION(aElement->GetComposedDoc() == Document(), "Unexpected document; this will lead to incorrect behavior!"); if (!aElement->HasFlag(RestyleBit())) { NS_ASSERTION(!aElement->HasFlag(RootBit()), "Bogus root bit?"); return false; } mPendingRestyles.RemoveAndForget(aElement, aData); NS_ASSERTION(aData.get(), "Must have data if restyle bit is set"); if (aData->mRestyleHint & eRestyle_LaterSiblings) { // Someone readded the eRestyle_LaterSiblings hint for this // element. Leave it around for now, but remove the other restyle // hints and the change hint for it. Also unset its root bit, // since it's no longer a root with the new restyle data. // During a normal restyle, we should have already processed the // mDescendants array the last time we processed the restyle // for this element. But in RebuildAllStyleData, we don't initially // expand out eRestyle_LaterSiblings, so we can get in here the // first time we need to process a restyle for this element. In that // case, it's fine for us to have a non-empty mDescendants, since // we know that RebuildAllStyleData adds eRestyle_ForceDescendants // and we're guaranteed we'll restyle the entire tree. NS_ASSERTION(mRestyleManager->InRebuildAllStyleData() || aData->mDescendants.IsEmpty(), "expected descendants to be handled by now"); RestyleData* newData = new RestyleData; newData->mChangeHint = nsChangeHint(0); newData->mRestyleHint = eRestyle_LaterSiblings; mPendingRestyles.Put(aElement, newData); aElement->UnsetFlags(RootBit()); aData->mRestyleHint = nsRestyleHint(aData->mRestyleHint & ~eRestyle_LaterSiblings); } else { aElement->UnsetFlags(mRestyleBits); } return true; }
static void GetStatsForLongTermStorage_s( nsAutoPtr<RTCStatsQuery> query) { MOZ_ASSERT(query); nsresult rv = PeerConnectionImpl::ExecuteStatsQuery_s(query.get()); // Check whether packets were dropped due to rate limiting during // this call. (These calls must be made on STS) unsigned char rate_limit_bit_pattern = 0; if (!mozilla::nr_socket_short_term_violation_time().IsNull() && mozilla::nr_socket_short_term_violation_time() >= query->iceStartTime) { rate_limit_bit_pattern |= 1; } if (!mozilla::nr_socket_long_term_violation_time().IsNull() && mozilla::nr_socket_long_term_violation_time() >= query->iceStartTime) { rate_limit_bit_pattern |= 2; } if (query->failed) { Telemetry::Accumulate( Telemetry::WEBRTC_STUN_RATE_LIMIT_EXCEEDED_BY_TYPE_GIVEN_FAILURE, rate_limit_bit_pattern); } else { Telemetry::Accumulate( Telemetry::WEBRTC_STUN_RATE_LIMIT_EXCEEDED_BY_TYPE_GIVEN_SUCCESS, rate_limit_bit_pattern); } // Even if Telemetry::Accumulate is threadsafe, we still need to send the // query back to main, since that is where it must be destroyed. NS_DispatchToMainThread( WrapRunnableNM( &StoreLongTermICEStatisticsImpl_m, rv, query), NS_DISPATCH_NORMAL); }
bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel) { // We never have reentrant paint events, except when we're running our RPC // windows event spin loop. If we don't trap for this, we'll try to paint, // but view manager will refuse to paint the surface, resulting is black // flashes on the plugin rendering surface. if (mozilla::ipc::RPCChannel::IsSpinLoopActive() && mPainting) return false; if (mWindowType == eWindowType_plugin) { /** * After we CallUpdateWindow to the child, occasionally a WM_PAINT message * is posted to the parent event loop with an empty update rect. Do a * dummy paint so that Windows stops dispatching WM_PAINT in an inifinite * loop. See bug 543788. */ RECT updateRect; if (!GetUpdateRect(mWnd, &updateRect, FALSE) || (updateRect.left == updateRect.right && updateRect.top == updateRect.bottom)) { PAINTSTRUCT ps; BeginPaint(mWnd, &ps); EndPaint(mWnd, &ps); return true; } PluginInstanceParent* instance = reinterpret_cast<PluginInstanceParent*>( ::GetPropW(mWnd, L"PluginInstanceParentProperty")); if (instance) { unused << instance->CallUpdateWindow(); } else { // We should never get here since in-process plugins should have // subclassed our HWND and handled WM_PAINT, but in some cases that // could fail. Return without asserting since it's not our fault. NS_WARNING("Plugin failed to subclass our window"); } ValidateRect(mWnd, NULL); return true; } // Do an early async composite so that we at least have something on screen // in the right place, even if the content is out of date. if (GetLayerManager()->GetBackendType() == LAYERS_CLIENT && mCompositorParent) { mCompositorParent->ScheduleRenderOnCompositorThread(); } nsIWidgetListener* listener = GetPaintListener(); if (listener) { listener->WillPaintWindow(this); } // Re-get the listener since the will paint notification may have killed it. listener = GetPaintListener(); if (!listener) return false; bool result = true; PAINTSTRUCT ps; #ifdef MOZ_XUL if (!aDC && (eTransparencyTransparent == mTransparencyMode)) { // For layered translucent windows all drawing should go to memory DC and no // WM_PAINT messages are normally generated. To support asynchronous painting // we force generation of WM_PAINT messages by invalidating window areas with // RedrawWindow, InvalidateRect or InvalidateRgn function calls. // BeginPaint/EndPaint must be called to make Windows think that invalid area // is painted. Otherwise it will continue sending the same message endlessly. ::BeginPaint(mWnd, &ps); ::EndPaint(mWnd, &ps); aDC = mMemoryDC; } #endif mPainting = true; #ifdef WIDGET_DEBUG_OUTPUT HRGN debugPaintFlashRegion = NULL; HDC debugPaintFlashDC = NULL; if (debug_WantPaintFlashing()) { debugPaintFlashRegion = ::CreateRectRgn(0, 0, 0, 0); ::GetUpdateRgn(mWnd, debugPaintFlashRegion, TRUE); debugPaintFlashDC = ::GetDC(mWnd); } #endif // WIDGET_DEBUG_OUTPUT HDC hDC = aDC ? aDC : (::BeginPaint(mWnd, &ps)); if (!IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D)) { mPaintDC = hDC; } #ifdef MOZ_XUL bool forceRepaint = aDC || (eTransparencyTransparent == mTransparencyMode); #else bool forceRepaint = NULL != aDC; #endif nsIntRegion region = GetRegionToPaint(forceRepaint, ps, hDC); if (!region.IsEmpty() && listener) { // Should probably pass in a real region here, using GetRandomRgn // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/clipping_4q0e.asp #ifdef WIDGET_DEBUG_OUTPUT debug_DumpPaintEvent(stdout, this, region, nsAutoCString("noname"), (int32_t) mWnd); #endif // WIDGET_DEBUG_OUTPUT switch (GetLayerManager()->GetBackendType()) { case LAYERS_BASIC: { nsRefPtr<gfxASurface> targetSurface; #if defined(MOZ_XUL) // don't support transparency for non-GDI rendering, for now if ((IsRenderMode(gfxWindowsPlatform::RENDER_GDI) || IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D)) && eTransparencyTransparent == mTransparencyMode) { if (mTransparentSurface == nullptr) SetupTranslucentWindowMemoryBitmap(mTransparencyMode); targetSurface = mTransparentSurface; } #endif #ifdef CAIRO_HAS_D2D_SURFACE if (!targetSurface && IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D)) { if (!mD2DWindowSurface) { gfxASurface::gfxContentType content = gfxASurface::CONTENT_COLOR; #if defined(MOZ_XUL) if (mTransparencyMode != eTransparencyOpaque) { content = gfxASurface::CONTENT_COLOR_ALPHA; } #endif mD2DWindowSurface = new gfxD2DSurface(mWnd, content); } if (!mD2DWindowSurface->CairoStatus()) { targetSurface = mD2DWindowSurface; } else { mD2DWindowSurface = nullptr; } } #endif nsRefPtr<gfxWindowsSurface> targetSurfaceWin; if (!targetSurface && (IsRenderMode(gfxWindowsPlatform::RENDER_GDI) || IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D))) { uint32_t flags = (mTransparencyMode == eTransparencyOpaque) ? 0 : gfxWindowsSurface::FLAG_IS_TRANSPARENT; targetSurfaceWin = new gfxWindowsSurface(hDC, flags); targetSurface = targetSurfaceWin; } nsRefPtr<gfxImageSurface> targetSurfaceImage; if (!targetSurface && (IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH32) || IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24))) { gfxIntSize surfaceSize(ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top); if (!EnsureSharedSurfaceSize(surfaceSize)) { NS_ERROR("Couldn't allocate a shared image surface!"); return false; } // don't use the shared surface directly; instead, create a new one // that just reuses its buffer. targetSurfaceImage = new gfxImageSurface(sSharedSurfaceData.get(), surfaceSize, surfaceSize.width * 4, gfxASurface::ImageFormatRGB24); if (targetSurfaceImage && !targetSurfaceImage->CairoStatus()) { targetSurfaceImage->SetDeviceOffset(gfxPoint(-ps.rcPaint.left, -ps.rcPaint.top)); targetSurface = targetSurfaceImage; } } if (!targetSurface) { NS_ERROR("Invalid RenderMode!"); return false; } nsRefPtr<gfxContext> thebesContext; if (gfxPlatform::GetPlatform()->SupportsAzureContentForType(mozilla::gfx::BACKEND_CAIRO)) { RECT paintRect; ::GetClientRect(mWnd, &paintRect); RefPtr<mozilla::gfx::DrawTarget> dt = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(targetSurface, mozilla::gfx::IntSize(paintRect.right - paintRect.left, paintRect.bottom - paintRect.top)); thebesContext = new gfxContext(dt); } else { thebesContext = new gfxContext(targetSurface); } if (IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D)) { const nsIntRect* r; for (nsIntRegionRectIterator iter(region); (r = iter.Next()) != nullptr;) { thebesContext->Rectangle(gfxRect(r->x, r->y, r->width, r->height), true); } thebesContext->Clip(); thebesContext->SetOperator(gfxContext::OPERATOR_CLEAR); thebesContext->Paint(); thebesContext->SetOperator(gfxContext::OPERATOR_OVER); } // don't need to double buffer with anything but GDI BufferMode doubleBuffering = mozilla::layers::BUFFER_NONE; if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI)) { #ifdef MOZ_XUL switch (mTransparencyMode) { case eTransparencyGlass: case eTransparencyBorderlessGlass: default: // If we're not doing translucency, then double buffer doubleBuffering = mozilla::layers::BUFFER_BUFFERED; break; case eTransparencyTransparent: // If we're rendering with translucency, we're going to be // rendering the whole window; make sure we clear it first thebesContext->SetOperator(gfxContext::OPERATOR_CLEAR); thebesContext->Paint(); thebesContext->SetOperator(gfxContext::OPERATOR_OVER); break; } #else doubleBuffering = mozilla::layers::BUFFER_BUFFERED; #endif } { AutoLayerManagerSetup setupLayerManager(this, thebesContext, doubleBuffering); result = listener->PaintWindow(this, region); } #ifdef MOZ_XUL if ((IsRenderMode(gfxWindowsPlatform::RENDER_GDI) || IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D))&& eTransparencyTransparent == mTransparencyMode) { // Data from offscreen drawing surface was copied to memory bitmap of transparent // bitmap. Now it can be read from memory bitmap to apply alpha channel and after // that displayed on the screen. UpdateTranslucentWindow(); } else #endif #ifdef CAIRO_HAS_D2D_SURFACE if (result) { if (mD2DWindowSurface) { mD2DWindowSurface->Present(); } } #endif if (result) { if (IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24) || IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH32)) { gfxIntSize surfaceSize = targetSurfaceImage->GetSize(); // Just blit this directly BITMAPINFOHEADER bi; memset(&bi, 0, sizeof(BITMAPINFOHEADER)); bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = surfaceSize.width; bi.biHeight = - surfaceSize.height; bi.biPlanes = 1; bi.biBitCount = 32; bi.biCompression = BI_RGB; if (IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24)) { // On Windows CE/Windows Mobile, 24bpp packed-pixel sources // seem to be far faster to blit than 32bpp (see bug 484864). // So, convert the bits to 24bpp by stripping out the unused // alpha byte. 24bpp DIBs also have scanlines that are 4-byte // aligned though, so that must be taken into account. int srcstride = surfaceSize.width*4; int dststride = surfaceSize.width*3; dststride = (dststride + 3) & ~3; // Convert in place for (int j = 0; j < surfaceSize.height; ++j) { unsigned int *src = (unsigned int*) (targetSurfaceImage->Data() + j*srcstride); unsigned int *dst = (unsigned int*) (targetSurfaceImage->Data() + j*dststride); // go 4 pixels at a time, since each 4 pixels // turns into 3 DWORDs when converted into BGR: // BGRx BGRx BGRx BGRx -> BGRB GRBG RBGR // // However, since we're dealing with little-endian ints, this is actually: // xRGB xrgb xRGB xrgb -> bRGB GBrg rgbR int width_left = surfaceSize.width; while (width_left >= 4) { unsigned int a = *src++; unsigned int b = *src++; unsigned int c = *src++; unsigned int d = *src++; *dst++ = (a & 0x00ffffff) | (b << 24); *dst++ = ((b & 0x00ffff00) >> 8) | (c << 16); *dst++ = ((c & 0x00ff0000) >> 16) | (d << 8); width_left -= 4; } // then finish up whatever number of pixels are left, // using bytes. unsigned char *bsrc = (unsigned char*) src; unsigned char *bdst = (unsigned char*) dst; switch (width_left) { case 3: *bdst++ = *bsrc++; *bdst++ = *bsrc++; *bdst++ = *bsrc++; bsrc++; case 2: *bdst++ = *bsrc++; *bdst++ = *bsrc++; *bdst++ = *bsrc++; bsrc++; case 1: *bdst++ = *bsrc++; *bdst++ = *bsrc++; *bdst++ = *bsrc++; bsrc++; case 0: break; } } bi.biBitCount = 24; } StretchDIBits(hDC, ps.rcPaint.left, ps.rcPaint.top, surfaceSize.width, surfaceSize.height, 0, 0, surfaceSize.width, surfaceSize.height, targetSurfaceImage->Data(), (BITMAPINFO*) &bi, DIB_RGB_COLORS, SRCCOPY); } } } break; case LAYERS_OPENGL: static_cast<mozilla::layers::LayerManagerOGL*>(GetLayerManager())-> SetClippingRegion(region); result = listener->PaintWindow(this, region); break; #ifdef MOZ_ENABLE_D3D9_LAYER case LAYERS_D3D9: { nsRefPtr<LayerManagerD3D9> layerManagerD3D9 = static_cast<mozilla::layers::LayerManagerD3D9*>(GetLayerManager()); layerManagerD3D9->SetClippingRegion(region); result = listener->PaintWindow(this, region); if (layerManagerD3D9->DeviceWasRemoved()) { mLayerManager->Destroy(); mLayerManager = nullptr; // When our device was removed, we should have gfxWindowsPlatform // check if its render mode is up to date! gfxWindowsPlatform::GetPlatform()->UpdateRenderMode(); Invalidate(); } } break; #endif #ifdef MOZ_ENABLE_D3D10_LAYER case LAYERS_D3D10: { gfxWindowsPlatform::GetPlatform()->UpdateRenderMode(); LayerManagerD3D10 *layerManagerD3D10 = static_cast<mozilla::layers::LayerManagerD3D10*>(GetLayerManager()); if (layerManagerD3D10->device() != gfxWindowsPlatform::GetPlatform()->GetD3D10Device()) { Invalidate(); } else { result = listener->PaintWindow(this, region); } } break; #endif case LAYERS_CLIENT: result = listener->PaintWindow(this, region); break; default: NS_ERROR("Unknown layers backend used!"); break; }
/* [noscript] attribute SpdyPushCachePtr spdyPushCache; */ NS_IMETHODIMP nsLoadGroupConnectionInfo::GetSpdyPushCache(mozilla::net::SpdyPushCache **aSpdyPushCache) { *aSpdyPushCache = mSpdyCache.get(); return NS_OK; }
PRBool nsWindow::OnPaint(HDC aDC) { #ifdef MOZ_IPC if (mWindowType == eWindowType_plugin) { /** * After we CallUpdateWindow to the child, occasionally a WM_PAINT message * is posted to the parent event loop with an empty update rect. Do a * dummy paint so that Windows stops dispatching WM_PAINT in an inifinite * loop. See bug 543788. */ RECT updateRect; if (!GetUpdateRect(mWnd, &updateRect, FALSE) || (updateRect.left == updateRect.right && updateRect.top == updateRect.bottom)) { PAINTSTRUCT ps; BeginPaint(mWnd, &ps); EndPaint(mWnd, &ps); return PR_TRUE; } PluginInstanceParent* instance = reinterpret_cast<PluginInstanceParent*>( ::GetPropW(mWnd, L"PluginInstanceParentProperty")); if (instance) { instance->CallUpdateWindow(); ValidateRect(mWnd, NULL); return PR_TRUE; } } #endif #ifdef MOZ_IPC // We never have reentrant paint events, except when we're running our RPC // windows event spin loop. If we don't trap for this, we'll try to paint, // but view manager will refuse to paint the surface, resulting is black // flashes on the plugin rendering surface. if (mozilla::ipc::RPCChannel::IsSpinLoopActive() && mPainting) return PR_FALSE; #endif nsPaintEvent willPaintEvent(PR_TRUE, NS_WILL_PAINT, this); DispatchWindowEvent(&willPaintEvent); #ifdef CAIRO_HAS_DDRAW_SURFACE if (IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_DDRAW16)) { return OnPaintImageDDraw16(); } #endif PRBool result = PR_TRUE; PAINTSTRUCT ps; nsEventStatus eventStatus = nsEventStatus_eIgnore; #ifdef MOZ_XUL if (!aDC && (eTransparencyTransparent == mTransparencyMode)) { // For layered translucent windows all drawing should go to memory DC and no // WM_PAINT messages are normally generated. To support asynchronous painting // we force generation of WM_PAINT messages by invalidating window areas with // RedrawWindow, InvalidateRect or InvalidateRgn function calls. // BeginPaint/EndPaint must be called to make Windows think that invalid area // is painted. Otherwise it will continue sending the same message endlessly. ::BeginPaint(mWnd, &ps); ::EndPaint(mWnd, &ps); aDC = mMemoryDC; } #endif mPainting = PR_TRUE; #ifdef WIDGET_DEBUG_OUTPUT HRGN debugPaintFlashRegion = NULL; HDC debugPaintFlashDC = NULL; if (debug_WantPaintFlashing()) { debugPaintFlashRegion = ::CreateRectRgn(0, 0, 0, 0); ::GetUpdateRgn(mWnd, debugPaintFlashRegion, TRUE); debugPaintFlashDC = ::GetDC(mWnd); } #endif // WIDGET_DEBUG_OUTPUT HDC hDC = aDC ? aDC : (::BeginPaint(mWnd, &ps)); if (!IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D)) { mPaintDC = hDC; } #ifdef MOZ_XUL PRBool forceRepaint = aDC || (eTransparencyTransparent == mTransparencyMode); #else PRBool forceRepaint = NULL != aDC; #endif nsCOMPtr<nsIRegion> paintRgnWin = GetRegionToPaint(forceRepaint, ps, hDC); if (paintRgnWin && !paintRgnWin->IsEmpty() && mEventCallback) { // generate the event and call the event callback nsPaintEvent event(PR_TRUE, NS_PAINT, this); InitEvent(event); event.region = paintRgnWin; event.rect = nsnull; // Should probably pass in a real region here, using GetRandomRgn // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/clipping_4q0e.asp #ifdef WIDGET_DEBUG_OUTPUT debug_DumpPaintEvent(stdout, this, &event, nsCAutoString("noname"), (PRInt32) mWnd); #endif // WIDGET_DEBUG_OUTPUT nsRefPtr<gfxASurface> targetSurface; #if defined(MOZ_XUL) // don't support transparency for non-GDI rendering, for now if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI) && eTransparencyTransparent == mTransparencyMode) { if (mTransparentSurface == nsnull) SetupTranslucentWindowMemoryBitmap(mTransparencyMode); targetSurface = mTransparentSurface; } #endif nsRefPtr<gfxWindowsSurface> targetSurfaceWin; if (!targetSurface && IsRenderMode(gfxWindowsPlatform::RENDER_GDI)) { targetSurfaceWin = new gfxWindowsSurface(hDC); targetSurface = targetSurfaceWin; } #ifdef CAIRO_HAS_D2D_SURFACE if (!targetSurface && IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D)) { if (!mD2DWindowSurface) { mD2DWindowSurface = new gfxD2DSurface(mWnd); } targetSurface = mD2DWindowSurface; } #endif #ifdef CAIRO_HAS_DDRAW_SURFACE nsRefPtr<gfxDDrawSurface> targetSurfaceDDraw; if (!targetSurface && (IsRenderMode(gfxWindowsPlatform::RENDER_DDRAW) || IsRenderMode(gfxWindowsPlatform::RENDER_DDRAW_GL))) { if (!glpDD) { if (!nsWindowGfx::InitDDraw()) { NS_WARNING("DirectDraw init failed; falling back to RENDER_IMAGE_STRETCH24"); gfxWindowsPlatform::GetPlatform()->SetRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24); goto DDRAW_FAILED; } } // create a rect that maps the window in screen space // create a new sub-surface that aliases this one RECT winrect; GetClientRect(mWnd, &winrect); MapWindowPoints(mWnd, NULL, (LPPOINT)&winrect, 2); targetSurfaceDDraw = new gfxDDrawSurface(gpDDSurf.get(), winrect); targetSurface = targetSurfaceDDraw; } #endif DDRAW_FAILED: nsRefPtr<gfxImageSurface> targetSurfaceImage; if (!targetSurface && (IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH32) || IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24))) { gfxIntSize surfaceSize(ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top); if (!EnsureSharedSurfaceSize(surfaceSize)) { NS_ERROR("Couldn't allocate a shared image surface!"); return NS_ERROR_FAILURE; } // don't use the shared surface directly; instead, create a new one // that just reuses its buffer. targetSurfaceImage = new gfxImageSurface(sSharedSurfaceData.get(), surfaceSize, surfaceSize.width * 4, gfxASurface::ImageFormatRGB24); if (targetSurfaceImage && !targetSurfaceImage->CairoStatus()) { targetSurfaceImage->SetDeviceOffset(gfxPoint(-ps.rcPaint.left, -ps.rcPaint.top)); targetSurface = targetSurfaceImage; } } if (!targetSurface) { NS_ERROR("Invalid RenderMode!"); return NS_ERROR_FAILURE; } nsRefPtr<gfxContext> thebesContext = new gfxContext(targetSurface); thebesContext->SetFlag(gfxContext::FLAG_DESTINED_FOR_SCREEN); if (IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D) && paintRgnWin) { PRUint32 rects; paintRgnWin->GetNumRects(&rects); nsRegionRectSet *rectSet = NULL; paintRgnWin->GetRects(&rectSet); for (int i = 0; i < rectSet->mNumRects; i++) { thebesContext->Rectangle( gfxRect( rectSet->mRects[i].x, rectSet->mRects[i].y, rectSet->mRects[i].width, rectSet->mRects[i].height), PR_TRUE); } thebesContext->Clip(); paintRgnWin->FreeRects(rectSet); } #ifdef WINCE thebesContext->SetFlag(gfxContext::FLAG_SIMPLIFY_OPERATORS); #endif // don't need to double buffer with anything but GDI if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI)) { # if defined(MOZ_XUL) && !defined(WINCE) if (eTransparencyGlass == mTransparencyMode && nsUXThemeData::sHaveCompositor) { thebesContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA); } else if (eTransparencyTransparent == mTransparencyMode) { // If we're rendering with translucency, we're going to be // rendering the whole window; make sure we clear it first thebesContext->SetOperator(gfxContext::OPERATOR_CLEAR); thebesContext->Paint(); thebesContext->SetOperator(gfxContext::OPERATOR_OVER); } else #endif { // If we're not doing translucency, then double buffer thebesContext->PushGroup(gfxASurface::CONTENT_COLOR); } } nsCOMPtr<nsIRenderingContext> rc; nsresult rv = mContext->CreateRenderingContextInstance (*getter_AddRefs(rc)); if (NS_FAILED(rv)) { NS_WARNING("CreateRenderingContextInstance failed"); return PR_FALSE; } rv = rc->Init(mContext, thebesContext); if (NS_FAILED(rv)) { NS_WARNING("RC::Init failed"); return PR_FALSE; } event.renderingContext = rc; result = DispatchWindowEvent(&event, eventStatus); event.renderingContext = nsnull; #ifdef MOZ_XUL if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI) && eTransparencyTransparent == mTransparencyMode) { // Data from offscreen drawing surface was copied to memory bitmap of transparent // bitmap. Now it can be read from memory bitmap to apply alpha channel and after // that displayed on the screen. UpdateTranslucentWindow(); } else #endif #ifdef CAIRO_HAS_D2D_SURFACE if (result) { if (mD2DWindowSurface) { mD2DWindowSurface->Present(); } } #endif if (result) { if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI)) { // Only update if DispatchWindowEvent returned TRUE; otherwise, nothing handled // this, and we'll just end up painting with black. thebesContext->PopGroupToSource(); thebesContext->SetOperator(gfxContext::OPERATOR_SOURCE); thebesContext->Paint(); } else if (IsRenderMode(gfxWindowsPlatform::RENDER_DDRAW) || IsRenderMode(gfxWindowsPlatform::RENDER_DDRAW_GL)) { #ifdef CAIRO_HAS_DDRAW_SURFACE // blit with direct draw HRESULT hr = glpDDClipper->SetHWnd(0, mWnd); #ifdef DEBUG if (FAILED(hr)) DDError("SetHWnd", hr); #endif // blt from the affected area from the window back-buffer to the // screen-relative coordinates of the window paint area RECT dst_rect = ps.rcPaint; MapWindowPoints(mWnd, NULL, (LPPOINT)&dst_rect, 2); hr = glpDDPrimary->Blt(&dst_rect, gpDDSurf->GetDDSurface(), &dst_rect, DDBLT_WAITNOTBUSY, NULL); #ifdef DEBUG if (FAILED(hr)) DDError("SetHWnd", hr); #endif #endif } else if (IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24) || IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH32)) { gfxIntSize surfaceSize = targetSurfaceImage->GetSize(); // Just blit this directly BITMAPINFOHEADER bi; memset(&bi, 0, sizeof(BITMAPINFOHEADER)); bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = surfaceSize.width; bi.biHeight = - surfaceSize.height; bi.biPlanes = 1; bi.biBitCount = 32; bi.biCompression = BI_RGB; if (IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24)) { // On Windows CE/Windows Mobile, 24bpp packed-pixel sources // seem to be far faster to blit than 32bpp (see bug 484864). // So, convert the bits to 24bpp by stripping out the unused // alpha byte. 24bpp DIBs also have scanlines that are 4-byte // aligned though, so that must be taken into account. int srcstride = surfaceSize.width*4; int dststride = surfaceSize.width*3; dststride = (dststride + 3) & ~3; // Convert in place for (int j = 0; j < surfaceSize.height; ++j) { unsigned int *src = (unsigned int*) (targetSurfaceImage->Data() + j*srcstride); unsigned int *dst = (unsigned int*) (targetSurfaceImage->Data() + j*dststride); // go 4 pixels at a time, since each 4 pixels // turns into 3 DWORDs when converted into BGR: // BGRx BGRx BGRx BGRx -> BGRB GRBG RBGR // // However, since we're dealing with little-endian ints, this is actually: // xRGB xrgb xRGB xrgb -> bRGB GBrg rgbR int width_left = surfaceSize.width; while (width_left >= 4) { unsigned int a = *src++; unsigned int b = *src++; unsigned int c = *src++; unsigned int d = *src++; *dst++ = (a & 0x00ffffff) | (b << 24); *dst++ = ((b & 0x00ffff00) >> 8) | (c << 16); *dst++ = ((c & 0x00ff0000) >> 16) | (d << 8); width_left -= 4; } // then finish up whatever number of pixels are left, // using bytes. unsigned char *bsrc = (unsigned char*) src; unsigned char *bdst = (unsigned char*) dst; switch (width_left) { case 3: *bdst++ = *bsrc++; *bdst++ = *bsrc++; *bdst++ = *bsrc++; bsrc++; case 2: *bdst++ = *bsrc++; *bdst++ = *bsrc++; *bdst++ = *bsrc++; bsrc++; case 1: *bdst++ = *bsrc++; *bdst++ = *bsrc++; *bdst++ = *bsrc++; bsrc++; case 0: break; } } bi.biBitCount = 24; } StretchDIBits(hDC, ps.rcPaint.left, ps.rcPaint.top, surfaceSize.width, surfaceSize.height, 0, 0, surfaceSize.width, surfaceSize.height, targetSurfaceImage->Data(), (BITMAPINFO*) &bi, DIB_RGB_COLORS, SRCCOPY); } }