Bug 739648 - WebGL rendering is broken on Android due to tiles being rendered at y-flipped coordinates - r=bgirard

This commit is contained in:
Benoit Jacob 2012-05-03 15:59:19 -04:00
parent 236dd8e7f5
commit 657df782fe
5 changed files with 67 additions and 36 deletions

View File

@ -739,8 +739,9 @@ already_AddRefed<TextureImage>
GLContext::CreateTextureImage(const nsIntSize& aSize,
TextureImage::ContentType aContentType,
GLenum aWrapMode,
bool aUseNearestFilter)
TextureImage::Flags aFlags)
{
bool useNearestFilter = aFlags & TextureImage::UseNearestFilter;
MakeCurrent();
GLuint texture;
@ -749,13 +750,13 @@ GLContext::CreateTextureImage(const nsIntSize& aSize,
fActiveTexture(LOCAL_GL_TEXTURE0);
fBindTexture(LOCAL_GL_TEXTURE_2D, texture);
GLint texfilter = aUseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
GLint texfilter = useNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, texfilter);
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter);
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, aWrapMode);
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, aWrapMode);
return CreateBasicTextureImage(texture, aSize, aWrapMode, aContentType, this);
return CreateBasicTextureImage(texture, aSize, aWrapMode, aContentType, this, aFlags);
}
void GLContext::ApplyFilterToBoundTexture(gfxPattern::GraphicsFilter aFilter)
@ -938,14 +939,13 @@ BasicTextureImage::Resize(const nsIntSize& aSize)
TiledTextureImage::TiledTextureImage(GLContext* aGL,
nsIntSize aSize,
TextureImage::ContentType aContentType,
bool aUseNearestFilter)
: TextureImage(aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, aUseNearestFilter)
TextureImage::Flags aFlags)
: TextureImage(aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, aFlags)
, mCurrentImage(0)
, mInUpdate(false)
, mRows(0)
, mColumns(0)
, mGL(aGL)
, mUseNearestFilter(aUseNearestFilter)
, mTextureState(Created)
, mIterationCallback(nsnull)
{
@ -975,7 +975,7 @@ TiledTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion,
int oldCurrentImage = mCurrentImage;
BeginTileIteration();
do {
nsIntRect tileRect = GetTileRect();
nsIntRect tileRect = GetSrcTileRect();
int xPos = tileRect.x;
int yPos = tileRect.y;
@ -1187,6 +1187,15 @@ nsIntRect TiledTextureImage::GetTileRect()
return rect;
}
nsIntRect TiledTextureImage::GetSrcTileRect()
{
nsIntRect rect = GetTileRect();
unsigned int srcY = mFlags & NeedsYFlip
? mSize.height - rect.height - rect.y
: rect.y;
return nsIntRect(rect.x, srcY, rect.width, rect.height);
}
void
TiledTextureImage::BindTexture(GLenum aTextureUnit)
{
@ -1267,7 +1276,7 @@ void TiledTextureImage::Resize(const nsIntSize& aSize)
// Create a new tile.
nsRefPtr<TextureImage> teximg =
mGL->TileGenFunc(size, mContentType, mUseNearestFilter);
mGL->TileGenFunc(size, mContentType, mFlags);
if (replace)
mImages.ReplaceElementAt(i, teximg.forget());
else

View File

@ -127,6 +127,12 @@ public:
Valid // Texture fully ready to use.
};
enum Flags {
NoFlags = 0x0,
UseNearestFilter = 0x1,
NeedsYFlip = 0x2
};
typedef gfxASurface::gfxContentType ContentType;
virtual ~TextureImage() {}
@ -318,18 +324,24 @@ protected:
*/
TextureImage(const nsIntSize& aSize,
GLenum aWrapMode, ContentType aContentType,
bool aIsRGB = false)
Flags aFlags = NoFlags)
: mSize(aSize)
, mWrapMode(aWrapMode)
, mContentType(aContentType)
, mFilter(gfxPattern::FILTER_GOOD)
, mFlags(aFlags)
{}
virtual nsIntRect GetSrcTileRect() {
return nsIntRect(nsIntPoint(0,0), mSize);
};
nsIntSize mSize;
GLenum mWrapMode;
ContentType mContentType;
ShaderProgramType mShaderType;
gfxPattern::GraphicsFilter mFilter;
Flags mFlags;
};
/**
@ -352,8 +364,9 @@ public:
const nsIntSize& aSize,
GLenum aWrapMode,
ContentType aContentType,
GLContext* aContext)
: TextureImage(aSize, aWrapMode, aContentType)
GLContext* aContext,
TextureImage::Flags aFlags = TextureImage::NoFlags)
: TextureImage(aSize, aWrapMode, aContentType, aFlags)
, mTexture(aTexture)
, mTextureState(Created)
, mGLContext(aContext)
@ -408,7 +421,7 @@ class TiledTextureImage
{
public:
TiledTextureImage(GLContext* aGL, nsIntSize aSize,
TextureImage::ContentType, bool aUseNearestFilter = false);
TextureImage::ContentType, TextureImage::Flags aFlags = TextureImage::NoFlags);
~TiledTextureImage();
void DumpDiv();
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
@ -428,7 +441,10 @@ public:
virtual bool InUpdate() const { return mInUpdate; };
virtual void BindTexture(GLenum);
virtual void ApplyFilter();
protected:
virtual nsIntRect GetSrcTileRect();
unsigned int mCurrentImage;
TileIterationCallback mIterationCallback;
void* mIterationCallbackData;
@ -1274,7 +1290,8 @@ public:
* |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=true| for GL_NEAREST filtering. Return
* |aFlags=UseNearestFilter| for GL_NEAREST filtering. Specify
* |aFlags=NeedsYFlip| if the image is flipped. Return
* NULL if creating the TextureImage fails.
*
* The returned TextureImage may only be used with this GLContext.
@ -1286,7 +1303,7 @@ public:
CreateTextureImage(const nsIntSize& aSize,
TextureImage::ContentType aContentType,
GLenum aWrapMode,
bool aUseNearestFilter=false);
TextureImage::Flags aFlags = TextureImage::NoFlags);
/**
* In EGL we want to use Tiled Texture Images, which we return
@ -1298,7 +1315,7 @@ public:
virtual already_AddRefed<TextureImage>
TileGenFunc(const nsIntSize& aSize,
TextureImage::ContentType aContentType,
bool aUseNearestFilter = false)
TextureImage::Flags aFlags = TextureImage::NoFlags)
{
return nsnull;
};
@ -1728,10 +1745,11 @@ protected:
const nsIntSize& aSize,
GLenum aWrapMode,
TextureImage::ContentType aContentType,
GLContext* aContext)
GLContext* aContext,
TextureImage::Flags aFlags = TextureImage::NoFlags)
{
nsRefPtr<BasicTextureImage> teximage(
new BasicTextureImage(aTexture, aSize, aWrapMode, aContentType, aContext));
new BasicTextureImage(aTexture, aSize, aWrapMode, aContentType, aContext, aFlags));
return teximage.forget();
}

View File

@ -525,13 +525,13 @@ public:
CreateTextureImage(const nsIntSize& aSize,
TextureImage::ContentType aContentType,
GLenum aWrapMode,
bool aUseNearestFilter=false);
TextureImage::Flags aFlags = TextureImage::NoFlags);
// a function to generate Tiles for Tiled Texture Image
virtual already_AddRefed<TextureImage>
TileGenFunc(const nsIntSize& aSize,
TextureImage::ContentType aContentType,
bool aUseNearestFilter = false);
TextureImage::Flags aFlags = TextureImage::NoFlags);
// hold a reference to the given surface
// for the lifetime of this context.
void HoldSurface(gfxASurface *aSurf) {
@ -800,8 +800,9 @@ public:
const nsIntSize& aSize,
GLenum aWrapMode,
ContentType aContentType,
GLContext* aContext)
: TextureImage(aSize, aWrapMode, aContentType)
GLContext* aContext,
TextureImage::Flags aFlags = TextureImage::NoFlags)
: TextureImage(aSize, aWrapMode, aContentType, aFlags)
, mGLContext(aContext)
, mUpdateFormat(gfxASurface::ImageFormatUnknown)
, mSurface(nsnull)
@ -1294,16 +1295,16 @@ already_AddRefed<TextureImage>
GLContextEGL::CreateTextureImage(const nsIntSize& aSize,
TextureImage::ContentType aContentType,
GLenum aWrapMode,
bool aUseNearestFilter)
TextureImage::Flags aFlags)
{
nsRefPtr<TextureImage> t = new gl::TiledTextureImage(this, aSize, aContentType, aUseNearestFilter);
nsRefPtr<TextureImage> t = new gl::TiledTextureImage(this, aSize, aContentType, aFlags);
return t.forget();
}
already_AddRefed<TextureImage>
GLContextEGL::TileGenFunc(const nsIntSize& aSize,
TextureImage::ContentType aContentType,
bool aUseNearestFilter)
TextureImage::Flags aFlags)
{
MakeCurrent();
@ -1314,9 +1315,9 @@ GLContextEGL::TileGenFunc(const nsIntSize& aSize,
fBindTexture(LOCAL_GL_TEXTURE_2D, texture);
nsRefPtr<TextureImageEGL> teximage =
new TextureImageEGL(texture, aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, this);
new TextureImageEGL(texture, aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, this, aFlags);
GLint texfilter = aUseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
GLint texfilter = aFlags & TextureImage::UseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, texfilter);
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter);
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);

View File

@ -859,7 +859,7 @@ TRY_AGAIN_NO_SHARING:
CreateTextureImage(const nsIntSize& aSize,
TextureImage::ContentType aContentType,
GLenum aWrapMode,
bool aUseNearestFilter = false);
TextureImage::Flags aFlags = TextureImage::NoFlags);
private:
friend class GLContextProviderGLX;
@ -896,7 +896,7 @@ class TextureImageGLX : public TextureImage
GLContextGLX::CreateTextureImage(const nsIntSize&,
ContentType,
GLenum,
bool);
TextureImage::Flags);
public:
virtual ~TextureImageGLX()
@ -960,8 +960,9 @@ private:
ContentType aContentType,
GLContext* aContext,
gfxASurface* aSurface,
GLXPixmap aPixmap)
: TextureImage(aSize, aWrapMode, aContentType)
GLXPixmap aPixmap,
TextureImage::Flags aFlags = TextureImage::NoFlags)
: TextureImage(aSize, aWrapMode, aContentType, aFlags)
, mGLContext(aContext)
, mUpdateSurface(aSurface)
, mPixmap(aPixmap)
@ -991,13 +992,13 @@ already_AddRefed<TextureImage>
GLContextGLX::CreateTextureImage(const nsIntSize& aSize,
TextureImage::ContentType aContentType,
GLenum aWrapMode,
bool aUseNearestFilter)
TextureImage::Flags aFlags)
{
if (!TextureImageSupportsGetBackingSurface()) {
return GLContext::CreateTextureImage(aSize,
aContentType,
aWrapMode,
aUseNearestFilter);
aFlags & UseNearestFilter);
}
Display *display = DefaultXDisplay();
@ -1032,9 +1033,9 @@ GLContextGLX::CreateTextureImage(const nsIntSize& aSize,
fBindTexture(LOCAL_GL_TEXTURE_2D, texture);
nsRefPtr<TextureImageGLX> teximage =
new TextureImageGLX(texture, aSize, aWrapMode, aContentType, this, surface, pixmap);
new TextureImageGLX(texture, aSize, aWrapMode, aContentType, this, surface, pixmap, aFlags);
GLint texfilter = aUseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
GLint texfilter = aFlags & UseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, texfilter);
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter);
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, aWrapMode);

View File

@ -339,10 +339,12 @@ ShadowCanvasLayerOGL::Init(const CanvasSurface& aNewFront, bool needYFlip)
{
nsRefPtr<gfxASurface> surf = ShadowLayerForwarder::OpenDescriptor(aNewFront);
mNeedsYFlip = needYFlip;
mTexImage = gl()->CreateTextureImage(surf->GetSize(),
surf->GetContentType(),
LOCAL_GL_CLAMP_TO_EDGE);
mNeedsYFlip = needYFlip;
LOCAL_GL_CLAMP_TO_EDGE,
mNeedsYFlip ? TextureImage::NeedsYFlip : TextureImage::NoFlags);
}
void