diff --git a/gfx/thebes/GLContext.h b/gfx/thebes/GLContext.h index 726c33f6b55..9563552b858 100644 --- a/gfx/thebes/GLContext.h +++ b/gfx/thebes/GLContext.h @@ -48,12 +48,15 @@ #endif #include "GLDefs.h" +#include "gfxASurface.h" +#include "gfxContext.h" #include "gfxRect.h" #include "nsISupportsImpl.h" #include "prlink.h" #include "nsDataHashtable.h" #include "nsHashKeys.h" +#include "nsRegion.h" #ifndef GLAPIENTRY #ifdef XP_WIN @@ -73,6 +76,8 @@ typedef char realGLboolean; namespace mozilla { namespace gl { +class GLContext; + class LibrarySymbolLoader { public: @@ -115,6 +120,93 @@ protected: }; +/** + * A TextureImage encapsulates a surface that can be drawn to by a + * Thebes gfxContext and (hopefully efficiently!) synchronized to a + * texture in the server. TextureImages are associated with one and + * only one GLContext. + * + * Implementation note: TextureImages attempt to unify two categories + * of backends + * + * (1) proxy to server-side object that can be bound to a texture; + * e.g. Pixmap on X11. + * + * (2) efficient manager of texture memory; e.g. by having clients draw + * into a scratch buffer which is then uploaded with + * glTexSubImage2D(). + */ +class TextureImage +{ + NS_INLINE_DECL_REFCOUNTING(TextureImage) +public: + typedef gfxASurface::gfxContentType ContentType; + + virtual ~TextureImage() {} + + /** + * Return a gfxContext for updating |aRegion| of the client's + * image if successul, NULL if not. |aRegion|'s bounds must fit + * within Size(); its coordinate space (if any) is ignored. If + * the update begins successfully, the returned gfxContext is + * owned by this. Otherwise, NULL is returned. + * + * |aRegion| is an inout param: the returned region is what the + * client must repaint. Category (1) regions above can + * efficiently handle repaints to "scattered" regions, while (2) + * can only efficiently handle repaints to rects. + * + * The returned context is neither translated nor clipped: it's a + * context for rect(<0,0>, Size()). Painting the returned context + * outside of |aRegion| results in undefined behavior. + * + * BeginUpdate() calls cannot be "nested", and each successful + * BeginUpdate() must be followed by exactly one EndUpdate() (see + * below). Failure to do so can leave this in a possibly + * inconsistent state. Unsuccessful BeginUpdate()s must not be + * followed by EndUpdate(). + */ + virtual gfxContext* BeginUpdate(nsIntRegion& aRegion) = 0; + /** + * Finish the active update and synchronize with the server, if + * necessary. Return PR_TRUE iff this's texture is already bound. + * + * BeginUpdate() must have been called exactly once before + * EndUpdate(). + */ + virtual PRBool EndUpdate() = 0; + + /** + * Return this TextureImage's texture ID for use with GL APIs. + * Callers are responsible for properly binding the texture etc. + * + * The effects of using a texture after BeginUpdate() but before + * EndUpdate() are undefined. + */ + GLuint Texture() { return mTexture; } + + /** Can be called safely at any time. */ + const nsIntSize& GetSize() const { return mSize; } + ContentType GetContentType() const { return mContentType; } + +protected: + /** + * After the ctor, the TextureImage is invalid. Implementations + * must allocate resources successfully before returning the new + * TextureImage from GLContext::CreateTextureImage(). That is, + * clients must not be given partially-constructed TextureImages. + */ + TextureImage(GLuint aTexture, const nsIntSize& aSize, ContentType aContentType) + : mTexture(aTexture) + , mSize(aSize) + , mContentType(aContentType) + {} + + GLuint mTexture; + nsIntSize mSize; + ContentType mContentType; +}; + class GLContext : public LibrarySymbolLoader { @@ -191,6 +283,27 @@ public: MakeCurrent(); fDeleteTextures(1, &tex); } + + /** + * Return a valid, allocated TextureImage of |aSize| with + * |aContentType|. The TextureImage's texture is configured to + * use |aWrapMode| (usually GL_CLAMP_TO_EDGE or GL_REPEAT) and by + * default, GL_LINEAR filtering. Specify + * |aUseNearestFilter=PR_TRUE| for GL_NEAREST filtering. Return + * NULL if creating the TextureImage fails. + * + * The returned TextureImage may only be used with this GLContext. + * Attempting to use the returned TextureImage after this + * GLContext is destroyed will result in undefined (and likely + * crashy) behavior. + */ + virtual already_AddRefed + CreateTextureImage(const nsIntSize& aSize, + TextureImage::ContentType aContentType, + GLint aWrapMode, + PRBool aUseNearestFilter=PR_FALSE) + { return NULL; } + protected: PRBool mInitialized;