/*static*/ already_AddRefed<gfxASurface> ShadowLayerForwarder::PlatformOpenDescriptor(OpenMode aMode, const SurfaceDescriptor& aSurface) { SAMPLE_LABEL("ShadowLayerForwarder", "PlatformOpenDescriptor"); if (SurfaceDescriptor::TSurfaceDescriptorGralloc != aSurface.type()) { return nullptr; } sp<GraphicBuffer> buffer = GrallocBufferActor::GetFrom(aSurface.get_SurfaceDescriptorGralloc()); uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN; if (OPEN_READ_WRITE == aMode) { usage |= GRALLOC_USAGE_SW_WRITE_OFTEN; } void *vaddr; DebugOnly<status_t> status = buffer->lock(usage, &vaddr); // If we fail to lock, we'll just end up aborting anyway. MOZ_ASSERT(status == OK); gfxIntSize size = gfxIntSize(buffer->getWidth(), buffer->getHeight()); gfxImageFormat format = ImageFormatForPixelFormat(buffer->getPixelFormat()); long pixelStride = buffer->getStride(); long byteStride = pixelStride * gfxASurface::BytePerPixelFromFormat(format); nsRefPtr<gfxASurface> surf = new gfxImageSurface((unsigned char*)vaddr, size, byteStride, format); return surf->CairoStatus() ? nullptr : surf.forget(); }
PRUint32 nsInputStreamPump::OnStateStop() { SAMPLE_LABEL("Input", "nsInputStreamPump::OnStateTransfer"); LOG((" OnStateStop [this=%x status=%x]\n", this, mStatus)); // if an error occurred, we must be sure to pass the error onto the async // stream. in some cases, this is redundant, but since close is idempotent, // this is OK. otherwise, be sure to honor the "close-when-done" option. if (NS_FAILED(mStatus)) mAsyncStream->CloseWithStatus(mStatus); else if (mCloseWhenDone) mAsyncStream->Close(); mAsyncStream = 0; mTargetThread = 0; mIsPending = false; mListener->OnStopRequest(this, mListenerContext, mStatus); mListener = 0; mListenerContext = 0; if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus); return STATE_IDLE; }
bool ShadowLayerForwarder::PlatformAllocBuffer(const gfxIntSize& aSize, gfxASurface::gfxContentType aContent, uint32_t aCaps, SurfaceDescriptor* aBuffer) { // Some GL implementations fail to render gralloc textures with // width < 64. There's not much point in gralloc'ing buffers that // small anyway, so fall back on shared memory plus a texture // upload. if (aSize.width < 64) { return false; } SAMPLE_LABEL("ShadowLayerForwarder", "PlatformAllocBuffer"); // Gralloc buffers are efficiently mappable as gfxImageSurface, so // no need to check |aCaps & MAP_AS_IMAGE_SURFACE|. MaybeMagicGrallocBufferHandle handle; PGrallocBufferChild* gc = mShadowManager->SendPGrallocBufferConstructor(aSize, aContent, &handle); if (!gc) { NS_ERROR("GrallocBufferConstructor failed by returned null"); return false; } else if (handle.Tnull_t == handle.type()) { NS_ERROR("GrallocBufferConstructor failed by returning handle with type Tnull_t"); PGrallocBufferChild::Send__delete__(gc); return false; } GrallocBufferActor* gba = static_cast<GrallocBufferActor*>(gc); gba->InitFromHandle(handle.get_MagicGrallocBufferHandle()); *aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize, /* external */ false); return true; }
SharedSurface* SurfaceStream_TripleBuffer::SwapProducer(SurfaceFactory* factory, const gfxIntSize& size) { SAMPLE_LABEL("SurfaceStream_TripleBuffer", "SwapProducer"); MonitorAutoLock lock(mMonitor); if (mProducer) { RecycleScraps(factory); // If WaitForCompositor succeeds, mStaging has moved to mConsumer. // If it failed, we might have to scrap it. if (mStaging && !WaitForCompositor()) Scrap(mStaging); MOZ_ASSERT(!mStaging); Move(mProducer, mStaging); mStaging->Fence(); } MOZ_ASSERT(!mProducer); New(factory, size, mProducer); return mProducer; }
NS_IMETHODIMP PluginStreamListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt) { SAMPLE_LABEL("PluginStreamListener", "OnStartRequest"); nsCOMPtr<nsIContent> embed = mPluginDoc->GetPluginContent(); nsCOMPtr<nsIObjectLoadingContent> objlc = do_QueryInterface(embed); nsCOMPtr<nsIStreamListener> objListener = do_QueryInterface(objlc); if (!objListener) { NS_NOTREACHED("PluginStreamListener without appropriate content node"); return NS_BINDING_ABORTED; } SetStreamListener(objListener); // Sets up the ObjectLoadingContent tag as if it is waiting for a // channel, so it can proceed with a load normally once it gets OnStartRequest nsresult rv = objlc->InitializeFromChannel(request); if (NS_FAILED(rv)) { NS_NOTREACHED("InitializeFromChannel failed"); return rv; } // Note that because we're now hooked up to a plugin listener, this will // likely spawn a plugin, which may re-enter. return MediaDocumentStreamListener::OnStartRequest(request, ctxt); }
/*static*/ PGrallocBufferParent* GrallocBufferActor::Create(const gfxIntSize& aSize, const gfxContentType& aContent, MaybeMagicGrallocBufferHandle* aOutHandle) { SAMPLE_LABEL("GrallocBufferActor", "Create"); GrallocBufferActor* actor = new GrallocBufferActor(); *aOutHandle = null_t(); android::PixelFormat format = PixelFormatForContentType(aContent); sp<GraphicBuffer> buffer( new GraphicBuffer(aSize.width, aSize.height, format, GraphicBuffer::USAGE_SW_READ_OFTEN | GraphicBuffer::USAGE_SW_WRITE_OFTEN | GraphicBuffer::USAGE_HW_TEXTURE)); if (buffer->initCheck() != OK) return actor; size_t bpp = gfxASurface::BytePerPixelFromFormat( gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent)); actor->mAllocBytes = aSize.width * aSize.height * bpp; sCurrentAlloc += actor->mAllocBytes; actor->mGraphicBuffer = buffer; *aOutHandle = MagicGrallocBufferHandle(buffer); return actor; }
PRUint32 nsInputStreamPump::OnStateStart() { SAMPLE_LABEL("nsInputStreamPump", "OnStateStart"); LOG((" OnStateStart [this=%x]\n", this)); nsresult rv; // need to check the reason why the stream is ready. this is required // so our listener can check our status from OnStartRequest. // XXX async streams should have a GetStatus method! if (NS_SUCCEEDED(mStatus)) { PRUint32 avail; rv = mAsyncStream->Available(&avail); if (NS_FAILED(rv) && rv != NS_BASE_STREAM_CLOSED) mStatus = rv; } rv = mListener->OnStartRequest(this, mListenerContext); // an error returned from OnStartRequest should cause us to abort; however, // we must not stomp on mStatus if already canceled. if (NS_FAILED(rv) && NS_SUCCEEDED(mStatus)) mStatus = rv; return NS_SUCCEEDED(mStatus) ? STATE_TRANSFER : STATE_STOP; }
nsresult nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsIView* aView, nsEventStatus* aStatus) { SAMPLE_LABEL("event", "nsViewManager::DispatchEvent"); if ((NS_IS_MOUSE_EVENT(aEvent) && // Ignore mouse events that we synthesize. static_cast<nsMouseEvent*>(aEvent)->reason == nsMouseEvent::eReal && // Ignore mouse exit and enter (we'll get moves if the user // is really moving the mouse) since we get them when we // create and destroy widgets. aEvent->message != NS_MOUSE_EXIT && aEvent->message != NS_MOUSE_ENTER) || NS_IS_KEY_EVENT(aEvent) || NS_IS_IME_EVENT(aEvent) || aEvent->message == NS_PLUGIN_INPUT_EVENT) { gLastUserEventTime = PR_IntervalToMicroseconds(PR_IntervalNow()); } // Find the view whose coordinates system we're in. nsIView* view = aView; bool dispatchUsingCoordinates = NS_IsEventUsingCoordinates(aEvent); if (dispatchUsingCoordinates) { // Will dispatch using coordinates. Pretty bogus but it's consistent // with what presshell does. view = GetDisplayRootFor(view); } // If the view has no frame, look for a view that does. nsIFrame* frame = view->GetFrame(); if (!frame && (dispatchUsingCoordinates || NS_IS_KEY_EVENT(aEvent) || NS_IS_IME_RELATED_EVENT(aEvent) || NS_IS_NON_RETARGETED_PLUGIN_EVENT(aEvent) || aEvent->message == NS_PLUGIN_ACTIVATE || aEvent->message == NS_PLUGIN_FOCUS || aEvent->message == NS_PLUGIN_RESOLUTION_CHANGED)) { while (view && !view->GetFrame()) { view = view->GetParent(); } if (view) { frame = view->GetFrame(); } } if (nullptr != frame) { // Hold a refcount to the presshell. The continued existence of the // presshell will delay deletion of this view hierarchy should the event // want to cause its destruction in, say, some JavaScript event handler. nsCOMPtr<nsIPresShell> shell = view->GetViewManager()->GetPresShell(); if (shell) { return shell->HandleEvent(frame, aEvent, false, aStatus); } } *aStatus = nsEventStatus_eIgnore; return NS_OK; }
bool SurfaceStream_TripleBuffer_Async::WaitForCompositor() { SAMPLE_LABEL("SurfaceStream_TripleBuffer_Async", "WaitForCompositor"); // We are assumed to be locked while (mStaging) mMonitor.Wait(); return true; }
/*static*/ already_AddRefed<TextureImage> ShadowLayerManager::OpenDescriptorForDirectTexturing(GLContext* aGL, const SurfaceDescriptor& aDescriptor, GLenum aWrapMode) { SAMPLE_LABEL("ShadowLayerManager", "OpenDescriptorForDirectTexturing"); if (SurfaceDescriptor::TSurfaceDescriptorGralloc != aDescriptor.type()) { return nullptr; } sp<GraphicBuffer> buffer = GrallocBufferActor::GetFrom(aDescriptor); return aGL->CreateDirectTextureImage(buffer.get(), aWrapMode); }
void ThebesLayerBuffer::DrawBufferWithRotation(gfxContext* aTarget, float aOpacity, gfxASurface* aMask, const gfxMatrix* aMaskTransform) { SAMPLE_LABEL("ThebesLayerBuffer", "DrawBufferWithRotation"); // Draw four quadrants. We could use REPEAT_, but it's probably better // not to, to be performance-safe. DrawBufferQuadrant(aTarget, LEFT, TOP, aOpacity, aMask, aMaskTransform); DrawBufferQuadrant(aTarget, RIGHT, TOP, aOpacity, aMask, aMaskTransform); DrawBufferQuadrant(aTarget, LEFT, BOTTOM, aOpacity, aMask, aMaskTransform); DrawBufferQuadrant(aTarget, RIGHT, BOTTOM, aOpacity, aMask, aMaskTransform); }
NS_IMETHODIMP PluginStreamListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt) { SAMPLE_LABEL("PluginStreamListener", "OnStartRequest"); // Have to set up our plugin stuff before we call OnStartRequest, so // that the plugin listener can get that call. nsresult rv = SetupPlugin(); NS_ASSERTION(NS_FAILED(rv) || mNextStream, "We should have a listener by now"); nsresult rv2 = MediaDocumentStreamListener::OnStartRequest(request, ctxt); return NS_SUCCEEDED(rv) ? rv2 : rv; }
/*static*/ bool ShadowLayerForwarder::PlatformCloseDescriptor(const SurfaceDescriptor& aDescriptor) { SAMPLE_LABEL("ShadowLayerForwarder", "PlatformCloseDescriptor"); if (SurfaceDescriptor::TSurfaceDescriptorGralloc != aDescriptor.type()) { return false; } sp<GraphicBuffer> buffer = GrallocBufferActor::GetFrom(aDescriptor); // If the buffer wasn't lock()d, this probably blows up. But since // PlatformCloseDescriptor() is private and only used by // AutoOpenSurface, we want to know if the logic is wrong there. buffer->unlock(); return true; }
NS_IMETHODIMP nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream *stream) { LOG(("nsInputStreamPump::OnInputStreamReady [this=%x]\n", this)); SAMPLE_LABEL("Input", "nsInputStreamPump::OnInputStreamReady"); // this function has been called from a PLEvent, so we can safely call // any listener or progress sink methods directly from here. for (;;) { if (mSuspendCount || mState == STATE_IDLE) { mWaiting = false; break; } PRUint32 nextState; switch (mState) { case STATE_START: nextState = OnStateStart(); break; case STATE_TRANSFER: nextState = OnStateTransfer(); break; case STATE_STOP: nextState = OnStateStop(); break; default: nextState = 0; NS_NOTREACHED("Unknown enum value."); return NS_ERROR_UNEXPECTED; } if (mState == nextState && !mSuspendCount) { NS_ASSERTION(mState == STATE_TRANSFER, "unexpected state"); NS_ASSERTION(NS_SUCCEEDED(mStatus), "unexpected status"); mWaiting = false; mStatus = EnsureWaiting(); if (NS_SUCCEEDED(mStatus)) break; nextState = STATE_STOP; } mState = nextState; } return NS_OK; }
// Unlike other cross-process forwarding methods, GetValue needs to replicate // the following behaviour of DOMStorageImpl::GetValue: // // - if a security error occurs, or the item isn't found, return null without // propogating the error. // // If DOMStorageImpl::GetValue ever changes its behaviour, this should be kept // in sync. nsIDOMStorageItem* StorageChild::GetValue(bool aCallerSecure, const nsAString& aKey, nsresult* rv) { SAMPLE_LABEL("StorageChild", "GetValue"); nsresult rv2 = *rv = NS_OK; StorageItem storageItem; SendGetValue(aCallerSecure, mSessionOnly, nsString(aKey), &storageItem, &rv2); if (rv2 == NS_ERROR_DOM_SECURITY_ERR || rv2 == NS_ERROR_DOM_NOT_FOUND_ERR) return nullptr; *rv = rv2; if (NS_FAILED(*rv) || storageItem.type() == StorageItem::Tnull_t) return nullptr; const ItemData& data = storageItem.get_ItemData(); nsIDOMStorageItem* item = new nsDOMStorageItem(this, aKey, data.value(), data.secure()); return item; }
/*static*/ PGrallocBufferParent* GrallocBufferActor::Create(const gfxIntSize& aSize, const gfxContentType& aContent, MaybeMagicGrallocBufferHandle* aOutHandle) { SAMPLE_LABEL("GrallocBufferActor", "Create"); GrallocBufferActor* actor = new GrallocBufferActor(); *aOutHandle = null_t(); android::PixelFormat format = PixelFormatForContentType(aContent); sp<GraphicBuffer> buffer( new GraphicBuffer(aSize.width, aSize.height, format, GraphicBuffer::USAGE_SW_READ_OFTEN | GraphicBuffer::USAGE_SW_WRITE_OFTEN | GraphicBuffer::USAGE_HW_TEXTURE)); if (buffer->initCheck() != OK) return actor; actor->mGraphicBuffer = buffer; *aOutHandle = MagicGrallocBufferHandle(buffer); return actor; }
bool ShadowLayerForwarder::PlatformAllocBuffer(const gfxIntSize& aSize, gfxASurface::gfxContentType aContent, uint32_t aCaps, SurfaceDescriptor* aBuffer) { SAMPLE_LABEL("ShadowLayerForwarder", "PlatformAllocBuffer"); // Gralloc buffers are efficiently mappable as gfxImageSurface, so // no need to check |aCaps & MAP_AS_IMAGE_SURFACE|. MaybeMagicGrallocBufferHandle handle; PGrallocBufferChild* gc = mShadowManager->SendPGrallocBufferConstructor(aSize, aContent, &handle); if (handle.Tnull_t == handle.type()) { PGrallocBufferChild::Send__delete__(gc); return false; } GrallocBufferActor* gba = static_cast<GrallocBufferActor*>(gc); gba->InitFromHandle(handle.get_MagicGrallocBufferHandle()); *aBuffer = SurfaceDescriptorGralloc(nullptr, gc, /* external */ false); return true; }
NS_IMETHODIMP nsStreamLoader::OnStopRequest(nsIRequest* request, nsISupports *ctxt, nsresult aStatus) { SAMPLE_LABEL("network", "nsStreamLoader::OnStopRequest"); if (mObserver) { // provide nsIStreamLoader::request during call to OnStreamComplete mRequest = request; nsresult rv = mObserver->OnStreamComplete(this, mContext, aStatus, mLength, mData); if (rv == NS_SUCCESS_ADOPTED_DATA) { // the observer now owns the data buffer, and the loader must // not deallocate it mData = nullptr; mLength = 0; mAllocated = 0; } // done.. cleanup mRequest = 0; mObserver = 0; mContext = 0; } return NS_OK; }
void RestyleTracker::DoProcessRestyles() { SAMPLE_LABEL("CSS", "ProcessRestyles"); // Make sure to not rebuild quote or counter lists while we're // processing restyles mFrameConstructor->BeginUpdate(); mFrameConstructor->mInStyleRefresh = true; // loop so that we process any restyle events generated by processing while (mPendingRestyles.Count()) { if (mHaveLaterSiblingRestyles) { // Convert them to individual restyles on all the later siblings nsAutoTArray<nsRefPtr<Element>, RESTYLE_ARRAY_STACKSIZE> laterSiblingArr; LaterSiblingCollector siblingCollector = { this, &laterSiblingArr }; mPendingRestyles.Enumerate(CollectLaterSiblings, &siblingCollector); for (PRUint32 i = 0; i < laterSiblingArr.Length(); ++i) { Element* element = laterSiblingArr[i]; for (nsIContent* sibling = element->GetNextSibling(); sibling; sibling = sibling->GetNextSibling()) { if (sibling->IsElement() && AddPendingRestyle(sibling->AsElement(), eRestyle_Subtree, NS_STYLE_HINT_NONE)) { // Nothing else to do here; we'll handle the following // siblings when we get to |sibling| in laterSiblingArr. break; } } } // Now remove all those eRestyle_LaterSiblings bits for (PRUint32 i = 0; i < laterSiblingArr.Length(); ++i) { Element* element = laterSiblingArr[i]; NS_ASSERTION(element->HasFlag(RestyleBit()), "How did that happen?"); RestyleData data; #ifdef DEBUG bool found = #endif mPendingRestyles.Get(element, &data); NS_ASSERTION(found, "Where did our entry go?"); data.mRestyleHint = nsRestyleHint(data.mRestyleHint & ~eRestyle_LaterSiblings); mPendingRestyles.Put(element, data); } mHaveLaterSiblingRestyles = false; } PRUint32 rootCount; while ((rootCount = mRestyleRoots.Length())) { // Make sure to pop the element off our restyle root array, so // that we can freely append to the array as we process this // element. nsRefPtr<Element> element; element.swap(mRestyleRoots[rootCount - 1]); mRestyleRoots.RemoveElementAt(rootCount - 1); // Do the document check before calling GetRestyleData, since we // don't want to do the sibling-processing GetRestyleData does if // the node is no longer relevant. if (element->GetCurrentDoc() != Document()) { // Content node has been removed from our document; nothing else // to do here continue; } RestyleData data; if (!GetRestyleData(element, &data)) { continue; } ProcessOneRestyle(element, data.mRestyleHint, data.mChangeHint); } if (mHaveLaterSiblingRestyles) { // Keep processing restyles for now continue; } // Now we only have entries with change hints left. To be safe in // case of reentry from the handing of the change hint, use a // scratch array instead of calling out to ProcessOneRestyle while // enumerating the hashtable. Use the stack if we can, otherwise // fall back on heap-allocation. nsAutoTArray<RestyleEnumerateData, RESTYLE_ARRAY_STACKSIZE> restyleArr; RestyleEnumerateData* restylesToProcess = restyleArr.AppendElements(mPendingRestyles.Count()); if (restylesToProcess) { RestyleEnumerateData* lastRestyle = restylesToProcess; RestyleCollector collector = { this, &lastRestyle }; mPendingRestyles.Enumerate(CollectRestyles, &collector); // Clear the hashtable now that we don't need it anymore mPendingRestyles.Clear(); for (RestyleEnumerateData* currentRestyle = restylesToProcess; currentRestyle != lastRestyle; ++currentRestyle) { ProcessOneRestyle(currentRestyle->mElement, currentRestyle->mRestyleHint, currentRestyle->mChangeHint); } } } // Set mInStyleRefresh to false now, since the EndUpdate call might // add more restyles. mFrameConstructor->mInStyleRefresh = false; mFrameConstructor->EndUpdate(); #ifdef DEBUG mFrameConstructor->mPresShell->VerifyStyleTree(); #endif }
NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsIView* aView, nsEventStatus *aStatus) { NS_ASSERTION(!aView || static_cast<nsView*>(aView)->GetViewManager() == this, "wrong view manager"); SAMPLE_LABEL("event", "nsViewManager::DispatchEvent"); *aStatus = nsEventStatus_eIgnore; switch(aEvent->message) { case NS_SIZE: { if (aView) { // client area dimensions are set on the view nscoord width = ((nsSizeEvent*)aEvent)->windowSize->width; nscoord height = ((nsSizeEvent*)aEvent)->windowSize->height; // The root view may not be set if this is the resize associated with // window creation if (aView == mRootView) { PRInt32 p2a = AppUnitsPerDevPixel(); SetWindowDimensions(NSIntPixelsToAppUnits(width, p2a), NSIntPixelsToAppUnits(height, p2a)); *aStatus = nsEventStatus_eConsumeNoDefault; } else if (IsViewForPopup(aView)) { nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); if (pm) { pm->PopupResized(aView->GetFrame(), nsIntSize(width, height)); *aStatus = nsEventStatus_eConsumeNoDefault; } } } } break; case NS_MOVE: { // A popup's parent view is the root view for the parent window, so when // a popup moves, the popup's frame and view position must be updated // to match. if (aView && IsViewForPopup(aView)) { nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); if (pm) { pm->PopupMoved(aView->GetFrame(), aEvent->refPoint); *aStatus = nsEventStatus_eConsumeNoDefault; } } break; } case NS_DONESIZEMOVE: { if (mPresShell) { nsPresContext* presContext = mPresShell->GetPresContext(); if (presContext) { nsEventStateManager::ClearGlobalActiveContent(nsnull); } } nsIPresShell::ClearMouseCapture(nsnull); } break; case NS_XUL_CLOSE: { // if this is a popup, make a request to hide it. Note that a popuphidden // event listener may cancel the event and the popup will not be hidden. nsIWidget* widget = aView->GetWidget(); if (widget) { nsWindowType type; widget->GetWindowType(type); if (type == eWindowType_popup) { nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); if (pm) { pm->HidePopup(aView->GetFrame()); *aStatus = nsEventStatus_eConsumeNoDefault; } } } } break; case NS_WILL_PAINT: { if (!aView || !mContext) break; *aStatus = nsEventStatus_eConsumeNoDefault; nsPaintEvent *event = static_cast<nsPaintEvent*>(aEvent); NS_ASSERTION(static_cast<nsView*>(aView) == nsView::GetViewFor(event->widget), "view/widget mismatch"); // If an ancestor widget was hidden and then shown, we could // have a delayed resize to handle. for (nsViewManager *vm = this; vm; vm = vm->mRootView->GetParent() ? vm->mRootView->GetParent()->GetViewManager() : nsnull) { if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) && vm->mRootView->IsEffectivelyVisible() && mPresShell && mPresShell->IsVisible()) { vm->FlushDelayedResize(true); vm->InvalidateView(vm->mRootView); } } // Flush things like reflows and plugin widget geometry updates by // calling WillPaint on observer presShells. nsRefPtr<nsViewManager> rootVM = RootViewManager(); if (mPresShell) { rootVM->CallWillPaintOnObservers(event->willSendDidPaint); } // Flush view widget geometry updates and invalidations. rootVM->ProcessPendingUpdates(); } break; case NS_PAINT: { if (!aView || !mContext) break; *aStatus = nsEventStatus_eConsumeNoDefault; nsPaintEvent *event = static_cast<nsPaintEvent*>(aEvent); nsView* view = static_cast<nsView*>(aView); NS_ASSERTION(view == nsView::GetViewFor(event->widget), "view/widget mismatch"); NS_ASSERTION(IsPaintingAllowed(), "shouldn't be receiving paint events while painting is " "disallowed!"); if (!event->didSendWillPaint) { // Send NS_WILL_PAINT event ourselves. nsPaintEvent willPaintEvent(true, NS_WILL_PAINT, event->widget); willPaintEvent.willSendDidPaint = event->willSendDidPaint; DispatchEvent(&willPaintEvent, view, aStatus); // Get the view pointer again since NS_WILL_PAINT might have // destroyed it during CallWillPaintOnObservers (bug 378273). view = nsView::GetViewFor(event->widget); } if (!view || event->region.IsEmpty()) break; // Paint. Refresh(view, event->region, event->willSendDidPaint); break; } case NS_DID_PAINT: { nsRefPtr<nsViewManager> rootVM = RootViewManager(); rootVM->CallDidPaintOnObserver(); break; } case NS_CREATE: case NS_DESTROY: case NS_SETZLEVEL: /* Don't pass these events through. Passing them through causes performance problems on pages with lots of views/frames @see bug 112861 */ *aStatus = nsEventStatus_eConsumeNoDefault; break; case NS_DISPLAYCHANGED: //Destroy the cached backbuffer to force a new backbuffer //be constructed with the appropriate display depth. //@see bugzilla bug 6061 *aStatus = nsEventStatus_eConsumeDoDefault; break; case NS_SYSCOLORCHANGED: { if (mPresShell) { // Hold a refcount to the presshell. The continued existence of the observer will // delay deletion of this view hierarchy should the event want to cause its // destruction in, say, some JavaScript event handler. nsCOMPtr<nsIPresShell> presShell = mPresShell; presShell->HandleEvent(aView->GetFrame(), aEvent, false, aStatus); } } break; default: { if ((NS_IS_MOUSE_EVENT(aEvent) && // Ignore mouse events that we synthesize. static_cast<nsMouseEvent*>(aEvent)->reason == nsMouseEvent::eReal && // Ignore mouse exit and enter (we'll get moves if the user // is really moving the mouse) since we get them when we // create and destroy widgets. aEvent->message != NS_MOUSE_EXIT && aEvent->message != NS_MOUSE_ENTER) || NS_IS_KEY_EVENT(aEvent) || NS_IS_IME_EVENT(aEvent) || aEvent->message == NS_PLUGIN_INPUT_EVENT) { gLastUserEventTime = PR_IntervalToMicroseconds(PR_IntervalNow()); } if (aEvent->message == NS_DEACTIVATE) { // if a window is deactivated, clear the mouse capture regardless // of what is capturing nsIPresShell::ClearMouseCapture(nsnull); } // Find the view whose coordinates system we're in. nsIView* view = aView; bool dispatchUsingCoordinates = NS_IsEventUsingCoordinates(aEvent); if (dispatchUsingCoordinates) { // Will dispatch using coordinates. Pretty bogus but it's consistent // with what presshell does. view = GetDisplayRootFor(view); } // If the view has no frame, look for a view that does. nsIFrame* frame = view->GetFrame(); if (!frame && (dispatchUsingCoordinates || NS_IS_KEY_EVENT(aEvent) || NS_IS_IME_RELATED_EVENT(aEvent) || NS_IS_NON_RETARGETED_PLUGIN_EVENT(aEvent) || aEvent->message == NS_PLUGIN_ACTIVATE || aEvent->message == NS_PLUGIN_FOCUS)) { while (view && !view->GetFrame()) { view = view->GetParent(); } if (view) { frame = view->GetFrame(); } } if (nsnull != frame) { // Hold a refcount to the presshell. The continued existence of the // presshell will delay deletion of this view hierarchy should the event // want to cause its destruction in, say, some JavaScript event handler. nsCOMPtr<nsIPresShell> shell = view->GetViewManager()->GetPresShell(); if (shell) { shell->HandleEvent(frame, aEvent, false, aStatus); } } break; } } return NS_OK; }
void LayerManagerOGL::Render() { SAMPLE_LABEL("LayerManagerOGL", "Render"); if (mDestroyed) { NS_WARNING("Call on destroyed layer manager"); return; } nsIntRect rect; mWidget->GetClientBounds(rect); WorldTransformRect(rect); GLint width = rect.width; GLint height = rect.height; // We can't draw anything to something with no area // so just return if (width == 0 || height == 0) return; // If the widget size changed, we have to force a MakeCurrent // to make sure that GL sees the updated widget size. if (mWidgetSize.width != width || mWidgetSize.height != height) { MakeCurrent(true); mWidgetSize.width = width; mWidgetSize.height = height; } else { MakeCurrent(); } SetupBackBuffer(width, height); SetupPipeline(width, height, ApplyWorldTransform); // Default blend function implements "OVER" mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA, LOCAL_GL_ONE, LOCAL_GL_ONE); mGLContext->fEnable(LOCAL_GL_BLEND); const nsIntRect *clipRect = mRoot->GetClipRect(); if (clipRect) { nsIntRect r = *clipRect; WorldTransformRect(r); mGLContext->fScissor(r.x, r.y, r.width, r.height); } else { mGLContext->fScissor(0, 0, width, height); } mGLContext->fEnable(LOCAL_GL_SCISSOR_TEST); mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0); mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT); // Render our layers. RootLayer()->RenderLayer(mGLContext->IsDoubleBuffered() ? 0 : mBackBufferFBO, nsIntPoint(0, 0)); mWidget->DrawWindowOverlay(this, rect); #ifdef MOZ_DUMP_PAINTING if (gfxUtils::sDumpPainting) { nsIntRect rect; mWidget->GetBounds(rect); nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(rect.Size(), gfxASurface::CONTENT_COLOR_ALPHA); nsRefPtr<gfxContext> ctx = new gfxContext(surf); CopyToTarget(ctx); WriteSnapshotToDumpFile(this, surf); } #endif if (mTarget) { CopyToTarget(mTarget); mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); return; } if (sDrawFPS) { mFPS.DrawFPS(mGLContext, GetCopy2DProgram()); } if (mGLContext->IsDoubleBuffered()) { mGLContext->SwapBuffers(); LayerManager::PostPresent(); mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); return; } mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0); mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0); CopyProgram *copyprog = GetCopy2DProgram(); if (mFBOTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) { copyprog = GetCopy2DRectProgram(); } mGLContext->fBindTexture(mFBOTextureTarget, mBackBufferTexture); copyprog->Activate(); copyprog->SetTextureUnit(0); if (copyprog->GetTexCoordMultiplierUniformLocation() != -1) { float f[] = { float(width), float(height) }; copyprog->SetUniform(copyprog->GetTexCoordMultiplierUniformLocation(), 2, f); } // we're going to use client-side vertex arrays for this. mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); // "COPY" mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ZERO, LOCAL_GL_ONE, LOCAL_GL_ZERO); // enable our vertex attribs; we'll call glVertexPointer below // to fill with the correct data. GLint vcattr = copyprog->AttribLocation(CopyProgram::VertexCoordAttrib); GLint tcattr = copyprog->AttribLocation(CopyProgram::TexCoordAttrib); mGLContext->fEnableVertexAttribArray(vcattr); mGLContext->fEnableVertexAttribArray(tcattr); const nsIntRect *r; nsIntRegionRectIterator iter(mClippingRegion); while ((r = iter.Next()) != nsnull) { nsIntRect cRect = *r; r = &cRect; WorldTransformRect(cRect); float left = (GLfloat)r->x / width; float right = (GLfloat)r->XMost() / width; float top = (GLfloat)r->y / height; float bottom = (GLfloat)r->YMost() / height; float vertices[] = { left * 2.0f - 1.0f, -(top * 2.0f - 1.0f), right * 2.0f - 1.0f, -(top * 2.0f - 1.0f), left * 2.0f - 1.0f, -(bottom * 2.0f - 1.0f), right * 2.0f - 1.0f, -(bottom * 2.0f - 1.0f) }; // Use flipped texture coordinates since our // projection matrix also has a flip and we // need to cancel that out. float coords[] = { left, bottom, right, bottom, left, top, right, top }; mGLContext->fVertexAttribPointer(vcattr, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, vertices); mGLContext->fVertexAttribPointer(tcattr, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, coords); mGLContext->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); } mGLContext->fDisableVertexAttribArray(vcattr); mGLContext->fDisableVertexAttribArray(tcattr); mGLContext->fFlush(); mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); }
bool ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies) { SAMPLE_LABEL("ShadowLayerForwarder", "EndTranscation"); RenderTraceScope rendertrace("Foward Transaction", "000091"); NS_ABORT_IF_FALSE(HasShadowManager(), "no manager to forward to"); NS_ABORT_IF_FALSE(!mTxn->Finished(), "forgot BeginTransaction?"); AutoTxnEnd _(mTxn); if (mTxn->Empty()) { MOZ_LAYERS_LOG(("[LayersForwarder] 0-length cset (?), skipping Update()")); return true; } MOZ_LAYERS_LOG(("[LayersForwarder] destroying buffers...")); for (PRUint32 i = 0; i < mTxn->mDyingBuffers.Length(); ++i) { DestroySharedSurface(&mTxn->mDyingBuffers[i]); } MOZ_LAYERS_LOG(("[LayersForwarder] building transaction...")); // We purposely add attribute-change ops to the final changeset // before we add paint ops. This allows layers to record the // attribute changes before new pixels arrive, which can be useful // for setting up back/front buffers. RenderTraceScope rendertrace2("Foward Transaction", "000092"); for (ShadowableLayerSet::const_iterator it = mTxn->mMutants.begin(); it != mTxn->mMutants.end(); ++it) { ShadowableLayer* shadow = *it; Layer* mutant = shadow->AsLayer(); NS_ABORT_IF_FALSE(!!mutant, "unshadowable layer?"); LayerAttributes attrs; CommonLayerAttributes& common = attrs.common(); common.visibleRegion() = mutant->GetVisibleRegion(); common.transform() = mutant->GetTransform(); common.contentFlags() = mutant->GetContentFlags(); common.opacity() = mutant->GetOpacity(); common.useClipRect() = !!mutant->GetClipRect(); common.clipRect() = (common.useClipRect() ? *mutant->GetClipRect() : nsIntRect()); common.isFixedPosition() = mutant->GetIsFixedPosition(); if (Layer* maskLayer = mutant->GetMaskLayer()) { common.maskLayerChild() = Shadow(maskLayer->AsShadowableLayer()); } else { common.maskLayerChild() = NULL; } common.maskLayerParent() = NULL; attrs.specific() = null_t(); mutant->FillSpecificAttributes(attrs.specific()); mTxn->AddEdit(OpSetLayerAttributes(NULL, Shadow(shadow), attrs)); } AutoInfallibleTArray<Edit, 10> cset; size_t nCsets = mTxn->mCset.size() + mTxn->mPaints.size(); NS_ABORT_IF_FALSE(nCsets > 0, "should have bailed by now"); cset.SetCapacity(nCsets); if (!mTxn->mCset.empty()) { cset.AppendElements(&mTxn->mCset.front(), mTxn->mCset.size()); } // Paints after non-paint ops, including attribute changes. See // above. if (!mTxn->mPaints.empty()) { cset.AppendElements(&mTxn->mPaints.front(), mTxn->mPaints.size()); } MOZ_LAYERS_LOG(("[LayersForwarder] syncing before send...")); PlatformSyncBeforeUpdate(); if (mTxn->mSwapRequired) { MOZ_LAYERS_LOG(("[LayersForwarder] sending transaction...")); RenderTraceScope rendertrace3("Forward Transaction", "000093"); if (!mShadowManager->SendUpdate(cset, mIsFirstPaint, aReplies)) { MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!")); return false; } } else { // If we don't require a swap we can call SendUpdateNoSwap which // assumes that aReplies is empty (DEBUG assertion) MOZ_LAYERS_LOG(("[LayersForwarder] sending no swap transaction...")); RenderTraceScope rendertrace3("Forward NoSwap Transaction", "000093"); if (!mShadowManager->SendUpdateNoSwap(cset, mIsFirstPaint)) { MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!")); return false; } } mIsFirstPaint = false; MOZ_LAYERS_LOG(("[LayersForwarder] ... done")); return true; }
NS_IMETHODIMP nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, nsISupports* aContext) { nsresult rv = NS_OK; SAMPLE_LABEL("nsPluginStreamListenerPeer", "OnStartRequest"); if (mRequests.IndexOfObject(GetBaseRequest(request)) == -1) { NS_ASSERTION(mRequests.Count() == 0, "Only our initial stream should be unknown!"); TrackRequest(request); } if (mHaveFiredOnStartRequest) { return NS_OK; } mHaveFiredOnStartRequest = true; nsCOMPtr<nsIChannel> channel = do_QueryInterface(request); NS_ENSURE_TRUE(channel, NS_ERROR_FAILURE); // deal with 404 (Not Found) HTTP response, // just return, this causes the request to be ignored. nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); if (httpChannel) { uint32_t responseCode = 0; rv = httpChannel->GetResponseStatus(&responseCode); if (NS_FAILED(rv)) { // NPP_Notify() will be called from OnStopRequest // in nsNPAPIPluginStreamListener::CleanUpStream // return error will cancel this request // ...and we also need to tell the plugin that mRequestFailed = true; return NS_ERROR_FAILURE; } if (responseCode > 206) { // not normal uint32_t wantsAllNetworkStreams = 0; // We don't always have an instance here already, but if we do, check // to see if it wants all streams. if (mPluginInstance) { rv = mPluginInstance->GetValueFromPlugin(NPPVpluginWantsAllNetworkStreams, &wantsAllNetworkStreams); // If the call returned an error code make sure we still use our default value. if (NS_FAILED(rv)) { wantsAllNetworkStreams = 0; } } if (!wantsAllNetworkStreams) { mRequestFailed = true; return NS_ERROR_FAILURE; } } } // Get the notification callbacks from the channel and save it as // week ref we'll use it in nsPluginStreamInfo::RequestRead() when // we'll create channel for byte range request. nsCOMPtr<nsIInterfaceRequestor> callbacks; channel->GetNotificationCallbacks(getter_AddRefs(callbacks)); if (callbacks) mWeakPtrChannelCallbacks = do_GetWeakReference(callbacks); nsCOMPtr<nsILoadGroup> loadGroup; channel->GetLoadGroup(getter_AddRefs(loadGroup)); if (loadGroup) mWeakPtrChannelLoadGroup = do_GetWeakReference(loadGroup); int64_t length; rv = channel->GetContentLength(&length); // it's possible for the server to not send a Content-Length. // we should still work in this case. if (NS_FAILED(rv) || length == -1) { // check out if this is file channel nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(channel); if (fileChannel) { // file does not exist mRequestFailed = true; return NS_ERROR_FAILURE; } mLength = 0; } else { mLength = length; } nsAutoCString aContentType; // XXX but we already got the type above! rv = channel->GetContentType(aContentType); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsIURI> aURL; rv = channel->GetURI(getter_AddRefs(aURL)); if (NS_FAILED(rv)) return rv; aURL->GetSpec(mURLSpec); if (!aContentType.IsEmpty()) mContentType = aContentType; #ifdef PLUGIN_LOGGING PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NOISY, ("nsPluginStreamListenerPeer::OnStartRequest this=%p request=%p mime=%s, url=%s\n", this, request, aContentType.get(), mURLSpec.get())); PR_LogFlush(); #endif // Set up the stream listener... rv = SetUpStreamListener(request, aURL); if (NS_FAILED(rv)) return rv; return rv; }
PRUint32 nsInputStreamPump::OnStateTransfer() { SAMPLE_LABEL("Input", "nsInputStreamPump::OnStateTransfer"); LOG((" OnStateTransfer [this=%x]\n", this)); // if canceled, go directly to STATE_STOP... if (NS_FAILED(mStatus)) return STATE_STOP; nsresult rv; PRUint32 avail; rv = mAsyncStream->Available(&avail); LOG((" Available returned [stream=%x rv=%x avail=%u]\n", mAsyncStream.get(), rv, avail)); if (rv == NS_BASE_STREAM_CLOSED) { rv = NS_OK; avail = 0; } else if (NS_SUCCEEDED(rv) && avail) { // figure out how much data to report (XXX detect overflow??) if (PRUint64(avail) + mStreamOffset > mStreamLength) avail = PRUint32(mStreamLength - mStreamOffset); if (avail) { // we used to limit avail to 16K - we were afraid some ODA handlers // might assume they wouldn't get more than 16K at once // we're removing that limit since it speeds up local file access. // Now there's an implicit 64K limit of 4 16K segments // NOTE: ok, so the story is as follows. OnDataAvailable impls // are by contract supposed to consume exactly |avail| bytes. // however, many do not... mailnews... stream converters... // cough, cough. the input stream pump is fairly tolerant // in this regard; however, if an ODA does not consume any // data from the stream, then we could potentially end up in // an infinite loop. we do our best here to try to catch // such an error. (see bug 189672) // in most cases this QI will succeed (mAsyncStream is almost always // a nsPipeInputStream, which implements nsISeekableStream::Tell). PRInt64 offsetBefore; nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mAsyncStream); if (seekable && NS_FAILED(seekable->Tell(&offsetBefore))) { NS_NOTREACHED("Tell failed on readable stream"); offsetBefore = 0; } // report the current stream offset to our listener... if we've // streamed more than PR_UINT32_MAX, then avoid overflowing the // stream offset. it's the best we can do without a 64-bit stream // listener API. PRUint32 odaOffset = mStreamOffset > PR_UINT32_MAX ? PR_UINT32_MAX : PRUint32(mStreamOffset); LOG((" calling OnDataAvailable [offset=%lld(%u) count=%u]\n", mStreamOffset, odaOffset, avail)); rv = mListener->OnDataAvailable(this, mListenerContext, mAsyncStream, odaOffset, avail); // don't enter this code if ODA failed or called Cancel if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(mStatus)) { // test to see if this ODA failed to consume data if (seekable) { // NOTE: if Tell fails, which can happen if the stream is // now closed, then we assume that everything was read. PRInt64 offsetAfter; if (NS_FAILED(seekable->Tell(&offsetAfter))) offsetAfter = offsetBefore + avail; if (offsetAfter > offsetBefore) mStreamOffset += (offsetAfter - offsetBefore); else if (mSuspendCount == 0) { // // possible infinite loop if we continue pumping data! // // NOTE: although not allowed by nsIStreamListener, we // will allow the ODA impl to Suspend the pump. IMAP // does this :-( // NS_ERROR("OnDataAvailable implementation consumed no data"); mStatus = NS_ERROR_UNEXPECTED; } } else mStreamOffset += avail; // assume ODA behaved well } } } // an error returned from Available or OnDataAvailable should cause us to // abort; however, we must not stomp on mStatus if already canceled. if (NS_SUCCEEDED(mStatus)) { if (NS_FAILED(rv)) mStatus = rv; else if (avail) { // if stream is now closed, advance to STATE_STOP right away. // Available may return 0 bytes available at the moment; that // would not mean that we are done. // XXX async streams should have a GetStatus method! rv = mAsyncStream->Available(&avail); if (NS_SUCCEEDED(rv)) return STATE_TRANSFER; } } return STATE_STOP; }