void SimpleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion, const nsIntRegion& aPaintRegion, LayerManager::DrawThebesLayerCallback aCallback, void* aCallbackData) { mCallback = aCallback; mCallbackData = aCallbackData; #ifdef GFX_TILEDLAYER_PREF_WARNINGS long start = PR_IntervalNow(); #endif // If this region is empty XMost() - 1 will give us a negative value. NS_ASSERTION(!aPaintRegion.GetBounds().IsEmpty(), "Empty paint region\n"); PROFILER_LABEL("SimpleTiledLayerBuffer", "PaintThebesUpdate"); Update(aNewValidRegion, aPaintRegion); #ifdef GFX_TILEDLAYER_PREF_WARNINGS if (PR_IntervalNow() - start > 10) { const nsIntRect bounds = aPaintRegion.GetBounds(); printf_stderr("Time to tile [%i, %i, %i, %i] -> %i\n", bounds.x, bounds.y, bounds.width, bounds.height, PR_IntervalNow() - start); } #endif mLastPaintOpaque = mThebesLayer->CanUseOpaqueSurface(); mCallback = nullptr; mCallbackData = nullptr; }
nsresult WebMWriter::SetMetadata(TrackMetadataBase* aMetadata) { MOZ_ASSERT(aMetadata); PROFILER_LABEL("WebMWriter", "SetMetadata", js::ProfileEntry::Category::OTHER); if (aMetadata->GetKind() == TrackMetadataBase::METADATA_VP8) { VP8Metadata* meta = static_cast<VP8Metadata*>(aMetadata); MOZ_ASSERT(meta, "Cannot find vp8 encoder metadata"); mEbmlComposer->SetVideoConfig(meta->mWidth, meta->mHeight, meta->mDisplayWidth, meta->mDisplayHeight, meta->mEncodedFrameRate); mMetadataRequiredFlag = mMetadataRequiredFlag & ~ContainerWriter::CREATE_VIDEO_TRACK; } if (aMetadata->GetKind() == TrackMetadataBase::METADATA_VORBIS) { VorbisMetadata* meta = static_cast<VorbisMetadata*>(aMetadata); MOZ_ASSERT(meta, "Cannot find vorbis encoder metadata"); mEbmlComposer->SetAudioConfig(meta->mSamplingFrequency, meta->mChannels, meta->mBitDepth); mEbmlComposer->SetAudioCodecPrivateData(meta->mData); mMetadataRequiredFlag = mMetadataRequiredFlag & ~ContainerWriter::CREATE_AUDIO_TRACK; } if (!mMetadataRequiredFlag) { mEbmlComposer->GenerateHeader(); } return NS_OK; }
uint32_t nsInputStreamPump::OnStateStart() { PROFILER_LABEL("nsInputStreamPump", "OnStateStart"); LOG((" OnStateStart [this=%p]\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)) { uint64_t 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; }
NS_IMETHODIMP nsIncrementalStreamLoader::OnStopRequest(nsIRequest* request, nsISupports *ctxt, nsresult aStatus) { PROFILER_LABEL("nsIncrementalStreamLoader", "OnStopRequest", js::ProfileEntry::Category::NETWORK); if (mObserver) { // provide nsIIncrementalStreamLoader::request during call to OnStreamComplete mRequest = request; size_t length = mData.length(); uint8_t* elems = mData.extractOrCopyRawBuffer(); nsresult rv = mObserver->OnStreamComplete(this, mContext, aStatus, length, elems); if (rv != NS_SUCCESS_ADOPTED_DATA) { // The observer didn't take ownership of the extracted data buffer, so // put it back into mData. mData.replaceRawBuffer(elems, length); } // done.. cleanup ReleaseData(); mRequest = 0; mObserver = 0; mContext = 0; } return NS_OK; }
already_AddRefed<TrackMetadataBase> OmxVideoTrackEncoder::GetMetadata() { PROFILER_LABEL("OmxVideoTrackEncoder", "GetMetadata", js::ProfileEntry::Category::OTHER); { // Wait if mEncoder is not initialized nor is being canceled. ReentrantMonitorAutoEnter mon(mReentrantMonitor); while (!mCanceled && !mInitialized) { mReentrantMonitor.Wait(); } } if (mCanceled || mEncodingComplete) { return nullptr; } nsRefPtr<AVCTrackMetadata> meta = new AVCTrackMetadata(); meta->mWidth = mFrameWidth; meta->mHeight = mFrameHeight; meta->mDisplayWidth = mDisplayWidth; meta->mDisplayHeight = mDisplayHeight; meta->mFrameRate = ENCODER_CONFIG_FRAME_RATE; return meta.forget(); }
nsresult MediaEncoder::WriteEncodedDataToMuxer(TrackEncoder *aTrackEncoder) { if (aTrackEncoder == nullptr) { return NS_OK; } if (aTrackEncoder->IsEncodingComplete()) { return NS_OK; } PROFILER_LABEL("MediaEncoder", "WriteEncodedDataToMuxer", js::ProfileEntry::Category::OTHER); EncodedFrameContainer encodedVideoData; nsresult rv = aTrackEncoder->GetEncodedTrack(encodedVideoData); if (NS_FAILED(rv)) { // Encoding might be canceled. LOG(PR_LOG_ERROR, ("Error! Fail to get encoded data from video encoder.")); mState = ENCODE_ERROR; return rv; } rv = mWriter->WriteEncodedTrack(encodedVideoData, aTrackEncoder->IsEncodingComplete() ? ContainerWriter::END_OF_STREAM : 0); if (NS_FAILED(rv)) { LOG(PR_LOG_ERROR, ("Error! Fail to write encoded video track to the media container.")); mState = ENCODE_ERROR; } return rv; }
NS_IMETHODIMP PluginStreamListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt) { PROFILER_LABEL("PluginStreamListener", "OnStartRequest", js::ProfileEntry::Category::NETWORK); 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); }
void Decoder::Write(const char* aBuffer, uint32_t aCount) { PROFILER_LABEL("ImageDecoder", "Write"); // We're strict about decoder errors NS_ABORT_IF_FALSE(!HasDecoderError(), "Not allowed to make more decoder calls after error!"); // If a data error occured, just ignore future data if (HasDataError()) return; if (IsSizeDecode() && HasSize()) { // More data came in since we found the size. We have nothing to do here. return; } // Pass the data along to the implementation WriteInternal(aBuffer, aCount); // If we're a synchronous decoder and we need a new frame to proceed, let's // create one and call it again. while (mSynchronous && NeedsNewFrame() && !HasDataError()) { nsresult rv = AllocateFrame(); if (NS_SUCCEEDED(rv)) { // Tell the decoder to use the data it saved when it asked for a new frame. WriteInternal(nullptr, 0); } } }
void ClientCanvasLayer::RenderLayer() { PROFILER_LABEL("ClientCanvasLayer", "RenderLayer", js::ProfileEntry::Category::GRAPHICS); RenderMaskLayers(this); if (!mCanvasClient) { TextureFlags flags = TextureFlags::IMMEDIATE_UPLOAD; if (mOriginPos == gl::OriginPos::BottomLeft) { flags |= TextureFlags::ORIGIN_BOTTOM_LEFT; } if (!mGLContext) { // We don't support locking for buffer surfaces currently flags |= TextureFlags::IMMEDIATE_UPLOAD; } if (!mIsAlphaPremultiplied) { flags |= TextureFlags::NON_PREMULTIPLIED; } mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(), ClientManager()->AsShadowForwarder(), flags); if (!mCanvasClient) { return; } if (HasShadow()) { if (mAsyncRenderer) { static_cast<CanvasClientBridge*>(mCanvasClient.get())->SetLayer(this); } else { mCanvasClient->Connect(); ClientManager()->AsShadowForwarder()->Attach(mCanvasClient, this); } } } if (mCanvasClient && mAsyncRenderer) { mCanvasClient->UpdateAsync(mAsyncRenderer); } if (!IsDirty()) { return; } Painted(); FirePreTransactionCallback(); if (mBufferProvider && mBufferProvider->GetTextureClient()) { mCanvasClient->UpdateFromTexture(mBufferProvider->GetTextureClient()); } else { mCanvasClient->Update(gfx::IntSize(mBounds.width, mBounds.height), this); } FireDidTransactionCallback(); ClientManager()->Hold(this); mCanvasClient->Updated(); }
nsresult SVGIFrameElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, bool aCompileEventHandlers) { nsresult rv = nsSVGElement::BindToTree(aDocument, aParent, aBindingParent, aCompileEventHandlers); NS_ENSURE_SUCCESS(rv, rv); if (aDocument) { NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(), "Missing a script blocker!"); PROFILER_LABEL("SVGIFrameElement", "BindToTree", js::ProfileEntry::Category::OTHER); // We're in a document now. Kick off the frame load. LoadSrc(); if (HasAttr(kNameSpaceID_None, nsGkAtoms::sandbox)) { if (mFrameLoader) { mFrameLoader->ApplySandboxFlags(GetSandboxFlags()); } } } // We're now in document and scripts may move us, so clear // the mNetworkCreated flag. mNetworkCreated = false; return rv; }
SharedSurface* SurfaceStream_TripleBuffer::SwapProducer(SurfaceFactory* factory, const gfxIntSize& size) { PROFILER_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; }
nsresult OggWriter::SetMetadata(TrackMetadataBase* aMetadata) { MOZ_ASSERT(aMetadata); PROFILER_LABEL("OggWriter", "SetMetadata", js::ProfileEntry::Category::OTHER); if (aMetadata->GetKind() != TrackMetadataBase::METADATA_OPUS) { LOG("wrong meta data type!"); return NS_ERROR_FAILURE; } // Validate each field of METADATA mMetadata = static_cast<OpusMetadata*>(aMetadata); if (mMetadata->mIdHeader.Length() == 0) { LOG("miss mIdHeader!"); return NS_ERROR_FAILURE; } if (mMetadata->mCommentHeader.Length() == 0) { LOG("miss mCommentHeader!"); return NS_ERROR_FAILURE; } return NS_OK; }
/*static*/ already_AddRefed<gfxASurface> ShadowLayerForwarder::PlatformOpenDescriptor(OpenMode aMode, const SurfaceDescriptor& aSurface) { PROFILER_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 = aSurface.get_SurfaceDescriptorGralloc().size(); 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(); }
/*static*/ PGrallocBufferParent* GrallocBufferActor::Create(const gfxIntSize& aSize, const uint32_t& aFormat, const uint32_t& aUsage, MaybeMagicGrallocBufferHandle* aOutHandle) { PROFILER_LABEL("GrallocBufferActor", "Create"); GrallocBufferActor* actor = new GrallocBufferActor(); *aOutHandle = null_t(); uint32_t format = aFormat; uint32_t usage = aUsage; if (format == 0 || usage == 0) { printf_stderr("GrallocBufferActor::Create -- format and usage must be non-zero"); return actor; } sp<GraphicBuffer> buffer(new GraphicBuffer(aSize.width, aSize.height, format, usage)); if (buffer->initCheck() != OK) return actor; size_t bpp = BytesPerPixelForPixelFormat(format); actor->mAllocBytes = aSize.width * aSize.height * bpp; sCurrentAlloc += actor->mAllocBytes; actor->mGraphicBuffer = buffer; *aOutHandle = MagicGrallocBufferHandle(buffer); return actor; }
void nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsView* aView, nsEventStatus* aStatus) { PROFILER_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. nsView* 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) { shell->HandleEvent(frame, aEvent, false, aStatus); return; } } *aStatus = nsEventStatus_eIgnore; }
bool ISurfaceAllocator::PlatformAllocSurfaceDescriptor(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; } PROFILER_LABEL("ShadowLayerForwarder", "PlatformAllocSurfaceDescriptor"); // Gralloc buffers are efficiently mappable as gfxImageSurface, so // no need to check |aCaps & MAP_AS_IMAGE_SURFACE|. MaybeMagicGrallocBufferHandle handle; PGrallocBufferChild* gc; bool defaultRBSwap; if (aCaps & USING_GL_RENDERING_ONLY) { gc = AllocGrallocBuffer(aSize, PixelFormatForContentType(aContent), GraphicBuffer::USAGE_HW_RENDER | GraphicBuffer::USAGE_HW_TEXTURE, &handle); // If you're allocating for USING_GL_RENDERING_ONLY, then we don't flag // this for RB swap. defaultRBSwap = false; } else { gc = AllocGrallocBuffer(aSize, PixelFormatForContentType(aContent), GraphicBuffer::USAGE_SW_READ_OFTEN | GraphicBuffer::USAGE_SW_WRITE_OFTEN | GraphicBuffer::USAGE_HW_TEXTURE, &handle); // But if you're allocating for non-GL-only rendering, we flag for // RB swap to preserve old behaviour and proper interaction with // cairo. defaultRBSwap = true; } 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, defaultRBSwap); return true; }
uint32_t nsInputStreamPump::OnStateStop() { mMonitor.AssertCurrentThreadIn(); if (!NS_IsMainThread()) { // Hopefully temporary hack: OnStateStop should only run on the main // thread, but we're seeing some rare off-main-thread calls. For now // just redispatch to the main thread in release builds, and crash in // debug builds. MOZ_ASSERT(NS_IsMainThread(), "OnStateStop should only be called on the main thread."); nsresult rv = NS_DispatchToMainThread( NewRunnableMethod(this, &nsInputStreamPump::CallOnStateStop)); NS_ENSURE_SUCCESS(rv, STATE_IDLE); return STATE_IDLE; } PROFILER_LABEL("nsInputStreamPump", "OnStateStop", js::ProfileEntry::Category::NETWORK); LOG((" OnStateStop [this=%p 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 (!mAsyncStream || !mListener) { MOZ_ASSERT(mAsyncStream, "null mAsyncStream: OnStateStop called twice?"); MOZ_ASSERT(mListener, "null mListener: OnStateStop called twice?"); return STATE_IDLE; } if (NS_FAILED(mStatus)) mAsyncStream->CloseWithStatus(mStatus); else if (mCloseWhenDone) mAsyncStream->Close(); mAsyncStream = 0; mTargetThread = 0; mIsPending = false; { // Note: Must exit monitor for call to OnStartRequest to avoid // deadlocks when calls to RetargetDeliveryTo for multiple // nsInputStreamPumps are needed (e.g. nsHttpChannel). mMonitor.Exit(); mListener->OnStopRequest(this, mListenerContext, mStatus); mMonitor.Enter(); } mListener = 0; mListenerContext = 0; if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus); return STATE_IDLE; }
void ClientThebesLayer::PaintThebes() { PROFILER_LABEL("ClientThebesLayer", "PaintThebes"); NS_ASSERTION(ClientManager()->InDrawing(), "Can only draw in drawing phase"); //TODO: This is going to copy back pixels that we might end up // drawing over anyway. It would be nice if we could avoid // this duplication. mContentClient->SyncFrontBufferToBackBuffer(); bool canUseOpaqueSurface = CanUseOpaqueSurface(); ContentType contentType = canUseOpaqueSurface ? GFX_CONTENT_COLOR : GFX_CONTENT_COLOR_ALPHA; { uint32_t flags = 0; #ifndef MOZ_WIDGET_ANDROID if (ClientManager()->CompositorMightResample()) { flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE; } if (!(flags & ThebesLayerBuffer::PAINT_WILL_RESAMPLE)) { if (MayResample()) { flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE; } } #endif PaintState state = mContentClient->BeginPaintBuffer(this, contentType, flags); mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate); if (state.mContext) { // The area that became invalid and is visible needs to be repainted // (this could be the whole visible area if our buffer switched // from RGB to RGBA, because we might need to repaint with // subpixel AA) state.mRegionToInvalidate.And(state.mRegionToInvalidate, GetEffectiveVisibleRegion()); nsIntRegion extendedDrawRegion = state.mRegionToDraw; SetAntialiasingFlags(this, state.mContext); PaintBuffer(state.mContext, state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate, state.mDidSelfCopy, state.mClip); MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this)); Mutated(); } else { // It's possible that state.mRegionToInvalidate is nonempty here, // if we are shrinking the valid region to nothing. So use mRegionToDraw // instead. NS_WARN_IF_FALSE(state.mRegionToDraw.IsEmpty(), "No context when we have something to draw, resource exhaustion?"); } } }
bool ClientLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback, void* aCallbackData, EndTransactionFlags) { PROFILER_LABEL("ClientLayerManager", "EndTransactionInternal", js::ProfileEntry::Category::GRAPHICS); #ifdef MOZ_LAYERS_HAVE_LOG MOZ_LAYERS_LOG((" ----- (beginning paint)")); Log(); #endif profiler_tracing("Paint", "Rasterize", TRACING_INTERVAL_START); NS_ASSERTION(InConstruction(), "Should be in construction phase"); mPhase = PHASE_DRAWING; ClientLayer* root = ClientLayer::ToClientLayer(GetRoot()); mTransactionIncomplete = false; // Apply pending tree updates before recomputing effective // properties. GetRoot()->ApplyPendingUpdatesToSubtree(); mPaintedLayerCallback = aCallback; mPaintedLayerCallbackData = aCallbackData; GetRoot()->ComputeEffectiveTransforms(Matrix4x4()); root->RenderLayer(); if (!mRepeatTransaction && !GetRoot()->GetInvalidRegion().IsEmpty()) { GetRoot()->Mutated(); } if (!mIsRepeatTransaction) { mAnimationReadyTime = TimeStamp::Now(); GetRoot()->StartPendingAnimations(mAnimationReadyTime); } mPaintedLayerCallback = nullptr; mPaintedLayerCallbackData = nullptr; // Go back to the construction phase if the transaction isn't complete. // Layout will update the layer tree and call EndTransaction(). mPhase = mTransactionIncomplete ? PHASE_CONSTRUCTION : PHASE_NONE; NS_ASSERTION(!aCallback || !mTransactionIncomplete, "If callback is not null, transaction must be complete"); if (gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) { FrameLayerBuilder::InvalidateAllLayers(this); } return !mTransactionIncomplete; }
void ThebesLayerComposite::RenderLayer(const nsIntRect& aClipRect) { if (!mBuffer || !mBuffer->IsAttached()) { return; } PROFILER_LABEL("ThebesLayerComposite", "RenderLayer", js::ProfileEntry::Category::GRAPHICS); MOZ_ASSERT(mBuffer->GetCompositor() == mCompositeManager->GetCompositor() && mBuffer->GetLayer() == this, "buffer is corrupted"); gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height); #ifdef MOZ_DUMP_PAINTING if (gfxUtils::sDumpPainting) { RefPtr<gfx::DataSourceSurface> surf = mBuffer->GetAsSurface(); if (surf) { WriteSnapshotToDumpFile(this, surf); } } #endif EffectChain effectChain(this); LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(mMaskLayer, effectChain); AddBlendModeEffect(effectChain); const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion(); TiledLayerProperties tiledLayerProps; if (mRequiresTiledProperties) { tiledLayerProps.mVisibleRegion = visibleRegion; tiledLayerProps.mEffectiveResolution = GetEffectiveResolution(); tiledLayerProps.mValidRegion = mValidRegion; } mBuffer->SetPaintWillResample(MayResample()); mBuffer->Composite(effectChain, GetEffectiveOpacity(), GetEffectiveTransform(), gfx::Filter::LINEAR, clipRect, &visibleRegion, mRequiresTiledProperties ? &tiledLayerProps : nullptr); mBuffer->BumpFlashCounter(); if (mRequiresTiledProperties) { mValidRegion = tiledLayerProps.mValidRegion; } mCompositeManager->GetCompositor()->MakeCurrent(); }
void Decoder::Write(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy) { PROFILER_LABEL("ImageDecoder", "Write", js::ProfileEntry::Category::GRAPHICS); MOZ_ASSERT(NS_IsMainThread() || aStrategy == DecodeStrategy::ASYNC); // We're strict about decoder errors MOZ_ASSERT(!HasDecoderError(), "Not allowed to make more decoder calls after error!"); // Begin recording telemetry data. TimeStamp start = TimeStamp::Now(); mChunkCount++; // Keep track of the total number of bytes written. mBytesDecoded += aCount; // If we're flushing data, clear the flag. if (aBuffer == nullptr && aCount == 0) { MOZ_ASSERT(mNeedsToFlushData, "Flushing when we don't need to"); mNeedsToFlushData = false; } // If a data error occured, just ignore future data. if (HasDataError()) return; if (IsSizeDecode() && HasSize()) { // More data came in since we found the size. We have nothing to do here. return; } // Pass the data along to the implementation WriteInternal(aBuffer, aCount, aStrategy); // If we're a synchronous decoder and we need a new frame to proceed, let's // create one and call it again. if (aStrategy == DecodeStrategy::SYNC) { while (NeedsNewFrame() && !HasDataError()) { nsresult rv = AllocateFrame(); if (NS_SUCCEEDED(rv)) { // Use the data we saved when we asked for a new frame. WriteInternal(nullptr, 0, aStrategy); } mNeedsToFlushData = false; } } // Finish telemetry. mDecodeTime += (TimeStamp::Now() - start); }
bool SurfaceStream_TripleBuffer_Async::WaitForCompositor() { PROFILER_LABEL("SurfaceStream_TripleBuffer_Async", "WaitForCompositor"); // We are assumed to be locked while (mStaging) mMonitor.Wait(); return true; }
void CompositorParent::ForceComposeToTarget(DrawTarget* aTarget, const nsIntRect* aRect) { PROFILER_LABEL("CompositorParent", "ForceComposeToTarget", js::ProfileEntry::Category::GRAPHICS); AutoRestore<bool> override(mOverrideComposeReadiness); mOverrideComposeReadiness = true; CompositeToTarget(aTarget, aRect); }
void ClientCanvasLayer::RenderLayer() { PROFILER_LABEL("ClientCanvasLayer", "RenderLayer", js::ProfileEntry::Category::GRAPHICS); if (GetMaskLayer()) { ToClientLayer(GetMaskLayer())->RenderLayer(); } if (!IsDirty()) { return; } if (!mCanvasClient) { TextureFlags flags = TextureFlags::IMMEDIATE_UPLOAD; if (mNeedsYFlip) { flags |= TextureFlags::NEEDS_Y_FLIP; } if (!mGLContext) { // We don't support locking for buffer surfaces currently flags |= TextureFlags::IMMEDIATE_UPLOAD; } else { // GLContext's SurfaceStream handles ownership itself, // and doesn't require layers to do any deallocation. flags |= TextureFlags::DEALLOCATE_CLIENT; } if (!mIsAlphaPremultiplied) { flags |= TextureFlags::NON_PREMULTIPLIED; } mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(), ClientManager()->AsShadowForwarder(), flags); if (!mCanvasClient) { return; } if (HasShadow()) { mCanvasClient->Connect(); ClientManager()->AsShadowForwarder()->Attach(mCanvasClient, this); } } FirePreTransactionCallback(); mCanvasClient->Update(gfx::IntSize(mBounds.width, mBounds.height), this); FireDidTransactionCallback(); ClientManager()->Hold(this); mCanvasClient->Updated(); mCanvasClient->OnTransaction(); }
nsresult WebMWriter::WriteEncodedTrack(const EncodedFrameContainer& aData, uint32_t aFlags) { PROFILER_LABEL("WebMWriter", "SetMetadata", js::ProfileEntry::Category::OTHER); for (uint32_t i = 0 ; i < aData.GetEncodedFrames().Length(); i++) { mEbmlComposer->WriteSimpleBlock(aData.GetEncodedFrames().ElementAt(i).get()); } return NS_OK; }
/*static*/ already_AddRefed<TextureImage> LayerManagerComposite::OpenDescriptorForDirectTexturing(GLContext* aGL, const SurfaceDescriptor& aDescriptor, GLenum aWrapMode) { PROFILER_LABEL("LayerManagerComposite", "OpenDescriptorForDirectTexturing"); if (SurfaceDescriptor::TSurfaceDescriptorGralloc != aDescriptor.type()) { return nullptr; } sp<GraphicBuffer> buffer = GrallocBufferActor::GetFrom(aDescriptor); return aGL->CreateDirectTextureImage(buffer.get(), aWrapMode); }
nsresult MediaEncoder::WriteEncodedDataToMuxer(TrackEncoder *aTrackEncoder) { if (aTrackEncoder == nullptr) { return NS_OK; } if (aTrackEncoder->IsEncodingComplete()) { return NS_OK; } PROFILER_LABEL("MediaEncoder", "WriteEncodedDataToMuxer", js::ProfileEntry::Category::OTHER); EncodedFrameContainer encodedVideoData; nsresult rv = aTrackEncoder->GetEncodedTrack(encodedVideoData); if (NS_FAILED(rv)) { // Encoding might be canceled. LOG(LogLevel::Error, ("Error! Fail to get encoded data from video encoder.")); mState = ENCODE_ERROR; return rv; } // Update timestamps to accommodate pauses const nsTArray<RefPtr<EncodedFrame> >& encodedFrames = encodedVideoData.GetEncodedFrames(); // Take a copy of the atomic so we don't continually access it uint64_t microsecondsSpentPaused = mMicrosecondsSpentPaused; for (size_t i = 0; i < encodedFrames.Length(); ++i) { RefPtr<EncodedFrame> frame = encodedFrames[i]; if (frame->GetTimeStamp() > microsecondsSpentPaused && frame->GetTimeStamp() - microsecondsSpentPaused > mLastMuxedTimestamp) { // Use the adjusted timestamp if it's after the last timestamp frame->SetTimeStamp(frame->GetTimeStamp() - microsecondsSpentPaused); } else { // If not, we force the last time stamp. We do this so the frames are // still around and in order in case the codec needs to reference them. // Dropping them here may result in artifacts in playback. frame->SetTimeStamp(mLastMuxedTimestamp); } MOZ_ASSERT(mLastMuxedTimestamp <= frame->GetTimeStamp(), "Our frames should be ordered by this point!"); mLastMuxedTimestamp = frame->GetTimeStamp(); } rv = mWriter->WriteEncodedTrack(encodedVideoData, aTrackEncoder->IsEncodingComplete() ? ContainerWriter::END_OF_STREAM : 0); if (NS_FAILED(rv)) { LOG(LogLevel::Error, ("Error! Fail to write encoded video track to the media container.")); mState = ENCODE_ERROR; } return rv; }
nsresult WebMWriter::GetContainerData(nsTArray<nsTArray<uint8_t> >* aOutputBufs, uint32_t aFlags) { PROFILER_LABEL("WebMWriter", "GetContainerData", js::ProfileEntry::Category::OTHER); mEbmlComposer->ExtractBuffer(aOutputBufs, aFlags); if (aFlags & ContainerWriter::FLUSH_NEEDED) { mIsWritingComplete = true; } return NS_OK; }
void ClientThebesLayer::PaintThebes() { PROFILER_LABEL("ClientThebesLayer", "PaintThebes"); NS_ASSERTION(ClientManager()->InDrawing(), "Can only draw in drawing phase"); { mContentClient->PrepareFrame(); uint32_t flags = 0; #ifndef MOZ_WIDGET_ANDROID if (ClientManager()->CompositorMightResample()) { flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE; } if (!(flags & RotatedContentBuffer::PAINT_WILL_RESAMPLE)) { if (MayResample()) { flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE; } } #endif PaintState state = mContentClient->BeginPaintBuffer(this, flags); mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate); if (DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(this, state)) { // The area that became invalid and is visible needs to be repainted // (this could be the whole visible area if our buffer switched // from RGB to RGBA, because we might need to repaint with // subpixel AA) state.mRegionToInvalidate.And(state.mRegionToInvalidate, GetEffectiveVisibleRegion()); SetAntialiasingFlags(this, target); nsRefPtr<gfxContext> ctx = gfxContext::ContextForDrawTarget(target); PaintBuffer(ctx, state.mRegionToDraw, state.mRegionToDraw, state.mRegionToInvalidate, state.mDidSelfCopy, state.mClip); MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this)); Mutated(); ctx = nullptr; mContentClient->ReturnDrawTargetToBuffer(target); } else { // It's possible that state.mRegionToInvalidate is nonempty here, // if we are shrinking the valid region to nothing. So use mRegionToDraw // instead. NS_WARN_IF_FALSE(state.mRegionToDraw.IsEmpty(), "No context when we have something to draw, resource exhaustion?"); } } }
/*static*/ bool ShadowLayerForwarder::PlatformCloseDescriptor(const SurfaceDescriptor& aDescriptor) { PROFILER_LABEL("ShadowLayerForwarder", "PlatformCloseDescriptor"); if (SurfaceDescriptor::TSurfaceDescriptorGralloc != aDescriptor.type()) { return false; } sp<GraphicBuffer> buffer = GrallocBufferActor::GetFrom(aDescriptor); DebugOnly<status_t> status = buffer->unlock(); // If we fail to unlock, we'll subsequently fail to lock and end up aborting anyway. MOZ_ASSERT(status == OK); return true; }