Bug 959154 - Part 7: Moz2Dify GLTextureImage::BeginUpdate/EndUpdate. r=nical

This commit is contained in:
Andreas Pehrson 2014-02-13 19:00:01 +01:00
parent ce51738acb
commit 3b57ddea97
4 changed files with 95 additions and 111 deletions

View File

@ -119,10 +119,10 @@ BasicTextureImage::~BasicTextureImage()
}
}
gfxASurface*
gfx::DrawTarget*
BasicTextureImage::BeginUpdate(nsIntRegion& aRegion)
{
NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
NS_ASSERTION(!mUpdateDrawTarget, "BeginUpdate() without EndUpdate()?");
// determine the region the client will need to repaint
if (CanUploadSubTextures(mGLContext)) {
@ -139,20 +139,13 @@ BasicTextureImage::BeginUpdate(nsIntRegion& aRegion)
return nullptr;
}
ImageFormat format =
gfx::SurfaceFormat format =
(GetContentType() == gfxContentType::COLOR) ?
gfxImageFormat::RGB24 : gfxImageFormat::ARGB32;
mUpdateSurface =
GetSurfaceForUpdate(gfxIntSize(rgnSize.width, rgnSize.height), format);
gfx::SurfaceFormat::B8G8R8X8 : gfx::SurfaceFormat::B8G8R8A8;
mUpdateDrawTarget =
GetDrawTargetForUpdate(gfx::IntSize(rgnSize.width, rgnSize.height), format);
if (!mUpdateSurface || mUpdateSurface->CairoStatus()) {
mUpdateSurface = nullptr;
return nullptr;
}
mUpdateSurface->SetDeviceOffset(gfxPoint(-rgnSize.x, -rgnSize.y));
return mUpdateSurface;
return mUpdateDrawTarget;
}
void
@ -168,19 +161,18 @@ BasicTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
void
BasicTextureImage::EndUpdate()
{
NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
NS_ASSERTION(!!mUpdateDrawTarget, "EndUpdate() without BeginUpdate()?");
// FIXME: this is the slow boat. Make me fast (with GLXPixmap?).
// Undo the device offset that BeginUpdate set; doesn't much matter for us here,
// but important if we ever do anything directly with the surface.
mUpdateSurface->SetDeviceOffset(gfxPoint(0, 0));
RefPtr<gfx::SourceSurface> updateSnapshot = mUpdateDrawTarget->Snapshot();
RefPtr<gfx::DataSourceSurface> updateData = updateSnapshot->GetDataSurface();
bool relative = FinishedSurfaceUpdate();
mTextureFormat =
DeprecatedUploadSurfaceToTexture(mGLContext,
mUpdateSurface,
UploadSurfaceToTexture(mGLContext,
updateData,
mUpdateRegion,
mTexture,
mTextureState == Created,
@ -188,7 +180,7 @@ BasicTextureImage::EndUpdate()
relative);
FinishedSurfaceUpload();
mUpdateSurface = nullptr;
mUpdateDrawTarget = nullptr;
mTextureState = Valid;
}
@ -200,12 +192,10 @@ BasicTextureImage::BindTexture(GLenum aTextureUnit)
mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
}
already_AddRefed<gfxASurface>
BasicTextureImage::GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt)
TemporaryRef<gfx::DrawTarget>
BasicTextureImage::GetDrawTargetForUpdate(const gfx::IntSize& aSize, gfx::SurfaceFormat aFmt)
{
return gfxPlatform::GetPlatform()->
CreateOffscreenSurface(aSize.ToIntSize(),
gfxASurface::ContentFromFormat(aFmt));
return gfx::Factory::CreateDrawTarget(gfx::BackendType::CAIRO, aSize, aFmt);
}
bool
@ -246,7 +236,7 @@ BasicTextureImage::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion
void
BasicTextureImage::Resize(const gfx::IntSize& aSize)
{
NS_ASSERTION(!mUpdateSurface, "Resize() while in update?");
NS_ASSERTION(!mUpdateDrawTarget, "Resize() while in update?");
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
@ -451,7 +441,7 @@ TiledTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
aForRegion = newRegion;
}
gfxASurface*
gfx::DrawTarget*
TiledTextureImage::BeginUpdate(nsIntRegion& aRegion)
{
NS_ASSERTION(!mInUpdate, "nested update");
@ -482,18 +472,14 @@ TiledTextureImage::BeginUpdate(nsIntRegion& aRegion)
// adjust for tile offset
aRegion.MoveBy(-xPos, -yPos);
// forward the actual call
nsRefPtr<gfxASurface> surface = mImages[i]->BeginUpdate(aRegion);
RefPtr<gfx::DrawTarget> drawTarget = mImages[i]->BeginUpdate(aRegion);
// caller expects container space
aRegion.MoveBy(xPos, yPos);
// Correct the device offset
gfxPoint offset = surface->GetDeviceOffset();
surface->SetDeviceOffset(gfxPoint(offset.x - xPos,
offset.y - yPos));
// we don't have a temp surface
mUpdateSurface = nullptr;
mUpdateDrawTarget = nullptr;
// remember which image to EndUpdate
mCurrentImage = i;
return surface.get();
return drawTarget.get();
}
}
@ -504,22 +490,21 @@ TiledTextureImage::BeginUpdate(nsIntRegion& aRegion)
bounds = aRegion.GetBounds();
// update covers multiple Images - create a temp surface to paint in
gfxImageFormat format =
gfx::SurfaceFormat format =
(GetContentType() == gfxContentType::COLOR) ?
gfxImageFormat::RGB24 : gfxImageFormat::ARGB32;
mUpdateSurface = gfxPlatform::GetPlatform()->
CreateOffscreenSurface(bounds.Size().ToIntSize(),
gfxASurface::ContentFromFormat(format));
mUpdateSurface->SetDeviceOffset(gfxPoint(-bounds.x, -bounds.y));
gfx::SurfaceFormat::B8G8R8X8: gfx::SurfaceFormat::B8G8R8A8;
mUpdateDrawTarget = gfx::Factory::CreateDrawTarget(gfx::BackendType::CAIRO,
bounds.Size().ToIntSize(),
format);
return mUpdateSurface;
return mUpdateDrawTarget;;
}
void
TiledTextureImage::EndUpdate()
{
NS_ASSERTION(mInUpdate, "EndUpdate not in update");
if (!mUpdateSurface) { // update was to a single TextureImage
if (!mUpdateDrawTarget) { // update was to a single TextureImage
mImages[mCurrentImage]->EndUpdate();
mInUpdate = false;
mTextureState = Valid;
@ -527,6 +512,13 @@ TiledTextureImage::EndUpdate()
return;
}
RefPtr<gfx::SourceSurface> updateSnapshot = mUpdateDrawTarget->Snapshot();
RefPtr<gfx::DataSourceSurface> updateData = updateSnapshot->GetDataSurface();
nsRefPtr<gfxASurface> updateSurface = new gfxImageSurface(updateData->GetData(),
gfx::ThebesIntSize(updateData->GetSize()),
updateData->Stride(),
gfx::SurfaceFormatToImageFormat(updateData->GetFormat()));
// upload tiles from temp surface
for (unsigned i = 0; i < mImages.Length(); i++) {
int xPos = (i % mColumns) * mTileSize;
@ -539,17 +531,17 @@ TiledTextureImage::EndUpdate()
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);
// copy tile from temp target
gfx::DrawTarget* drawTarget = mImages[i]->BeginUpdate(subregion);
nsRefPtr<gfxContext> ctx = new gfxContext(drawTarget);
gfxUtils::ClipToRegion(ctx, subregion);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->SetSource(mUpdateSurface, gfxPoint(-xPos, -yPos));
ctx->SetSource(updateSurface, gfxPoint(-xPos, -yPos));
ctx->Paint();
mImages[i]->EndUpdate();
}
mUpdateSurface = nullptr;
mUpdateDrawTarget = nullptr;
mInUpdate = false;
mTextureFormat = mImages[0]->GetTextureFormat();
mTextureState = Valid;

View File

@ -13,12 +13,14 @@
#include "GLContextTypes.h"
#include "GraphicsFilter.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/RefPtr.h"
class gfxASurface;
namespace mozilla {
namespace gfx {
class DataSourceSurface;
class DrawTarget;
}
}
@ -100,7 +102,7 @@ public:
* inconsistent state. Unsuccessful BeginUpdate()s must not be
* followed by EndUpdate().
*/
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion) = 0;
virtual gfx::DrawTarget* BeginUpdate(nsIntRegion& aRegion) = 0;
/**
* Retrieves the region that will require updating, given a
* region that needs to be updated. This can be used for
@ -278,14 +280,13 @@ public:
virtual void BindTexture(GLenum aTextureUnit);
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
virtual gfx::DrawTarget* BeginUpdate(nsIntRegion& aRegion);
virtual void GetUpdateRegion(nsIntRegion& aForRegion);
virtual void EndUpdate();
virtual bool DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom = gfx::IntPoint(0,0));
virtual GLuint GetTextureID() { return mTexture; }
// Returns a surface to draw into
virtual already_AddRefed<gfxASurface>
GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt);
virtual TemporaryRef<gfx::DrawTarget>
GetDrawTargetForUpdate(const gfx::IntSize& aSize, gfx::SurfaceFormat aFmt);
virtual void MarkValid() { mTextureState = Valid; }
@ -297,7 +298,7 @@ public:
// Call after surface data has been uploaded to a texture.
virtual void FinishedSurfaceUpload();
virtual bool InUpdate() const { return !!mUpdateSurface; }
virtual bool InUpdate() const { return !!mUpdateDrawTarget; }
virtual void Resize(const gfx::IntSize& aSize);
@ -305,7 +306,7 @@ protected:
GLuint mTexture;
TextureState mTextureState;
nsRefPtr<GLContext> mGLContext;
nsRefPtr<gfxASurface> mUpdateSurface;
RefPtr<gfx::DrawTarget> mUpdateDrawTarget;
nsIntRegion mUpdateRegion;
// The offset into the update surface at which the update rect is located.
@ -328,7 +329,7 @@ public:
TextureImage::ImageFormat aImageFormat = gfxImageFormat::Unknown);
~TiledTextureImage();
void DumpDiv();
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
virtual gfx::DrawTarget* BeginUpdate(nsIntRegion& aRegion);
virtual void GetUpdateRegion(nsIntRegion& aForRegion);
virtual void EndUpdate();
virtual void Resize(const gfx::IntSize& aSize);
@ -357,8 +358,8 @@ protected:
unsigned int mTileSize;
unsigned int mRows, mColumns;
GLContext* mGL;
// A temporary surface to faciliate cross-tile updates.
nsRefPtr<gfxASurface> mUpdateSurface;
// A temporary draw target to faciliate cross-tile updates.
RefPtr<gfx::DrawTarget> mUpdateDrawTarget;
// The region of update requested
nsIntRegion mUpdateRegion;
TextureState mTextureState;

View File

@ -15,35 +15,34 @@ namespace mozilla {
namespace gl {
static GLenum
GLFormatForImage(gfxImageFormat aFormat)
GLFormatForImage(gfx::SurfaceFormat aFormat)
{
switch (aFormat) {
case gfxImageFormat::ARGB32:
case gfxImageFormat::RGB24:
// Thebes only supports RGBX, not packed RGB.
case gfx::SurfaceFormat::B8G8R8A8:
case gfx::SurfaceFormat::B8G8R8X8:
return LOCAL_GL_RGBA;
case gfxImageFormat::RGB16_565:
case gfx::SurfaceFormat::R5G6B5:
return LOCAL_GL_RGB;
case gfxImageFormat::A8:
case gfx::SurfaceFormat::A8:
return LOCAL_GL_LUMINANCE;
default:
NS_WARNING("Unknown GL format for Image format");
NS_WARNING("Unknown GL format for Surface format");
}
return 0;
}
static GLenum
GLTypeForImage(gfxImageFormat aFormat)
GLTypeForImage(gfx::SurfaceFormat aFormat)
{
switch (aFormat) {
case gfxImageFormat::ARGB32:
case gfxImageFormat::RGB24:
case gfxImageFormat::A8:
case gfx::SurfaceFormat::B8G8R8A8:
case gfx::SurfaceFormat::B8G8R8X8:
case gfx::SurfaceFormat::A8:
return LOCAL_GL_UNSIGNED_BYTE;
case gfxImageFormat::RGB16_565:
case gfx::SurfaceFormat::R5G6B5:
return LOCAL_GL_UNSIGNED_SHORT_5_6_5;
default:
NS_WARNING("Unknown GL format for Image format");
NS_WARNING("Unknown GL format for Surface format");
}
return 0;
}
@ -58,7 +57,7 @@ TextureImageEGL::TextureImageEGL(GLuint aTexture,
TextureImage::ImageFormat aImageFormat)
: TextureImage(aSize, aWrapMode, aContentType, aFlags)
, mGLContext(aContext)
, mUpdateFormat(aImageFormat)
, mUpdateFormat(gfx::ImageFormatToSurfaceFormat(aImageFormat))
, mEGLImage(nullptr)
, mTexture(aTexture)
, mSurface(nullptr)
@ -66,16 +65,14 @@ TextureImageEGL::TextureImageEGL(GLuint aTexture,
, mTextureState(aTextureState)
, mBound(false)
{
if (mUpdateFormat == gfxImageFormat::Unknown) {
mUpdateFormat = gfxPlatform::GetPlatform()->OptimalFormatForContent(GetContentType());
if (mUpdateFormat == gfx::SurfaceFormat::UNKNOWN) {
mUpdateFormat = gfx::ImageFormatToSurfaceFormat(
gfxPlatform::GetPlatform()->OptimalFormatForContent(GetContentType()));
}
if (mUpdateFormat == gfxImageFormat::RGB16_565) {
if (mUpdateFormat == gfx::SurfaceFormat::R5G6B5) {
mTextureFormat = gfx::SurfaceFormat::R8G8B8X8;
} else if (mUpdateFormat == gfxImageFormat::RGB24) {
// RGB24 means really RGBX for Thebes, which means we have to
// use the right shader and ignore the uninitialized alpha
// value.
} else if (mUpdateFormat == gfx::SurfaceFormat::B8G8R8X8) {
mTextureFormat = gfx::SurfaceFormat::B8G8R8X8;
} else {
mTextureFormat = gfx::SurfaceFormat::B8G8R8A8;
@ -114,10 +111,10 @@ TextureImageEGL::GetUpdateRegion(nsIntRegion& aForRegion)
aForRegion = nsIntRegion(aForRegion.GetBounds());
}
gfxASurface*
gfx::DrawTarget*
TextureImageEGL::BeginUpdate(nsIntRegion& aRegion)
{
NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
NS_ASSERTION(!mUpdateDrawTarget, "BeginUpdate() without EndUpdate()?");
// determine the region the client will need to repaint
GetUpdateRegion(aRegion);
@ -131,19 +128,17 @@ TextureImageEGL::BeginUpdate(nsIntRegion& aRegion)
//printf_stderr("creating image surface %dx%d format %d\n", mUpdateRect.width, mUpdateRect.height, mUpdateFormat);
mUpdateSurface =
new gfxImageSurface(gfxIntSize(mUpdateRect.width, mUpdateRect.height),
mUpdateFormat);
mUpdateDrawTarget = gfx::Factory::CreateDrawTarget(gfx::BackendType::CAIRO,
gfx::IntSize(mUpdateRect.width, mUpdateRect.height),
mUpdateFormat);
mUpdateSurface->SetDeviceOffset(gfxPoint(-mUpdateRect.x, -mUpdateRect.y));
return mUpdateSurface;
return mUpdateDrawTarget;
}
void
TextureImageEGL::EndUpdate()
{
NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
NS_ASSERTION(!!mUpdateDrawTarget, "EndUpdate() without BeginUpdate()?");
//printf_stderr("EndUpdate: slow path");
@ -151,19 +146,15 @@ TextureImageEGL::EndUpdate()
// a fast mapping between our cairo target surface and the GL
// texture, so we have to upload data.
// Undo the device offset that BeginUpdate set; doesn't much
// matter for us here, but important if we ever do anything
// directly with the surface.
mUpdateSurface->SetDeviceOffset(gfxPoint(0, 0));
RefPtr<gfx::SourceSurface> updateSurface = nullptr;
RefPtr<gfx::DataSourceSurface> uploadImage = nullptr;
gfx::IntSize updateSize(mUpdateRect.width, mUpdateRect.height);
nsRefPtr<gfxImageSurface> uploadImage = nullptr;
gfxIntSize updateSize(mUpdateRect.width, mUpdateRect.height);
NS_ASSERTION(mUpdateDrawTarget->GetSize() == updateSize,
"Upload image is the wrong size!");
NS_ASSERTION(mUpdateSurface->GetType() == gfxSurfaceType::Image &&
mUpdateSurface->GetSize() == updateSize,
"Upload image isn't an image surface when one is expected, or is wrong size!");
uploadImage = static_cast<gfxImageSurface*>(mUpdateSurface.get());
updateSurface = mUpdateDrawTarget->Snapshot();
uploadImage = updateSurface->GetDataSurface();
if (!uploadImage) {
return;
@ -183,9 +174,9 @@ TextureImageEGL::EndUpdate()
mUpdateRect.width,
mUpdateRect.height,
0,
GLFormatForImage(uploadImage->Format()),
GLTypeForImage(uploadImage->Format()),
uploadImage->Data());
GLFormatForImage(uploadImage->GetFormat()),
GLTypeForImage(uploadImage->GetFormat()),
uploadImage->GetData());
} else {
mGLContext->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
0,
@ -193,12 +184,12 @@ TextureImageEGL::EndUpdate()
mUpdateRect.y,
mUpdateRect.width,
mUpdateRect.height,
GLFormatForImage(uploadImage->Format()),
GLTypeForImage(uploadImage->Format()),
uploadImage->Data());
GLFormatForImage(uploadImage->GetFormat()),
GLTypeForImage(uploadImage->GetFormat()),
uploadImage->GetData());
}
mUpdateSurface = nullptr;
mUpdateDrawTarget = nullptr;
mTextureState = Valid;
return; // mTexture is bound
}
@ -245,7 +236,7 @@ TextureImageEGL::BindTexture(GLenum aTextureUnit)
void
TextureImageEGL::Resize(const gfx::IntSize& aSize)
{
NS_ASSERTION(!mUpdateSurface, "Resize() while in update?");
NS_ASSERTION(!mUpdateDrawTarget, "Resize() while in update?");
if (mSize == aSize && mTextureState != Created)
return;

View File

@ -28,7 +28,7 @@ public:
virtual void GetUpdateRegion(nsIntRegion& aForRegion);
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
virtual gfx::DrawTarget* BeginUpdate(nsIntRegion& aRegion);
virtual void EndUpdate();
@ -45,7 +45,7 @@ public:
return mTexture;
};
virtual bool InUpdate() const { return !!mUpdateSurface; }
virtual bool InUpdate() const { return !!mUpdateDrawTarget; }
virtual void Resize(const gfx::IntSize& aSize);
@ -66,8 +66,8 @@ protected:
GLContext* mGLContext;
nsIntRect mUpdateRect;
ImageFormat mUpdateFormat;
nsRefPtr<gfxASurface> mUpdateSurface;
gfx::SurfaceFormat mUpdateFormat;
RefPtr<gfx::DrawTarget> mUpdateDrawTarget;
EGLImage mEGLImage;
GLuint mTexture;
EGLSurface mSurface;