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;
}
Beispiel #2
0
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();
}
Beispiel #6
0
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);
}
Beispiel #8
0
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;
}
Beispiel #12
0
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;
}
Beispiel #15
0
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();
}
Beispiel #21
0
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;
}
Beispiel #23
0
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);
}
Beispiel #24
0
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();
}
Beispiel #25
0
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);
}
Beispiel #27
0
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;
}
Beispiel #28
0
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;
}