gfx/gl/GLTextureImage.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef GLTEXTUREIMAGE_H_
     7 #define GLTEXTUREIMAGE_H_
     9 #include "nsAutoPtr.h"
    10 #include "nsRegion.h"
    11 #include "nsTArray.h"
    12 #include "gfxTypes.h"
    13 #include "GLContextTypes.h"
    14 #include "GraphicsFilter.h"
    15 #include "mozilla/gfx/Rect.h"
    16 #include "mozilla/RefPtr.h"
    18 class gfxASurface;
    20 namespace mozilla {
    21 namespace gfx {
    22 class DataSourceSurface;
    23 class DrawTarget;
    24 }
    25 }
    27 namespace mozilla {
    28 namespace gl {
    29 class GLContext;
    31 /**
    32  * A TextureImage encapsulates a surface that can be drawn to by a
    33  * Thebes gfxContext and (hopefully efficiently!) synchronized to a
    34  * texture in the server.  TextureImages are associated with one and
    35  * only one GLContext.
    36  *
    37  * Implementation note: TextureImages attempt to unify two categories
    38  * of backends
    39  *
    40  *  (1) proxy to server-side object that can be bound to a texture;
    41  *      e.g. Pixmap on X11.
    42  *
    43  *  (2) efficient manager of texture memory; e.g. by having clients draw
    44  *      into a scratch buffer which is then uploaded with
    45  *      glTexSubImage2D().
    46  */
    47 class TextureImage
    48 {
    49     NS_INLINE_DECL_REFCOUNTING(TextureImage)
    50 public:
    51     enum TextureState
    52     {
    53       Created, // Texture created, but has not had glTexImage called to initialize it.
    54       Allocated,  // Texture memory exists, but contents are invalid.
    55       Valid  // Texture fully ready to use.
    56     };
    58     enum Flags {
    59         NoFlags          = 0x0,
    60         UseNearestFilter = 0x1,
    61         NeedsYFlip       = 0x2,
    62         DisallowBigImage = 0x4
    63     };
    65     typedef gfxContentType ContentType;
    66     typedef gfxImageFormat ImageFormat;
    68     static already_AddRefed<TextureImage> Create(
    69                        GLContext* gl,
    70                        const nsIntSize& aSize,
    71                        TextureImage::ContentType aContentType,
    72                        GLenum aWrapMode,
    73                        TextureImage::Flags aFlags = TextureImage::NoFlags);
    74     // Moz2D equivalent...
    75     static already_AddRefed<TextureImage> Create(
    76                        GLContext* gl,
    77                        const gfx::IntSize& aSize,
    78                        TextureImage::ContentType aContentType,
    79                        GLenum aWrapMode,
    80                        TextureImage::Flags aFlags = TextureImage::NoFlags);
    82     /**
    83      * Returns a gfxASurface for updating |aRegion| of the client's
    84      * image if successul, nullptr if not.  |aRegion|'s bounds must fit
    85      * within Size(); its coordinate space (if any) is ignored.  If
    86      * the update begins successfully, the returned gfxASurface is
    87      * owned by this.  Otherwise, nullptr is returned.
    88      *
    89      * |aRegion| is an inout param: the returned region is what the
    90      * client must repaint.  Category (1) regions above can
    91      * efficiently handle repaints to "scattered" regions, while (2)
    92      * can only efficiently handle repaints to rects.
    93      *
    94      * Painting the returned surface outside of |aRegion| results
    95      * in undefined behavior.
    96      *
    97      * BeginUpdate() calls cannot be "nested", and each successful
    98      * BeginUpdate() must be followed by exactly one EndUpdate() (see
    99      * below).  Failure to do so can leave this in a possibly
   100      * inconsistent state.  Unsuccessful BeginUpdate()s must not be
   101      * followed by EndUpdate().
   102      */
   103     virtual gfx::DrawTarget* BeginUpdate(nsIntRegion& aRegion) = 0;
   104     /**
   105      * Retrieves the region that will require updating, given a
   106      * region that needs to be updated. This can be used for
   107      * making decisions about updating before calling BeginUpdate().
   108      *
   109      * |aRegion| is an inout param.
   110      */
   111     virtual void GetUpdateRegion(nsIntRegion& aForRegion) {
   112     }
   113     /**
   114      * Finish the active update and synchronize with the server, if
   115      * necessary.
   116      *
   117      * BeginUpdate() must have been called exactly once before
   118      * EndUpdate().
   119      */
   120     virtual void EndUpdate() = 0;
   122     /**
   123      * The Image may contain several textures for different regions (tiles).
   124      * These functions iterate over each sub texture image tile.
   125      */
   126     virtual void BeginTileIteration() {
   127     }
   129     virtual bool NextTile() {
   130         return false;
   131     }
   133     // Function prototype for a tile iteration callback. Returning false will
   134     // cause iteration to be interrupted (i.e. the corresponding NextTile call
   135     // will return false).
   136     typedef bool (* TileIterationCallback)(TextureImage* aImage,
   137                                            int aTileNumber,
   138                                            void* aCallbackData);
   140     // Sets a callback to be called every time NextTile is called.
   141     virtual void SetIterationCallback(TileIterationCallback aCallback,
   142                                       void* aCallbackData) {
   143     }
   145     virtual gfx::IntRect GetTileRect();
   147     virtual GLuint GetTextureID() = 0;
   149     virtual uint32_t GetTileCount() {
   150         return 1;
   151     }
   153     /**
   154      * Set this TextureImage's size, and ensure a texture has been
   155      * allocated.  Must not be called between BeginUpdate and EndUpdate.
   156      * After a resize, the contents are undefined.
   157      *
   158      * If this isn't implemented by a subclass, it will just perform
   159      * a dummy BeginUpdate/EndUpdate pair.
   160      */
   161     virtual void Resize(const gfx::IntSize& aSize) {
   162         mSize = aSize;
   163         nsIntRegion r(nsIntRect(0, 0, aSize.width, aSize.height));
   164         BeginUpdate(r);
   165         EndUpdate();
   166     }
   168     /**
   169      * Mark this texture as having valid contents. Call this after modifying
   170      * the texture contents externally.
   171      */
   172     virtual void MarkValid() {}
   174     /**
   175      * aSurf - the source surface to update from
   176      * aRegion - the region in this image to update
   177      * aFrom - offset in the source to update from
   178      */
   179     virtual bool DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom = gfx::IntPoint(0,0)) = 0;
   180     bool UpdateFromDataSource(gfx::DataSourceSurface *aSurf,
   181                               const nsIntRegion* aDstRegion = nullptr,
   182                               const gfx::IntPoint* aSrcOffset = nullptr);
   184     virtual void BindTexture(GLenum aTextureUnit) = 0;
   186     /**
   187      * Returns the image format of the texture. Only valid after a matching
   188      * BeginUpdate/EndUpdate pair have been called.
   189      */
   190     virtual gfx::SurfaceFormat GetTextureFormat() {
   191         return mTextureFormat;
   192     }
   194     /** Can be called safely at any time. */
   196     /**
   197      * If this TextureImage has a permanent gfxASurface backing,
   198      * return it.  Otherwise return nullptr.
   199      */
   200     virtual already_AddRefed<gfxASurface> GetBackingSurface()
   201     { return nullptr; }
   204     gfx::IntSize GetSize() const;
   205     ContentType GetContentType() const { return mContentType; }
   206     ImageFormat GetImageFormat() const { return mImageFormat; }
   207     virtual bool InUpdate() const = 0;
   208     GLenum GetWrapMode() const { return mWrapMode; }
   210     void SetFilter(GraphicsFilter aFilter) { mFilter = aFilter; }
   212 protected:
   213     friend class GLContext;
   215     /**
   216      * After the ctor, the TextureImage is invalid.  Implementations
   217      * must allocate resources successfully before returning the new
   218      * TextureImage from GLContext::CreateTextureImage().  That is,
   219      * clients must not be given partially-constructed TextureImages.
   220      */
   221     TextureImage(const nsIntSize& aSize,
   222                  GLenum aWrapMode, ContentType aContentType,
   223                  Flags aFlags = NoFlags,
   224                  ImageFormat aImageFormat = gfxImageFormat::Unknown)
   225         : mSize(aSize.ToIntSize())
   226         , mWrapMode(aWrapMode)
   227         , mContentType(aContentType)
   228         , mImageFormat(aImageFormat)
   229         , mFilter(GraphicsFilter::FILTER_GOOD)
   230         , mFlags(aFlags)
   231     {}
   233     // Moz2D equivalent...
   234     TextureImage(const gfx::IntSize& aSize,
   235                  GLenum aWrapMode, ContentType aContentType,
   236                  Flags aFlags = NoFlags);
   238     // Protected destructor, to discourage deletion outside of Release():
   239     virtual ~TextureImage() {}
   241     virtual gfx::IntRect GetSrcTileRect();
   243     gfx::IntSize mSize;
   244     GLenum mWrapMode;
   245     ContentType mContentType;
   246     ImageFormat mImageFormat;
   247     gfx::SurfaceFormat mTextureFormat;
   248     GraphicsFilter mFilter;
   249     Flags mFlags;
   250 };
   252 /**
   253  * BasicTextureImage is the baseline TextureImage implementation ---
   254  * it updates its texture by allocating a scratch buffer for the
   255  * client to draw into, then using glTexSubImage2D() to upload the new
   256  * pixels.  Platforms must provide the code to create a new surface
   257  * into which the updated pixels will be drawn, and the code to
   258  * convert the update surface's pixels into an image on which we can
   259  * glTexSubImage2D().
   260  */
   261 class BasicTextureImage
   262     : public TextureImage
   263 {
   264 public:
   265     virtual ~BasicTextureImage();
   267     BasicTextureImage(GLuint aTexture,
   268                       const nsIntSize& aSize,
   269                       GLenum aWrapMode,
   270                       ContentType aContentType,
   271                       GLContext* aContext,
   272                       TextureImage::Flags aFlags = TextureImage::NoFlags,
   273                       TextureImage::ImageFormat aImageFormat = gfxImageFormat::Unknown);
   274     BasicTextureImage(GLuint aTexture,
   275                       const gfx::IntSize& aSize,
   276                       GLenum aWrapMode,
   277                       ContentType aContentType,
   278                       GLContext* aContext,
   279                       TextureImage::Flags aFlags = TextureImage::NoFlags,
   280                       TextureImage::ImageFormat aImageFormat = gfxImageFormat::Unknown);
   282     virtual void BindTexture(GLenum aTextureUnit);
   284     virtual gfx::DrawTarget* BeginUpdate(nsIntRegion& aRegion);
   285     virtual void GetUpdateRegion(nsIntRegion& aForRegion);
   286     virtual void EndUpdate();
   287     virtual bool DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom = gfx::IntPoint(0,0));
   288     virtual GLuint GetTextureID() { return mTexture; }
   289     virtual TemporaryRef<gfx::DrawTarget>
   290       GetDrawTargetForUpdate(const gfx::IntSize& aSize, gfx::SurfaceFormat aFmt);
   292     virtual void MarkValid() { mTextureState = Valid; }
   294     // Call when drawing into the update surface is complete.
   295     // Returns true if textures should be upload with a relative
   296     // offset - See UploadSurfaceToTexture.
   297     virtual bool FinishedSurfaceUpdate();
   299     // Call after surface data has been uploaded to a texture.
   300     virtual void FinishedSurfaceUpload();
   302     virtual bool InUpdate() const { return !!mUpdateDrawTarget; }
   304     virtual void Resize(const gfx::IntSize& aSize);
   306 protected:
   307     GLuint mTexture;
   308     TextureState mTextureState;
   309     nsRefPtr<GLContext> mGLContext;
   310     RefPtr<gfx::DrawTarget> mUpdateDrawTarget;
   311     nsIntRegion mUpdateRegion;
   313     // The offset into the update surface at which the update rect is located.
   314     nsIntPoint mUpdateOffset;
   315 };
   317 /**
   318  * A container class that complements many sub TextureImages into a big TextureImage.
   319  * Aims to behave just like the real thing.
   320  */
   322 class TiledTextureImage
   323     : public TextureImage
   324 {
   325 public:
   326     TiledTextureImage(GLContext* aGL,
   327                       gfx::IntSize aSize,
   328                       TextureImage::ContentType,
   329                       TextureImage::Flags aFlags = TextureImage::NoFlags,
   330                       TextureImage::ImageFormat aImageFormat = gfxImageFormat::Unknown);
   331     ~TiledTextureImage();
   332     void DumpDiv();
   333     virtual gfx::DrawTarget* BeginUpdate(nsIntRegion& aRegion);
   334     virtual void GetUpdateRegion(nsIntRegion& aForRegion);
   335     virtual void EndUpdate();
   336     virtual void Resize(const gfx::IntSize& aSize);
   337     virtual uint32_t GetTileCount();
   338     virtual void BeginTileIteration();
   339     virtual bool NextTile();
   340     virtual void SetIterationCallback(TileIterationCallback aCallback,
   341                                       void* aCallbackData);
   342     virtual gfx::IntRect GetTileRect();
   343     virtual GLuint GetTextureID() {
   344         return mImages[mCurrentImage]->GetTextureID();
   345     }
   346     virtual bool DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom = gfx::IntPoint(0,0));
   347     virtual bool InUpdate() const { return mInUpdate; }
   348     virtual void BindTexture(GLenum);
   350 protected:
   351     virtual gfx::IntRect GetSrcTileRect();
   353     unsigned int mCurrentImage;
   354     TileIterationCallback mIterationCallback;
   355     void* mIterationCallbackData;
   356     nsTArray< nsRefPtr<TextureImage> > mImages;
   357     bool mInUpdate;
   358     gfx::IntSize mSize;
   359     unsigned int mTileSize;
   360     unsigned int mRows, mColumns;
   361     GLContext* mGL;
   362     // A temporary draw target to faciliate cross-tile updates.
   363     RefPtr<gfx::DrawTarget> mUpdateDrawTarget;
   364     // The region of update requested
   365     nsIntRegion mUpdateRegion;
   366     TextureState mTextureState;
   367     TextureImage::ImageFormat mImageFormat;
   368 };
   370 /**
   371  * Creates a TextureImage of the basic implementation, can be useful in cases
   372  * where we know we don't want to use platform-specific TextureImage.
   373  * In doubt, use GLContext::CreateTextureImage instead.
   374  */
   375 already_AddRefed<TextureImage>
   376 CreateBasicTextureImage(GLContext* aGL,
   377                         const gfx::IntSize& aSize,
   378                         TextureImage::ContentType aContentType,
   379                         GLenum aWrapMode,
   380                         TextureImage::Flags aFlags,
   381                         TextureImage::ImageFormat aImageFormat = gfxImageFormat::Unknown);
   383 /**
   384   * Return a valid, allocated TextureImage of |aSize| with
   385   * |aContentType|.  If |aContentType| is COLOR, |aImageFormat| can be used
   386   * to hint at the preferred RGB format, however it is not necessarily
   387   * respected.  The TextureImage's texture is configured to use
   388   * |aWrapMode| (usually GL_CLAMP_TO_EDGE or GL_REPEAT) and by
   389   * default, GL_LINEAR filtering.  Specify
   390   * |aFlags=UseNearestFilter| for GL_NEAREST filtering. Specify
   391   * |aFlags=NeedsYFlip| if the image is flipped. Return
   392   * nullptr if creating the TextureImage fails.
   393   *
   394   * The returned TextureImage may only be used with this GLContext.
   395   * Attempting to use the returned TextureImage after this
   396   * GLContext is destroyed will result in undefined (and likely
   397   * crashy) behavior.
   398   */
   399 already_AddRefed<TextureImage>
   400 CreateTextureImage(GLContext* gl,
   401                    const gfx::IntSize& aSize,
   402                    TextureImage::ContentType aContentType,
   403                    GLenum aWrapMode,
   404                    TextureImage::Flags aFlags = TextureImage::NoFlags,
   405                    TextureImage::ImageFormat aImageFormat = gfxImageFormat::Unknown);
   407 } // namespace gl
   408 } // namespace mozilla
   410 #endif /* GLTEXTUREIMAGE_H_ */

mercurial