Bug 607687 - Fennec should take care about Texture MAX size HW limitation r=jmuizelaar

This commit is contained in:
Florian Haenel 2011-07-06 11:00:47 -07:00
Родитель b7858d4918
Коммит de4075b859
8 изменённых файлов: 491 добавлений и 126 удалений

Просмотреть файл

@ -366,19 +366,21 @@ ShadowCanvasLayerOGL::RenderLayer(int aPreviousFrameBuffer,
{
mOGLManager->MakeCurrent();
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexImage->Texture());
ColorTextureLayerProgram *program =
mOGLManager->GetColorTextureLayerProgram(mTexImage->GetShaderProgramType());
ApplyFilter(mFilter);
program->Activate();
program->SetLayerQuadRect(nsIntRect(nsIntPoint(0, 0), mTexImage->GetSize()));
program->SetLayerTransform(GetEffectiveTransform());
program->SetLayerOpacity(GetEffectiveOpacity());
program->SetRenderOffset(aOffset);
program->SetTextureUnit(0);
mOGLManager->BindAndDrawQuad(program, mNeedsYFlip ? true : false);
mTexImage->BeginTileIteration();
do {
TextureImage::ScopedBindTexture texBind(mTexImage, LOCAL_GL_TEXTURE0);
program->SetLayerQuadRect(mTexImage->GetTileRect());
mOGLManager->BindAndDrawQuad(program, mNeedsYFlip); // FIXME flip order of tiles?
} while (mTexImage->NextTile());
}

Просмотреть файл

@ -938,20 +938,20 @@ ShadowImageLayerOGL::RenderLayer(int aPreviousFrameBuffer,
{
mOGLManager->MakeCurrent();
LayerProgram* program;
if (mTexImage) {
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexImage->Texture());
ColorTextureLayerProgram *colorProgram =
mOGLManager->GetColorTextureLayerProgram(mTexImage->GetShaderProgramType());
ApplyFilter(mFilter);
colorProgram->Activate();
colorProgram->SetTextureUnit(0);
colorProgram->SetLayerQuadRect(nsIntRect(nsIntPoint(0, 0), mTexImage->GetSize()));
program = colorProgram;
mTexImage->BeginTileIteration();
do {
TextureImage::ScopedBindTexture texBind(mTexImage, LOCAL_GL_TEXTURE0);
ApplyFilter(mFilter);
colorProgram->SetLayerQuadRect(mTexImage->GetTileRect());
mOGLManager->BindAndDrawQuad(colorProgram);
} while (mTexImage->NextTile());
} else {
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mYUVTexture[0].GetTextureID());
@ -962,7 +962,7 @@ ShadowImageLayerOGL::RenderLayer(int aPreviousFrameBuffer,
gl()->fActiveTexture(LOCAL_GL_TEXTURE2);
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mYUVTexture[2].GetTextureID());
ApplyFilter(mFilter);
YCbCrTextureLayerProgram *yuvProgram = mOGLManager->GetYCbCrLayerProgram();
yuvProgram->Activate();
@ -970,24 +970,14 @@ ShadowImageLayerOGL::RenderLayer(int aPreviousFrameBuffer,
mPictureRect.width,
mPictureRect.height));
yuvProgram->SetYCbCrTextureUnits(0, 1, 2);
yuvProgram->SetLayerTransform(GetEffectiveTransform());
yuvProgram->SetLayerOpacity(GetEffectiveOpacity());
yuvProgram->SetRenderOffset(aOffset);
program = yuvProgram;
program->SetLayerTransform(GetEffectiveTransform());
program->SetLayerOpacity(GetEffectiveOpacity());
program->SetRenderOffset(aOffset);
mOGLManager->BindAndDrawQuadWithTextureRect(program,
mOGLManager->BindAndDrawQuadWithTextureRect(yuvProgram,
mPictureRect,
nsIntSize(mSize.width, mSize.height));
return;
}
program->SetLayerTransform(GetEffectiveTransform());
program->SetLayerOpacity(GetEffectiveOpacity());
program->SetRenderOffset(aOffset);
mOGLManager->BindAndDrawQuad(program);
}
}

Просмотреть файл

@ -141,10 +141,6 @@ ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset,
mTexImageOnWhite->EndUpdate();
}
// Bind textures.
TextureImage::ScopedBindTexture texBind(mTexImage, LOCAL_GL_TEXTURE0);
TextureImage::ScopedBindTexture texOnWhiteBind(mTexImageOnWhite, LOCAL_GL_TEXTURE1);
PRInt32 passes = mTexImageOnWhite ? 2 : 1;
for (PRInt32 pass = 1; pass <= passes; ++pass) {
LayerProgram *program;
@ -194,17 +190,42 @@ ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset,
} else {
renderRegion = &visibleRegion;
}
nsIntRegionRectIterator iter(*renderRegion);
while (const nsIntRect *iterRect = iter.Next()) {
nsIntRect quadRect = *iterRect;
program->SetLayerQuadRect(quadRect);
quadRect.MoveBy(-GetOriginOffset());
aManager->BindAndDrawQuadWithTextureRect(program, quadRect,
mTexImage->GetSize(),
mTexImage->GetWrapMode());
mTexImage->BeginTileIteration();
if (mTexImageOnWhite) {
mTexImageOnWhite->BeginTileIteration();
NS_ASSERTION(mTexImageOnWhite->GetTileRect() == mTexImage->GetTileRect(), "component alpha textures should be the same size.");
}
nsIntRegion region(*renderRegion);
nsIntPoint origin = GetOriginOffset();
region.MoveBy(-origin); // translate into TexImage space, buffer origin might not be at texture (0,0)
do {
nsIntRect textureRect = mTexImage->GetTileRect();
textureRect.MoveBy(region.GetBounds().x, region.GetBounds().y);
nsIntRegion subregion(region);
subregion.And(region, textureRect); // region this texture is visible in
if (subregion.IsEmpty()) {
continue;
}
// Bind textures.
TextureImage::ScopedBindTexture texBind(mTexImage, LOCAL_GL_TEXTURE0);
TextureImage::ScopedBindTexture texOnWhiteBind(mTexImageOnWhite, LOCAL_GL_TEXTURE1);
nsIntRegionRectIterator iter(subregion);
while (const nsIntRect *iterRect = iter.Next()) {
nsIntRect regionRect = *iterRect; // one rectangle of this texture's region
// translate into the correct place for this texture sub-region
nsIntRect screenRect = regionRect;
screenRect.MoveBy(origin);
program->SetLayerQuadRect(screenRect);
regionRect.MoveBy(-mTexImage->GetTileRect().TopLeft()); // get region of tile
aManager->BindAndDrawQuadWithTextureRect(program, regionRect,
textureRect.Size(),
mTexImage->GetWrapMode());
}
} while (mTexImage->NextTile());
}
if (mTexImageOnWhite) {

Просмотреть файл

@ -52,6 +52,7 @@
#include "GLContextProvider.h"
#include "gfxCrashReporterUtils.h"
#include "gfxUtils.h"
#include "mozilla/Util.h" // for DebugOnly
@ -636,7 +637,7 @@ void
BasicTextureImage::BindTexture(GLenum aTextureUnit)
{
mGLContext->fActiveTexture(aTextureUnit);
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, Texture());
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
}
@ -659,7 +660,7 @@ BasicTextureImage::FinishedSurfaceUpload()
}
bool
BasicTextureImage::DirectUpdate(gfxASurface *aSurf, const nsIntRegion& aRegion)
BasicTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
{
nsIntRect bounds = aRegion.GetBounds();
nsIntRegion region;
@ -675,7 +676,7 @@ BasicTextureImage::DirectUpdate(gfxASurface *aSurf, const nsIntRegion& aRegion)
region,
mTexture,
mTextureState == Created,
bounds.TopLeft(),
bounds.TopLeft() + aFrom,
PR_FALSE);
mTextureState = Valid;
return true;
@ -702,6 +703,202 @@ BasicTextureImage::Resize(const nsIntSize& aSize)
mSize = aSize;
}
TiledTextureImage::TiledTextureImage(GLContext* aGL,
nsIntSize aSize,
TextureImage::ContentType aContentType,
PRBool aUseNearestFilter)
: TextureImage(aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, aUseNearestFilter)
, mCurrentImage(0)
, mInUpdate(PR_FALSE)
, mGL(aGL)
, mUseNearestFilter(aUseNearestFilter)
, mTextureState(Created)
{
mTileSize = mGL->GetMaxTextureSize();
if (aSize != nsIntSize(0,0)) {
Resize(aSize);
}
}
TiledTextureImage::~TiledTextureImage()
{
}
bool
TiledTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
{
nsIntRect bounds = aRegion.GetBounds();
nsIntRegion region;
if (mTextureState != Valid) {
bounds = nsIntRect(0, 0, mSize.width, mSize.height);
region = nsIntRegion(bounds);
} else {
region = aRegion;
}
PRBool result = PR_TRUE;
for (unsigned i = 0; i < mImages.Length(); i++) {
unsigned int xPos = (i % mColumns) * mTileSize;
unsigned int yPos = (i / mColumns) * mTileSize;
nsIntRegion tileRegion;
tileRegion.And(region, nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize())); // intersect with tile
if (tileRegion.IsEmpty())
continue;
tileRegion.MoveBy(-xPos, -yPos); // translate into tile local space
result &= mImages[i]->DirectUpdate(aSurf,
tileRegion,
aFrom + nsIntPoint(xPos, yPos));
}
mShaderType = mImages[0]->GetShaderProgramType();
mIsRGBFormat = mImages[0]->IsRGB();
mTextureState = Valid;
return result;
}
gfxASurface*
TiledTextureImage::BeginUpdate(nsIntRegion& aRegion)
{
NS_ASSERTION(!mInUpdate, "nested update");
mInUpdate = PR_TRUE;
if (mTextureState != Valid)
{
// if the texture hasn't been initialized yet, or something important
// changed, we need to recreate our backing surface and force the
// client to paint everything
mUpdateRegion = nsIntRect(nsIntPoint(0, 0), mSize);
} else {
mUpdateRegion = aRegion;
}
for (unsigned i = 0; i < mImages.Length(); i++) {
unsigned int xPos = (i % mColumns) * mTileSize;
unsigned int yPos = (i / mColumns) * mTileSize;
nsIntRegion imageRegion = nsIntRegion(nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize()));
// a single Image can handle this update request
if (imageRegion.Contains(aRegion)) {
// adjust for tile offset
aRegion.MoveBy(-xPos, -yPos);
// forward the actual call
nsRefPtr<gfxASurface> surface = mImages[i]->BeginUpdate(aRegion);
// caller expects container space
aRegion.MoveBy(xPos, yPos);
// we don't have a temp surface
mUpdateSurface = nsnull;
// remember which image to EndUpdate
mCurrentImage = i;
return surface.get();
}
}
// update covers multiple Images - create a temp surface to paint in
gfxASurface::gfxImageFormat format =
(GetContentType() == gfxASurface::CONTENT_COLOR) ?
gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32;
nsIntRect bounds = aRegion.GetBounds();
mUpdateSurface = gfxPlatform::GetPlatform()->
CreateOffscreenSurface(gfxIntSize(bounds.width, bounds.height), gfxASurface::ContentFromFormat(format));
mUpdateSurface->SetDeviceOffset(gfxPoint(-bounds.x, -bounds.y));
return mUpdateSurface;
}
void
TiledTextureImage::EndUpdate()
{
NS_ASSERTION(mInUpdate, "EndUpdate not in update");
if (!mUpdateSurface) { // update was to a single TextureImage
mImages[mCurrentImage]->EndUpdate();
mInUpdate = PR_FALSE;
mTextureState = Valid;
mShaderType = mImages[mCurrentImage]->GetShaderProgramType();
mIsRGBFormat = mImages[mCurrentImage]->IsRGB();
return;
}
// upload tiles from temp surface
for (unsigned i = 0; i < mImages.Length(); i++) {
unsigned int xPos = (i % mColumns) * mTileSize;
unsigned int yPos = (i / mColumns) * mTileSize;
nsIntRect imageRect = nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize());
nsIntRegion subregion;
subregion.And(mUpdateRegion, imageRect);
if (subregion.IsEmpty())
continue;
subregion.MoveBy(-xPos, -yPos); // Tile-local space
// copy tile from temp surface
gfxASurface* surf = mImages[i]->BeginUpdate(subregion);
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
gfxUtils::ClipToRegion(ctx, subregion);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->SetSource(mUpdateSurface, gfxPoint(-xPos, -yPos));
ctx->Paint();
mImages[i]->EndUpdate();
}
mUpdateSurface = nsnull;
mInUpdate = PR_FALSE;
mShaderType = mImages[0]->GetShaderProgramType();
mIsRGBFormat = mImages[0]->IsRGB();
}
void TiledTextureImage::BeginTileIteration()
{
mCurrentImage = 0;
}
PRBool TiledTextureImage::NextTile()
{
if (mCurrentImage + 1 < mImages.Length()) {
mCurrentImage++;
return PR_TRUE;
}
return PR_FALSE;
}
nsIntRect TiledTextureImage::GetTileRect()
{
nsIntRect rect = mImages[mCurrentImage]->GetTileRect();
unsigned int xPos = (mCurrentImage % mColumns) * mTileSize;
unsigned int yPos = (mCurrentImage / mColumns) * mTileSize;
rect.MoveTo(xPos, yPos);
return rect;
}
void
TiledTextureImage::BindTexture(GLenum aTextureUnit)
{
mImages[mCurrentImage]->BindTexture(aTextureUnit);
}
/*
* simple resize, just discards everything. we can be more clever just
* adding or discarding tiles, but do we want this?
*/
void TiledTextureImage::Resize(const nsIntSize& aSize)
{
if (mSize == aSize && mTextureState != Created) {
return;
}
mSize = aSize;
mImages.Clear();
// calculate rows and columns, rounding up
mColumns = (aSize.width + mTileSize - 1) / mTileSize;
mRows = (aSize.height + mTileSize - 1) / mTileSize;
for (unsigned int row = 0; row < mRows; row++) {
for (unsigned int col = 0; col < mColumns; col++) {
nsIntSize size( // use tilesize first, then the remainder
(col+1) * mTileSize > (unsigned int)aSize.width ? aSize.width % mTileSize : mTileSize,
(row+1) * mTileSize > (unsigned int)aSize.height ? aSize.height % mTileSize : mTileSize);
nsRefPtr<TextureImage> teximg =
mGL->TileGenFunc(size, mContentType, mUseNearestFilter);
mImages.AppendElement(teximg.forget());
}
}
mTextureState = Allocated;
}
PRBool
GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
{
@ -1245,6 +1442,9 @@ GLContext::BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect,
NS_ASSERTION(!aSrc->InUpdate(), "Source texture is in update!");
NS_ASSERTION(!aDst->InUpdate(), "Destination texture is in update!");
if (aSrcRect.IsEmpty() || aDstRect.IsEmpty())
return;
// only save/restore this stuff on Qualcomm Adreno, to work
// around an apparent bug
int savedFb = 0;
@ -1255,57 +1455,114 @@ GLContext::BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect,
fDisable(LOCAL_GL_SCISSOR_TEST);
fDisable(LOCAL_GL_BLEND);
SetBlitFramebufferForDestTexture(aDst->Texture());
// 2.0 means scale up by two
float blitScaleX = float(aDstRect.width) / float(aSrcRect.width);
float blitScaleY = float(aDstRect.height) / float(aSrcRect.height);
UseBlitProgram();
// We start iterating over all destination tiles
aDst->BeginTileIteration();
do {
// calculate portion of the tile that is going to be painted to
nsIntRect dstSubRect;
nsIntRect dstTextureRect = aDst->GetTileRect();
dstSubRect.IntersectRect(aDstRect, dstTextureRect);
nsIntSize srcSize = aSrc->GetSize();
nsIntSize dstSize = aDst->GetSize();
// this tile is not part of the destination rectangle aDstRect
if (dstSubRect.IsEmpty())
continue;
PushViewportRect(nsIntRect(0, 0, dstSize.width, dstSize.height));
// (*) transform the rect of this tile into the rectangle defined by aSrcRect...
nsIntRect dstInSrcRect(dstSubRect);
dstInSrcRect.MoveBy(-aDstRect.TopLeft());
// ...which might be of different size, hence scale accordingly
dstInSrcRect.ScaleRoundOut(1.0f / blitScaleX, 1.0f / blitScaleY);
dstInSrcRect.MoveBy(aSrcRect.TopLeft());
float dx0 = 2.0 * float(aDstRect.x) / float(dstSize.width) - 1.0;
float dy0 = 2.0 * float(aDstRect.y) / float(dstSize.height) - 1.0;
float dx1 = 2.0 * float(aDstRect.x + aDstRect.width) / float(dstSize.width) - 1.0;
float dy1 = 2.0 * float(aDstRect.y + aDstRect.height) / float(dstSize.height) - 1.0;
SetBlitFramebufferForDestTexture(aDst->GetTextureID());
UseBlitProgram();
RectTriangles rects;
if (aSrc->GetWrapMode() == LOCAL_GL_REPEAT) {
rects.addRect(/* dest rectangle */
dx0, dy0, dx1, dy1,
/* tex coords */
aSrcRect.x / float(srcSize.width),
aSrcRect.y / float(srcSize.height),
aSrcRect.XMost() / float(srcSize.width),
aSrcRect.YMost() / float(srcSize.height));
} else {
DecomposeIntoNoRepeatTriangles(aSrcRect, srcSize, rects);
aSrc->BeginTileIteration();
// now iterate over all tiles in the source Image...
do {
// calculate portion of the source tile that is in the source rect
nsIntRect srcSubRect;
nsIntRect srcTextureRect = aSrc->GetTileRect();
srcSubRect.IntersectRect(aSrcRect, srcTextureRect);
// now put the coords into the d[xy]0 .. d[xy]1 coordinate space
// from the 0..1 that it comes out of decompose
RectTriangles::vert_coord* v = (RectTriangles::vert_coord*)rects.vertexPointer();
for (int i = 0; i < rects.elements(); ++i) {
v[i].x = (v[i].x * (dx1 - dx0)) + dx0;
v[i].y = (v[i].y * (dy1 - dy0)) + dy0;
}
}
// this tile is not part of the source rect
if (srcSubRect.IsEmpty()) {
continue;
}
// calculate intersection of source rect with destination rect
srcSubRect.IntersectRect(srcSubRect, dstInSrcRect);
// this tile does not overlap the current destination tile
if (srcSubRect.IsEmpty()) {
continue;
}
// We now have the intersection of
// the current source tile
// and the desired source rectangle
// and the destination tile
// and the desired destination rectange
// in destination space.
// We need to transform this back into destination space, inverting the transform from (*)
nsIntRect srcSubInDstRect(srcSubRect);
srcSubInDstRect.MoveBy(-aSrcRect.TopLeft());
srcSubInDstRect.ScaleRoundOut(blitScaleX, blitScaleY);
srcSubInDstRect.MoveBy(aDstRect.TopLeft());
// we transform these rectangles to be relative to the current src and dst tiles, respectively
nsIntSize srcSize = srcTextureRect.Size();
nsIntSize dstSize = dstTextureRect.Size();
srcSubRect.MoveBy(-srcTextureRect.x, -srcTextureRect.y);
srcSubInDstRect.MoveBy(-dstTextureRect.x, -dstTextureRect.y);
fActiveTexture(LOCAL_GL_TEXTURE0);
fBindTexture(LOCAL_GL_TEXTURE_2D, aSrc->Texture());
float dx0 = 2.0 * float(srcSubInDstRect.x) / float(dstSize.width) - 1.0;
float dy0 = 2.0 * float(srcSubInDstRect.y) / float(dstSize.height) - 1.0;
float dx1 = 2.0 * float(srcSubInDstRect.x + srcSubInDstRect.width) / float(dstSize.width) - 1.0;
float dy1 = 2.0 * float(srcSubInDstRect.y + srcSubInDstRect.height) / float(dstSize.height) - 1.0;
PushViewportRect(nsIntRect(0, 0, dstSize.width, dstSize.height));
fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
RectTriangles rects;
if (aSrc->GetWrapMode() == LOCAL_GL_REPEAT) {
rects.addRect(/* dest rectangle */
dx0, dy0, dx1, dy1,
/* tex coords */
srcSubRect.x / float(srcSize.width),
srcSubRect.y / float(srcSize.height),
srcSubRect.XMost() / float(srcSize.width),
srcSubRect.YMost() / float(srcSize.height));
} else {
DecomposeIntoNoRepeatTriangles(srcSubRect, srcSize, rects);
fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.vertexPointer());
fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.texCoordPointer());
// now put the coords into the d[xy]0 .. d[xy]1 coordinate space
// from the 0..1 that it comes out of decompose
RectTriangles::vert_coord* v = (RectTriangles::vert_coord*)rects.vertexPointer();
fEnableVertexAttribArray(0);
fEnableVertexAttribArray(1);
for (unsigned int i = 0; i < rects.elements(); ++i) {
v[i].x = (v[i].x * (dx1 - dx0)) + dx0;
v[i].y = (v[i].y * (dy1 - dy0)) + dy0;
}
}
fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
TextureImage::ScopedBindTexture texBind(aSrc, LOCAL_GL_TEXTURE0);
fDisableVertexAttribArray(0);
fDisableVertexAttribArray(1);
fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.vertexPointer());
fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.texCoordPointer());
fEnableVertexAttribArray(0);
fEnableVertexAttribArray(1);
fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
fDisableVertexAttribArray(0);
fDisableVertexAttribArray(1);
PopViewportRect();
} while (aSrc->NextTile());
} while (aDst->NextTile());
fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, NULL);
fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, NULL);
@ -1325,8 +1582,6 @@ GLContext::BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect,
fEnable(LOCAL_GL_SCISSOR_TEST);
fEnable(LOCAL_GL_BLEND);
PopViewportRect();
}
static unsigned int

Просмотреть файл

@ -75,8 +75,12 @@ typedef char realGLboolean;
#include "GLContextSymbols.h"
namespace mozilla {
namespace gl {
namespace layers {
class LayerManagerOGL;
class ColorTextureLayerProgram;
};
namespace gl {
class GLContext;
class LibrarySymbolLoader
@ -156,6 +160,13 @@ class TextureImage
{
NS_INLINE_DECL_REFCOUNTING(TextureImage)
public:
enum TextureState
{
Created, // Texture created, but has not had glTexImage called to initialize it.
Allocated, // Texture memory exists, but contents are invalid.
Valid // Texture fully ready to use.
};
typedef gfxASurface::gfxContentType ContentType;
virtual ~TextureImage() {}
@ -191,6 +202,22 @@ public:
*/
virtual void EndUpdate() = 0;
/**
* The Image may contain several textures for different regions (tiles).
* These functions iterate over each sub texture image tile.
*/
virtual void BeginTileIteration() {
};
virtual PRBool NextTile() {
return PR_FALSE;
};
virtual nsIntRect GetTileRect() {
return nsIntRect(nsIntPoint(0,0), mSize);
};
virtual GLuint GetTextureID() = 0;
/**
* Set this TextureImage's size, and ensure a texture has been
* allocated. Must not be called between BeginUpdate and EndUpdate.
@ -206,7 +233,12 @@ public:
EndUpdate();
}
virtual bool DirectUpdate(gfxASurface *aSurf, const nsIntRegion& aRegion) =0;
/**
* aSurf - the source surface to update from
* aRegion - the region in this image to update
* aFrom - offset in the source to update from
*/
virtual bool DirectUpdate(gfxASurface *aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0)) = 0;
virtual void BindTexture(GLenum aTextureUnit) = 0;
virtual void ReleaseTexture() {};
@ -233,16 +265,6 @@ public:
TextureImage *mTexture;
};
/**
* Return this TextureImage's texture ID for use with GL APIs.
* Callers are responsible for properly binding the texture etc.
*
* The texture is only texture complete after either Resize
* or a matching pair of BeginUpdate/EndUpdate have been called.
* Otherwise, a texture ID may be returned, but the texture
* may not be texture complete.
*/
GLuint Texture() { return mTexture; }
/**
* Returns the shader program type that should be used to render
@ -279,17 +301,15 @@ protected:
* TextureImage from GLContext::CreateTextureImage(). That is,
* clients must not be given partially-constructed TextureImages.
*/
TextureImage(GLuint aTexture, const nsIntSize& aSize,
TextureImage(const nsIntSize& aSize,
GLenum aWrapMode, ContentType aContentType,
PRBool aIsRGB = PR_FALSE)
: mTexture(aTexture)
, mSize(aSize)
: mSize(aSize)
, mWrapMode(aWrapMode)
, mContentType(aContentType)
, mIsRGBFormat(aIsRGB)
{}
GLuint mTexture;
nsIntSize mSize;
GLenum mWrapMode;
ContentType mContentType;
@ -318,25 +338,19 @@ public:
GLenum aWrapMode,
ContentType aContentType,
GLContext* aContext)
: TextureImage(aTexture, aSize, aWrapMode, aContentType)
: TextureImage(aSize, aWrapMode, aContentType)
, mTexture(aTexture)
, mTextureState(Created)
, mGLContext(aContext)
, mUpdateOffset(0, 0)
{}
enum TextureState
{
Created, // Texture created, but has not had glTexImage called to initialize it.
Allocated, // Texture memory exists, but contents are invalid.
Valid // Texture fully ready to use.
};
virtual void BindTexture(GLenum aTextureUnit);
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
virtual void EndUpdate();
virtual bool DirectUpdate(gfxASurface *aSurf, const nsIntRegion& aRegion);
virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0));
virtual GLuint GetTextureID() { return mTexture; };
// Returns a surface to draw into
virtual already_AddRefed<gfxASurface>
GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt);
@ -354,6 +368,7 @@ public:
virtual void Resize(const nsIntSize& aSize);
protected:
GLuint mTexture;
TextureState mTextureState;
GLContext* mGLContext;
nsRefPtr<gfxASurface> mUpdateSurface;
@ -363,6 +378,47 @@ protected:
nsIntPoint mUpdateOffset;
};
/**
* A container class that complements many sub TextureImages into a big TextureImage.
* Aims to behave just like the real thing.
*/
class TiledTextureImage
: public TextureImage
{
public:
TiledTextureImage(GLContext* aGL, nsIntSize aSize,
TextureImage::ContentType aContentType, PRBool aUseNearestFilter = PR_FALSE);
~TiledTextureImage();
void DumpDiv();
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
virtual void EndUpdate();
virtual void Resize(const nsIntSize& aSize);
virtual void BeginTileIteration();
virtual PRBool NextTile();
virtual nsIntRect GetTileRect();
virtual GLuint GetTextureID() {
return mImages[mCurrentImage]->GetTextureID();
};
virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0));
virtual PRBool InUpdate() const { return mInUpdate; };
virtual void BindTexture(GLenum);
protected:
unsigned int mCurrentImage;
nsTArray< nsRefPtr<TextureImage> > mImages;
bool mInUpdate;
nsIntSize mSize;
unsigned int mTileSize;
unsigned int mRows, mColumns;
GLContext* mGL;
PRBool mUseNearestFilter;
// A temporary surface to faciliate cross-tile updates.
nsRefPtr<gfxASurface> mUpdateSurface;
// The region of update requested
nsIntRegion mUpdateRegion;
TextureState mTextureState;
};
struct THEBES_API ContextFormat
{
static const ContextFormat BasicRGBA32Format;
@ -706,6 +762,21 @@ public:
GLenum aWrapMode,
PRBool aUseNearestFilter=PR_FALSE);
/**
* In EGL we want to use Tiled Texture Images, which we return
* from CreateTextureImage above.
* Inside TiledTextureImage we need to create actual images and to
* prevent infinite recursion we need to differentiate the two
* functions.
**/
virtual already_AddRefed<TextureImage>
TileGenFunc(const nsIntSize& aSize,
TextureImage::ContentType aContentType,
PRBool aUseNearestFilter = PR_FALSE)
{
return nsnull;
};
/**
* Read the image data contained in aTexture, and return it as an ImageSurface.
* If GL_RGBA is given as the format, a ImageFormatARGB32 surface is returned.

Просмотреть файл

@ -821,13 +821,18 @@ public:
{
return sEGLLibrary.fSwapBuffers(EGL_DISPLAY(), mSurface);
}
// GLContext interface - returns Tiled Texture Image in our case
virtual already_AddRefed<TextureImage>
CreateTextureImage(const nsIntSize& aSize,
TextureImage::ContentType aContentType,
GLenum aWrapMode,
PRBool aUseNearestFilter=PR_FALSE);
// a function to generate Tiles for Tiled Texture Image
virtual already_AddRefed<TextureImage>
TileGenFunc(const nsIntSize& aSize,
TextureImage::ContentType aContentType,
PRBool aUseNearestFilter = PR_FALSE);
// hold a reference to the given surface
// for the lifetime of this context.
void HoldSurface(gfxASurface *aSurf) {
@ -1108,7 +1113,8 @@ public:
GLenum aWrapMode,
ContentType aContentType,
GLContext* aContext)
: TextureImage(aTexture, aSize, aWrapMode, aContentType)
: TextureImage(aSize, aWrapMode, aContentType)
, mTexture(aTexture)
, mGLContext(aContext)
, mUpdateFormat(gfxASurface::ImageFormatUnknown)
, mSurface(nsnull)
@ -1302,10 +1308,10 @@ public:
return; // mTexture is bound
}
virtual bool DirectUpdate(gfxASurface *aSurf, const nsIntRegion& aRegion)
virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
{
nsIntRect bounds = aRegion.GetBounds();
nsIntRegion region;
if (!mCreated) {
bounds = nsIntRect(0, 0, mSize.width, mSize.height);
@ -1319,7 +1325,7 @@ public:
if (mUpdateSurface) {
nsRefPtr<gfxContext> ctx = new gfxContext(mUpdateSurface);
gfxUtils::ClipToRegion(ctx, aRegion);
ctx->SetSource(aSurf);
ctx->SetSource(aSurf, gfxPoint(-aFrom.x, -aFrom.y));
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->Paint();
mUpdateSurface = nsnull;
@ -1331,7 +1337,7 @@ public:
region,
mTexture,
!mCreated,
bounds.TopLeft(),
bounds.TopLeft() + aFrom,
PR_FALSE);
}
@ -1342,10 +1348,14 @@ public:
virtual void BindTexture(GLenum aTextureUnit)
{
mGLContext->fActiveTexture(aTextureUnit);
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, Texture());
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
}
virtual GLuint GetTextureID() {
return mTexture;
};
virtual PRBool InUpdate() const { return !!mUpdateSurface; }
virtual void Resize(const nsIntSize& aSize)
@ -1576,6 +1586,7 @@ protected:
nsRefPtr<gfxASurface> mUpdateSurface;
EGLSurface mSurface;
EGLConfig mConfig;
GLuint mTexture;
EGLImageKHR mImageKHR;
PRPackedBool mCreated;
@ -1588,6 +1599,15 @@ GLContextEGL::CreateTextureImage(const nsIntSize& aSize,
TextureImage::ContentType aContentType,
GLenum aWrapMode,
PRBool aUseNearestFilter)
{
nsRefPtr<TextureImage> t = new gl::TiledTextureImage(this, aSize, aContentType);
return t.forget();
};
already_AddRefed<TextureImage>
GLContextEGL::TileGenFunc(const nsIntSize& aSize,
TextureImage::ContentType aContentType,
PRBool aUseNearestFilter)
{
MakeCurrent();
@ -1598,13 +1618,13 @@ GLContextEGL::CreateTextureImage(const nsIntSize& aSize,
fBindTexture(LOCAL_GL_TEXTURE_2D, texture);
nsRefPtr<TextureImageEGL> teximage =
new TextureImageEGL(texture, aSize, aWrapMode, aContentType, this);
new TextureImageEGL(texture, aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, this);
GLint texfilter = aUseNearestFilter ? 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);
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
return teximage.forget();
}

Просмотреть файл

@ -552,11 +552,12 @@ public:
mInUpdate = PR_FALSE;
}
virtual bool DirectUpdate(gfxASurface* aSurface, const nsIntRegion& aRegion)
virtual bool DirectUpdate(gfxASurface* aSurface, const nsIntRegion& aRegion, const nsIntPoint& aFrom)
{
nsRefPtr<gfxContext> ctx = new gfxContext(mUpdateSurface);
gfxUtils::ClipToRegion(ctx, aRegion);
ctx->SetSource(aSurface);
ctx->SetSource(aSurface, aFrom);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->Paint();
return true;
@ -565,7 +566,7 @@ public:
virtual void BindTexture(GLenum aTextureUnit)
{
mGLContext->fActiveTexture(aTextureUnit);
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, Texture());
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
sGLXLibrary.BindTexImage(mPixmap);
mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
}
@ -583,6 +584,10 @@ public:
virtual PRBool InUpdate() const { return mInUpdate; }
virtual GLuint GetTextureID() {
return mTexture;
};
private:
TextureImageGLX(GLuint aTexture,
const nsIntSize& aSize,
@ -591,11 +596,12 @@ private:
GLContext* aContext,
gfxASurface* aSurface,
GLXPixmap aPixmap)
: TextureImage(aTexture, aSize, aWrapMode, aContentType)
: TextureImage(aSize, aWrapMode, aContentType)
, mGLContext(aContext)
, mUpdateSurface(aSurface)
, mPixmap(aPixmap)
, mInUpdate(PR_FALSE)
, mTexture(aTexture)
{
if (aSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
mShaderType = gl::RGBALayerProgramType;
@ -608,6 +614,7 @@ private:
nsRefPtr<gfxASurface> mUpdateSurface;
GLXPixmap mPixmap;
PRPackedBool mInUpdate;
GLuint mTexture;
};
already_AddRefed<TextureImage>

Просмотреть файл

@ -2073,8 +2073,7 @@ nsChildView::DrawOver(LayerManager* aManager, nsIntRect aRect)
float bottomX = aRect.x + aRect.width;
float bottomY = aRect.y + aRect.height;
manager->gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
manager->gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mResizerImage->Texture());
TextureImage::ScopedBindTexture texBind(mResizerImage, LOCAL_GL_TEXTURE0);
ColorTextureLayerProgram *program =
manager->GetColorTextureLayerProgram(mResizerImage->GetShaderProgramType());