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_
13 #include "GLContextTypes.h"
14 #include "GraphicsFilter.h"
15 #include "mozilla/gfx/Rect.h"
16 #include "mozilla/RefPtr.h"
22 class DataSourceSurface
;
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
37 * Implementation note: TextureImages attempt to unify two categories
40 * (1) proxy to server-side object that can be bound to a texture;
43 * (2) efficient manager of texture memory; e.g. by having clients draw
44 * into a scratch buffer which is then uploaded with
49 NS_INLINE_DECL_REFCOUNTING(TextureImage
)
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.
60 UseNearestFilter
= 0x1,
61 OriginBottomLeft
= 0x2,
62 DisallowBigImage
= 0x4
65 typedef gfxContentType ContentType
;
66 typedef gfxImageFormat ImageFormat
;
68 static already_AddRefed
<TextureImage
> Create(
70 const gfx::IntSize
& aSize
,
71 TextureImage::ContentType aContentType
,
73 TextureImage::Flags aFlags
= TextureImage::NoFlags
);
76 * Returns a gfxASurface for updating |aRegion| of the client's
77 * image if successul, nullptr if not. |aRegion|'s bounds must fit
78 * within Size(); its coordinate space (if any) is ignored. If
79 * the update begins successfully, the returned gfxASurface is
80 * owned by this. Otherwise, nullptr is returned.
82 * |aRegion| is an inout param: the returned region is what the
83 * client must repaint. Category (1) regions above can
84 * efficiently handle repaints to "scattered" regions, while (2)
85 * can only efficiently handle repaints to rects.
87 * Painting the returned surface outside of |aRegion| results
88 * in undefined behavior.
90 * BeginUpdate() calls cannot be "nested", and each successful
91 * BeginUpdate() must be followed by exactly one EndUpdate() (see
92 * below). Failure to do so can leave this in a possibly
93 * inconsistent state. Unsuccessful BeginUpdate()s must not be
94 * followed by EndUpdate().
96 virtual gfx::DrawTarget
* BeginUpdate(nsIntRegion
& aRegion
) = 0;
98 * Retrieves the region that will require updating, given a
99 * region that needs to be updated. This can be used for
100 * making decisions about updating before calling BeginUpdate().
102 * |aRegion| is an inout param.
104 virtual void GetUpdateRegion(nsIntRegion
& aForRegion
) {
107 * Finish the active update and synchronize with the server, if
110 * BeginUpdate() must have been called exactly once before
113 virtual void EndUpdate() = 0;
116 * The Image may contain several textures for different regions (tiles).
117 * These functions iterate over each sub texture image tile.
119 virtual void BeginBigImageIteration() {
122 virtual bool NextTile() {
126 // Function prototype for a tile iteration callback. Returning false will
127 // cause iteration to be interrupted (i.e. the corresponding NextTile call
128 // will return false).
129 typedef bool (* BigImageIterationCallback
)(TextureImage
* aImage
,
131 void* aCallbackData
);
133 // Sets a callback to be called every time NextTile is called.
134 virtual void SetIterationCallback(BigImageIterationCallback aCallback
,
135 void* aCallbackData
) {
138 virtual gfx::IntRect
GetTileRect();
140 virtual GLuint
GetTextureID() = 0;
142 virtual uint32_t GetTileCount() {
147 * Set this TextureImage's size, and ensure a texture has been
148 * allocated. Must not be called between BeginUpdate and EndUpdate.
149 * After a resize, the contents are undefined.
151 * If this isn't implemented by a subclass, it will just perform
152 * a dummy BeginUpdate/EndUpdate pair.
154 virtual void Resize(const gfx::IntSize
& aSize
) {
156 nsIntRegion
r(nsIntRect(0, 0, aSize
.width
, aSize
.height
));
162 * Mark this texture as having valid contents. Call this after modifying
163 * the texture contents externally.
165 virtual void MarkValid() {}
168 * aSurf - the source surface to update from
169 * aRegion - the region in this image to update
170 * aFrom - offset in the source to update from
172 virtual bool DirectUpdate(gfx::DataSourceSurface
* aSurf
, const nsIntRegion
& aRegion
, const gfx::IntPoint
& aFrom
= gfx::IntPoint(0,0)) = 0;
173 bool UpdateFromDataSource(gfx::DataSourceSurface
*aSurf
,
174 const nsIntRegion
* aDstRegion
= nullptr,
175 const gfx::IntPoint
* aSrcOffset
= nullptr);
177 virtual void BindTexture(GLenum aTextureUnit
) = 0;
180 * Returns the image format of the texture. Only valid after a matching
181 * BeginUpdate/EndUpdate pair have been called.
183 virtual gfx::SurfaceFormat
GetTextureFormat() {
184 return mTextureFormat
;
187 /** Can be called safely at any time. */
190 * If this TextureImage has a permanent gfxASurface backing,
191 * return it. Otherwise return nullptr.
193 virtual already_AddRefed
<gfxASurface
> GetBackingSurface()
197 gfx::IntSize
GetSize() const;
198 ContentType
GetContentType() const { return mContentType
; }
199 ImageFormat
GetImageFormat() const { return mImageFormat
; }
200 virtual bool InUpdate() const = 0;
201 GLenum
GetWrapMode() const { return mWrapMode
; }
203 void SetFilter(GraphicsFilter aFilter
) { mFilter
= aFilter
; }
206 friend class GLContext
;
209 * After the ctor, the TextureImage is invalid. Implementations
210 * must allocate resources successfully before returning the new
211 * TextureImage from GLContext::CreateTextureImage(). That is,
212 * clients must not be given partially-constructed TextureImages.
214 TextureImage(const nsIntSize
& aSize
,
215 GLenum aWrapMode
, ContentType aContentType
,
216 Flags aFlags
= NoFlags
,
217 ImageFormat aImageFormat
= gfxImageFormat::Unknown
)
218 : mSize(aSize
.ToIntSize())
219 , mWrapMode(aWrapMode
)
220 , mContentType(aContentType
)
221 , mImageFormat(aImageFormat
)
222 , mFilter(GraphicsFilter::FILTER_GOOD
)
226 // Moz2D equivalent...
227 TextureImage(const gfx::IntSize
& aSize
,
228 GLenum aWrapMode
, ContentType aContentType
,
229 Flags aFlags
= NoFlags
);
231 // Protected destructor, to discourage deletion outside of Release():
232 virtual ~TextureImage() {}
234 virtual gfx::IntRect
GetSrcTileRect();
238 ContentType mContentType
;
239 ImageFormat mImageFormat
;
240 gfx::SurfaceFormat mTextureFormat
;
241 GraphicsFilter mFilter
;
246 * BasicTextureImage is the baseline TextureImage implementation ---
247 * it updates its texture by allocating a scratch buffer for the
248 * client to draw into, then using glTexSubImage2D() to upload the new
249 * pixels. Platforms must provide the code to create a new surface
250 * into which the updated pixels will be drawn, and the code to
251 * convert the update surface's pixels into an image on which we can
254 class BasicTextureImage
255 : public TextureImage
258 virtual ~BasicTextureImage();
260 BasicTextureImage(GLuint aTexture
,
261 const nsIntSize
& aSize
,
263 ContentType aContentType
,
265 TextureImage::Flags aFlags
= TextureImage::NoFlags
,
266 TextureImage::ImageFormat aImageFormat
= gfxImageFormat::Unknown
);
267 BasicTextureImage(GLuint aTexture
,
268 const gfx::IntSize
& aSize
,
270 ContentType aContentType
,
272 TextureImage::Flags aFlags
= TextureImage::NoFlags
,
273 TextureImage::ImageFormat aImageFormat
= gfxImageFormat::Unknown
);
275 virtual void BindTexture(GLenum aTextureUnit
);
277 virtual gfx::DrawTarget
* BeginUpdate(nsIntRegion
& aRegion
);
278 virtual void GetUpdateRegion(nsIntRegion
& aForRegion
);
279 virtual void EndUpdate();
280 virtual bool DirectUpdate(gfx::DataSourceSurface
* aSurf
, const nsIntRegion
& aRegion
, const gfx::IntPoint
& aFrom
= gfx::IntPoint(0,0));
281 virtual GLuint
GetTextureID() { return mTexture
; }
282 virtual TemporaryRef
<gfx::DrawTarget
>
283 GetDrawTargetForUpdate(const gfx::IntSize
& aSize
, gfx::SurfaceFormat aFmt
);
285 virtual void MarkValid() { mTextureState
= Valid
; }
287 // Call when drawing into the update surface is complete.
288 // Returns true if textures should be upload with a relative
289 // offset - See UploadSurfaceToTexture.
290 virtual bool FinishedSurfaceUpdate();
292 // Call after surface data has been uploaded to a texture.
293 virtual void FinishedSurfaceUpload();
295 virtual bool InUpdate() const { return !!mUpdateDrawTarget
; }
297 virtual void Resize(const gfx::IntSize
& aSize
);
301 TextureState mTextureState
;
302 nsRefPtr
<GLContext
> mGLContext
;
303 RefPtr
<gfx::DrawTarget
> mUpdateDrawTarget
;
304 nsIntRegion mUpdateRegion
;
306 // The offset into the update surface at which the update rect is located.
307 nsIntPoint mUpdateOffset
;
311 * A container class that complements many sub TextureImages into a big TextureImage.
312 * Aims to behave just like the real thing.
315 class TiledTextureImage MOZ_FINAL
316 : public TextureImage
319 TiledTextureImage(GLContext
* aGL
,
321 TextureImage::ContentType
,
322 TextureImage::Flags aFlags
= TextureImage::NoFlags
,
323 TextureImage::ImageFormat aImageFormat
= gfxImageFormat::Unknown
);
324 ~TiledTextureImage();
326 virtual gfx::DrawTarget
* BeginUpdate(nsIntRegion
& aRegion
);
327 virtual void GetUpdateRegion(nsIntRegion
& aForRegion
);
328 virtual void EndUpdate();
329 virtual void Resize(const gfx::IntSize
& aSize
);
330 virtual uint32_t GetTileCount();
331 virtual void BeginBigImageIteration();
332 virtual bool NextTile();
333 virtual void SetIterationCallback(BigImageIterationCallback aCallback
,
334 void* aCallbackData
);
335 virtual gfx::IntRect
GetTileRect();
336 virtual GLuint
GetTextureID() {
337 return mImages
[mCurrentImage
]->GetTextureID();
339 virtual bool DirectUpdate(gfx::DataSourceSurface
* aSurf
, const nsIntRegion
& aRegion
, const gfx::IntPoint
& aFrom
= gfx::IntPoint(0,0));
340 virtual bool InUpdate() const { return mInUpdate
; }
341 virtual void BindTexture(GLenum
);
344 virtual gfx::IntRect
GetSrcTileRect();
346 unsigned int mCurrentImage
;
347 BigImageIterationCallback mIterationCallback
;
348 void* mIterationCallbackData
;
349 nsTArray
< nsRefPtr
<TextureImage
> > mImages
;
352 unsigned int mTileSize
;
353 unsigned int mRows
, mColumns
;
355 // A temporary draw target to faciliate cross-tile updates.
356 RefPtr
<gfx::DrawTarget
> mUpdateDrawTarget
;
357 // The region of update requested
358 nsIntRegion mUpdateRegion
;
359 TextureState mTextureState
;
360 TextureImage::ImageFormat mImageFormat
;
364 * Creates a TextureImage of the basic implementation, can be useful in cases
365 * where we know we don't want to use platform-specific TextureImage.
366 * In doubt, use GLContext::CreateTextureImage instead.
368 already_AddRefed
<TextureImage
>
369 CreateBasicTextureImage(GLContext
* aGL
,
370 const gfx::IntSize
& aSize
,
371 TextureImage::ContentType aContentType
,
373 TextureImage::Flags aFlags
,
374 TextureImage::ImageFormat aImageFormat
= gfxImageFormat::Unknown
);
377 * Return a valid, allocated TextureImage of |aSize| with
378 * |aContentType|. If |aContentType| is COLOR, |aImageFormat| can be used
379 * to hint at the preferred RGB format, however it is not necessarily
380 * respected. The TextureImage's texture is configured to use
381 * |aWrapMode| (usually GL_CLAMP_TO_EDGE or GL_REPEAT) and by
382 * default, GL_LINEAR filtering. Specify
383 * |aFlags=UseNearestFilter| for GL_NEAREST filtering. Specify
384 * |aFlags=OriginBottomLeft| if the image is origin-bottom-left, instead of the
385 * default origin-top-left. Return
386 * nullptr if creating the TextureImage fails.
388 * The returned TextureImage may only be used with this GLContext.
389 * Attempting to use the returned TextureImage after this
390 * GLContext is destroyed will result in undefined (and likely
393 already_AddRefed
<TextureImage
>
394 CreateTextureImage(GLContext
* gl
,
395 const gfx::IntSize
& aSize
,
396 TextureImage::ContentType aContentType
,
398 TextureImage::Flags aFlags
= TextureImage::NoFlags
,
399 TextureImage::ImageFormat aImageFormat
= gfxImageFormat::Unknown
);
402 } // namespace mozilla
404 #endif /* GLTEXTUREIMAGE_H_ */