author Carsten "Tomcat" Book <>
Fri, 29 Apr 2016 14:21:16 +0200
changeset 295420 9979c96310a07ada1d91c166027c0829bea264d2
parent 286873 953741f757abdb9b12719aba565d82209a46ab7b
child 301406 232a786cf87fb0f68f9bda6e9316515524d2ac8a
permissions -rw-r--r--
Backed out changeset 85ce8cb0639a (bug 1268313)

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at */


#include "LayersTypes.h"
#include "mozilla/gfx/Point.h"          // for IntSize
#include "mozilla/Mutex.h"
#include "mozilla/RefPtr.h"             // for nsAutoPtr, nsRefPtr, etc
#include "nsCOMPtr.h"                   // for nsCOMPtr

class nsICanvasRenderingContextInternal;
class nsIInputStream;
class nsIThread;

namespace mozilla {

namespace gfx {
class DataSourceSurface;

namespace gl {
class GLContext;

namespace dom {
class HTMLCanvasElement;

namespace layers {

class CanvasClient;
class TextureClient;

 * Since HTMLCanvasElement and OffscreenCanvas are not thread-safe, we create
 * AsyncCanvasRenderer which is thread-safe wrapper object for communicating
 * among main, worker and ImageBridgeChild threads.
 * Each HTMLCanvasElement object is responsible for creating
 * AsyncCanvasRenderer object. Once Canvas is transfered to worker,
 * OffscreenCanvas will keep reference pointer of this object.
 * Sometimes main thread needs AsyncCanvasRenderer's result, such as layers
 * fallback to BasicLayerManager or calling toDataURL in Javascript. Simply call
 * GetSurface() in main thread will readback the result to mSurface.
 * If layers backend is LAYERS_CLIENT, this object will pass to ImageBridgeChild
 * for submitting frames to Compositor.
class AsyncCanvasRenderer final


  void NotifyElementAboutAttributesChanged();
  void NotifyElementAboutInvalidation();

  void SetCanvasClient(CanvasClient* aClient);

  void SetWidth(uint32_t aWidth)
    mWidth = aWidth;

  void SetHeight(uint32_t aHeight)
    mHeight = aHeight;

  void SetIsAlphaPremultiplied(bool aIsAlphaPremultiplied)
    mIsAlphaPremultiplied = aIsAlphaPremultiplied;

  // Active thread means the thread which spawns GLContext.
  void SetActiveThread();
  void ResetActiveThread();

  // This will readback surface and return the surface
  // in the DataSourceSurface.
  // Can be called in main thread only.
  already_AddRefed<gfx::DataSourceSurface> GetSurface();

  // For SharedSurface_Basic case, before the frame sending to the compositor,
  // we readback it to a texture client because SharedSurface_Basic cannot shared.
  // We don't want to readback it again here, so just copy the content of that
  // texture client here to avoid readback again.
  void CopyFromTextureClient(TextureClient *aClient);

  // Readback current WebGL's content and convert it to InputStream. This
  // function called GetSurface implicitly and GetSurface handles only get
  // called in the main thread. So this function can be called in main thread.
  GetInputStream(const char *aMimeType,
                 const char16_t *aEncoderOptions,
                 nsIInputStream **aStream);

  gfx::IntSize GetSize() const
    return gfx::IntSize(mWidth, mHeight);

  uint64_t GetCanvasClientAsyncID() const
    return mCanvasClientAsyncID;

  CanvasClient* GetCanvasClient() const
    return mCanvasClient;

  already_AddRefed<nsIThread> GetActiveThread();

  // The lifetime is controllered by HTMLCanvasElement.
  // Only accessed in main thread.
  dom::HTMLCanvasElement* mHTMLCanvasElement;

  // Only accessed in active thread.
  nsICanvasRenderingContextInternal* mContext;

  // We need to keep a reference to the context around here, otherwise the
  // canvas' surface texture destructor will deref and destroy it too early
  // Only accessed in active thread.
  RefPtr<gl::GLContext> mGLContext;

  virtual ~AsyncCanvasRenderer();

  // Readback current WebGL's content and return it as DataSourceSurface.
  already_AddRefed<gfx::DataSourceSurface> UpdateTarget();

  bool mIsAlphaPremultiplied;

  uint32_t mWidth;
  uint32_t mHeight;
  uint64_t mCanvasClientAsyncID;

  // The lifetime of this pointer is controlled by OffscreenCanvas
  // Can be accessed in active thread and ImageBridge thread.
  // But we never accessed it at the same time on both thread. So no
  // need to protect this member.
  CanvasClient* mCanvasClient;

  // When backend is LAYER_BASIC and SharedSurface type is Basic.
  // CanvasClient will readback the GLContext to a TextureClient
  // in order to send frame to compositor. To avoid readback again,
  // we copy from this TextureClient to this mSurfaceForBasic directly
  // by calling CopyFromTextureClient().
  RefPtr<gfx::DataSourceSurface> mSurfaceForBasic;

  // Protect non thread-safe objects.
  Mutex mMutex;

  // Can be accessed in any thread, need protect by mutex.
  nsCOMPtr<nsIThread> mActiveThread;

} // namespace layers
} // namespace mozilla