Bug 1032573 part 4 - Add AnimationTimeline::ToTimelineTime helper method; r=dbaron
[gecko.git] / gfx / gl / GLTextureImage.h
bloba8420ee4b07cb1e4c433f53813767dfba4003dec
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;
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.
37 * Implementation note: TextureImages attempt to unify two categories
38 * of backends
40 * (1) proxy to server-side object that can be bound to a texture;
41 * e.g. Pixmap on X11.
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().
47 class TextureImage
49 NS_INLINE_DECL_REFCOUNTING(TextureImage)
50 public:
51 enum TextureState
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.
58 enum Flags {
59 NoFlags = 0x0,
60 UseNearestFilter = 0x1,
61 NeedsYFlip = 0x2,
62 DisallowBigImage = 0x4
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.
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.
94 * Painting the returned surface outside of |aRegion| results
95 * in undefined behavior.
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().
103 virtual gfx::DrawTarget* BeginUpdate(nsIntRegion& aRegion) = 0;
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().
109 * |aRegion| is an inout param.
111 virtual void GetUpdateRegion(nsIntRegion& aForRegion) {
114 * Finish the active update and synchronize with the server, if
115 * necessary.
117 * BeginUpdate() must have been called exactly once before
118 * EndUpdate().
120 virtual void EndUpdate() = 0;
123 * The Image may contain several textures for different regions (tiles).
124 * These functions iterate over each sub texture image tile.
126 virtual void BeginBigImageIteration() {
129 virtual bool NextTile() {
130 return false;
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 (* BigImageIterationCallback)(TextureImage* aImage,
137 int aTileNumber,
138 void* aCallbackData);
140 // Sets a callback to be called every time NextTile is called.
141 virtual void SetIterationCallback(BigImageIterationCallback aCallback,
142 void* aCallbackData) {
145 virtual gfx::IntRect GetTileRect();
147 virtual GLuint GetTextureID() = 0;
149 virtual uint32_t GetTileCount() {
150 return 1;
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.
158 * If this isn't implemented by a subclass, it will just perform
159 * a dummy BeginUpdate/EndUpdate pair.
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();
169 * Mark this texture as having valid contents. Call this after modifying
170 * the texture contents externally.
172 virtual void MarkValid() {}
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
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;
187 * Returns the image format of the texture. Only valid after a matching
188 * BeginUpdate/EndUpdate pair have been called.
190 virtual gfx::SurfaceFormat GetTextureFormat() {
191 return mTextureFormat;
194 /** Can be called safely at any time. */
197 * If this TextureImage has a permanent gfxASurface backing,
198 * return it. Otherwise return nullptr.
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;
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.
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)
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;
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().
261 class BasicTextureImage
262 : public TextureImage
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;
318 * A container class that complements many sub TextureImages into a big TextureImage.
319 * Aims to behave just like the real thing.
322 class TiledTextureImage
323 : public TextureImage
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 BeginBigImageIteration();
339 virtual bool NextTile();
340 virtual void SetIterationCallback(BigImageIterationCallback aCallback,
341 void* aCallbackData);
342 virtual gfx::IntRect GetTileRect();
343 virtual GLuint GetTextureID() {
344 return mImages[mCurrentImage]->GetTextureID();
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 BigImageIterationCallback 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;
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.
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);
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.
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.
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_ */