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,
62 DisallowBigImage
= 0x4
65 typedef gfxContentType ContentType
;
66 typedef gfxImageFormat ImageFormat
;
68 static already_AddRefed
<TextureImage
> Create(
70 const nsIntSize
& aSize
,
71 TextureImage::ContentType aContentType
,
73 TextureImage::Flags aFlags
= TextureImage::NoFlags
);
74 // Moz2D equivalent...
75 static already_AddRefed
<TextureImage
> Create(
77 const gfx::IntSize
& aSize
,
78 TextureImage::ContentType aContentType
,
80 TextureImage::Flags aFlags
= TextureImage::NoFlags
);
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
117 * BeginUpdate() must have been called exactly once before
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() {
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
,
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() {
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
) {
163 nsIntRegion
r(nsIntRect(0, 0, aSize
.width
, aSize
.height
));
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()
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
; }
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
)
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();
245 ContentType mContentType
;
246 ImageFormat mImageFormat
;
247 gfx::SurfaceFormat mTextureFormat
;
248 GraphicsFilter mFilter
;
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
261 class BasicTextureImage
262 : public TextureImage
265 virtual ~BasicTextureImage();
267 BasicTextureImage(GLuint aTexture
,
268 const nsIntSize
& aSize
,
270 ContentType aContentType
,
272 TextureImage::Flags aFlags
= TextureImage::NoFlags
,
273 TextureImage::ImageFormat aImageFormat
= gfxImageFormat::Unknown
);
274 BasicTextureImage(GLuint aTexture
,
275 const gfx::IntSize
& aSize
,
277 ContentType aContentType
,
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
);
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
326 TiledTextureImage(GLContext
* aGL
,
328 TextureImage::ContentType
,
329 TextureImage::Flags aFlags
= TextureImage::NoFlags
,
330 TextureImage::ImageFormat aImageFormat
= gfxImageFormat::Unknown
);
331 ~TiledTextureImage();
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
);
351 virtual gfx::IntRect
GetSrcTileRect();
353 unsigned int mCurrentImage
;
354 BigImageIterationCallback mIterationCallback
;
355 void* mIterationCallbackData
;
356 nsTArray
< nsRefPtr
<TextureImage
> > mImages
;
359 unsigned int mTileSize
;
360 unsigned int mRows
, mColumns
;
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
,
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
399 already_AddRefed
<TextureImage
>
400 CreateTextureImage(GLContext
* gl
,
401 const gfx::IntSize
& aSize
,
402 TextureImage::ContentType aContentType
,
404 TextureImage::Flags aFlags
= TextureImage::NoFlags
,
405 TextureImage::ImageFormat aImageFormat
= gfxImageFormat::Unknown
);
408 } // namespace mozilla
410 #endif /* GLTEXTUREIMAGE_H_ */