From 8ff0e949d1b2e2674b92c5cc448ae6de72f0e500 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Thu, 16 Dec 2010 23:29:23 -0800 Subject: [PATCH] Bug 604101 - Part 4 - Use UploadSurfaceToTexture in TextureImage. r=joe a=blocking2.0 --- gfx/layers/opengl/CanvasLayerOGL.cpp | 3 +- gfx/layers/opengl/ImageLayerOGL.cpp | 3 +- gfx/layers/opengl/ThebesLayerOGL.cpp | 11 ++-- gfx/thebes/GLContext.cpp | 91 +++++----------------------- gfx/thebes/GLContext.h | 41 +++++++------ gfx/thebes/GLContextProviderCGL.mm | 39 ++++-------- gfx/thebes/GLContextProviderEGL.cpp | 3 + gfx/thebes/GLContextProviderGLX.cpp | 16 ----- gfx/thebes/GLContextProviderWGL.cpp | 18 ------ 9 files changed, 60 insertions(+), 165 deletions(-) diff --git a/gfx/layers/opengl/CanvasLayerOGL.cpp b/gfx/layers/opengl/CanvasLayerOGL.cpp index fb72c6c0d5b9..86f370b094f0 100644 --- a/gfx/layers/opengl/CanvasLayerOGL.cpp +++ b/gfx/layers/opengl/CanvasLayerOGL.cpp @@ -331,8 +331,7 @@ ShadowCanvasLayerOGL::RenderLayer(int aPreviousFrameBuffer, gl()->fActiveTexture(LOCAL_GL_TEXTURE0); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexImage->Texture()); ColorTextureLayerProgram *program = - mOGLManager->GetBasicLayerProgram(CanUseOpaqueSurface(), - mTexImage->IsRGB()); + mOGLManager->GetColorTextureLayerProgram(mTexImage->GetShaderProgramType()); ApplyFilter(mFilter); diff --git a/gfx/layers/opengl/ImageLayerOGL.cpp b/gfx/layers/opengl/ImageLayerOGL.cpp index 36619f824728..8f291151d967 100644 --- a/gfx/layers/opengl/ImageLayerOGL.cpp +++ b/gfx/layers/opengl/ImageLayerOGL.cpp @@ -781,8 +781,7 @@ ShadowImageLayerOGL::RenderLayer(int aPreviousFrameBuffer, gl()->fActiveTexture(LOCAL_GL_TEXTURE0); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexImage->Texture()); ColorTextureLayerProgram *program = - mOGLManager->GetBasicLayerProgram(CanUseOpaqueSurface(), - mTexImage->IsRGB()); + mOGLManager->GetColorTextureLayerProgram(mTexImage->GetShaderProgramType()); ApplyFilter(mFilter); diff --git a/gfx/layers/opengl/ThebesLayerOGL.cpp b/gfx/layers/opengl/ThebesLayerOGL.cpp index c8fed44897d4..5c6e5b55573d 100644 --- a/gfx/layers/opengl/ThebesLayerOGL.cpp +++ b/gfx/layers/opengl/ThebesLayerOGL.cpp @@ -181,18 +181,17 @@ ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset, if (!mTexImage) return; - // Note BGR: Cairo's image surfaces are always in what - // OpenGL and our shaders consider BGR format. - ColorTextureLayerProgram *program = - aManager->GetBasicLayerProgram(mLayer->CanUseOpaqueSurface(), - mTexImage->IsRGB()); - gl()->fActiveTexture(LOCAL_GL_TEXTURE0); if (!mTexImage->InUpdate() || !mTexImage->EndUpdate()) { gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexImage->Texture()); } + // Note BGR: Cairo's image surfaces are always in what + // OpenGL and our shaders consider BGR format. + ColorTextureLayerProgram *program = + aManager->GetColorTextureLayerProgram(mTexImage->GetShaderProgramType()); + float xres = mLayer->GetXResolution(); float yres = mLayer->GetYResolution(); diff --git a/gfx/thebes/GLContext.cpp b/gfx/thebes/GLContext.cpp index 7936f798223d..c10a387c0d24 100644 --- a/gfx/thebes/GLContext.cpp +++ b/gfx/thebes/GLContext.cpp @@ -536,8 +536,6 @@ BasicTextureImage::~BasicTextureImage() mGLContext->MakeCurrent(); mGLContext->fDeleteTextures(1, &mTexture); } - - mBackingSurface = nsnull; } gfxContext* @@ -549,20 +547,12 @@ BasicTextureImage::BeginUpdate(nsIntRegion& aRegion) ImageFormat format = (GetContentType() == gfxASurface::CONTENT_COLOR) ? gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32; - PRBool repaintEverything = PR_FALSE; - if (mGLContext->IsExtensionSupported(gl::GLContext::APPLE_client_storage)) { - repaintEverything = - !(mBackingSurface && - mBackingSurface->GetSize() == gfxIntSize(mSize.width, mSize.height) && - mBackingSurface->Format() == format); - } - if (!mTextureInited || repaintEverything) + if (!mTextureInited) { // 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 mUpdateRect = nsIntRect(nsIntPoint(0, 0), mSize); - mTextureInited = PR_FALSE; } else { mUpdateRect = aRegion.GetBounds(); } @@ -600,72 +590,21 @@ BasicTextureImage::EndUpdate() // but important if we ever do anything directly with the surface. originalSurface->SetDeviceOffset(gfxPoint(0, 0)); - nsRefPtr uploadImage = GetImageForUpload(originalSurface); - if (!uploadImage) - return PR_FALSE; - - mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture); - - // The images that come out of the cairo quartz surface are 16-byte aligned - // for performance. We know this is an RGBA surface, so we divide the - // stride by 4 to represent the number of elements long the row is. - mGLContext->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, - uploadImage->Stride() / 4); - - DEBUG_GL_ERROR_CHECK(mGLContext); - - if (!mTextureInited) - { - // If we can use the client storage extension, we should. - if (mGLContext->IsExtensionSupported(gl::GLContext::APPLE_client_storage)) { - mGLContext->fPixelStorei(LOCAL_GL_UNPACK_CLIENT_STORAGE_APPLE, - LOCAL_GL_TRUE); - DEBUG_GL_ERROR_CHECK(mGLContext); - } - - mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D, - 0, - LOCAL_GL_RGBA, - mUpdateRect.width, - mUpdateRect.height, - 0, - LOCAL_GL_RGBA, - LOCAL_GL_UNSIGNED_BYTE, - uploadImage->Data()); - - DEBUG_GL_ERROR_CHECK(mGLContext); - - mTextureInited = PR_TRUE; - - // Reset the pixel store attribute, and hold on to the update surface - // because we're using the client storage extension. - if (mGLContext->IsExtensionSupported(gl::GLContext::APPLE_client_storage)) { - mBackingSurface = uploadImage; - mGLContext->fPixelStorei(LOCAL_GL_UNPACK_CLIENT_STORAGE_APPLE, - LOCAL_GL_FALSE); - DEBUG_GL_ERROR_CHECK(mGLContext); - } - } else { - // By default, mUpdateOffset is initialized to (0, 0), so we will - // upload from the origin of the update surface. Subclasses can set - // mUpdateOffset in an overridden BeginUpdate or EndUpdate to change - // this. - unsigned char* data = uploadImage->Data() + mUpdateOffset.x * 4 + - mUpdateOffset.y * uploadImage->Stride(); - mGLContext->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, - 0, - mUpdateRect.x, - mUpdateRect.y, - mUpdateRect.width, - mUpdateRect.height, - LOCAL_GL_RGBA, - LOCAL_GL_UNSIGNED_BYTE, - data); + // The rect to upload from the surface is mUpdateRect sized and located at mUpdateOffset. + nsIntRect surfaceRect(mUpdateOffset.x, mUpdateOffset.y, mUpdateRect.width, mUpdateRect.height); + if (!mTextureInited) { + surfaceRect.x = 0; + surfaceRect.y = 0; } - mUpdateContext = NULL; - // Reset pixel store attributes to use the defaults. - mGLContext->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0); + mShaderType = + mGLContext->UploadSurfaceToTexture(originalSurface, + surfaceRect, + mTexture, + !mTextureInited, + mUpdateRect.TopLeft()); + mUpdateContext = nsnull; + mTextureInited = PR_TRUE; return PR_TRUE; // mTexture is bound } @@ -1274,7 +1213,7 @@ GLContext::UploadSurfaceToTexture(gfxASurface *aSurface, bool textureInited = aOverwrite ? false : true; MakeCurrent(); fActiveTexture(LOCAL_GL_TEXTURE0); - + if (!aTexture) { fGenTextures(1, &aTexture); fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture); diff --git a/gfx/thebes/GLContext.h b/gfx/thebes/GLContext.h index f489cd1830f4..0cd2095ec42d 100644 --- a/gfx/thebes/GLContext.h +++ b/gfx/thebes/GLContext.h @@ -117,6 +117,19 @@ protected: PlatformLookupFunction mLookupFunc; }; +enum ShaderProgramType { + RGBALayerProgramType, + BGRALayerProgramType, + RGBXLayerProgramType, + BGRXLayerProgramType, + RGBARectLayerProgramType, + ColorLayerProgramType, + YCbCrLayerProgramType, + Copy2DProgramType, + Copy2DRectProgramType, + NumProgramTypes +}; + /** * A TextureImage encapsulates a surface that can be drawn to by a @@ -200,6 +213,16 @@ public: */ GLuint Texture() { return mTexture; } + /** + * Returns the shader program type that should be used to render + * this texture. Only valid after a matching BeginUpdate/EndUpdate + * pair have been called. + */ + virtual ShaderProgramType GetShaderProgramType() + { + return mShaderType; + } + /** Can be called safely at any time. */ /** @@ -240,6 +263,7 @@ protected: GLenum mWrapMode; ContentType mContentType; PRPackedBool mIsRGBFormat; + ShaderProgramType mShaderType; }; /** @@ -280,12 +304,8 @@ protected: virtual already_AddRefed CreateUpdateSurface(const gfxIntSize& aSize, ImageFormat aFmt) = 0; - virtual already_AddRefed - GetImageForUpload(gfxASurface* aUpdateSurface) = 0; - PRBool mTextureInited; GLContext* mGLContext; - nsRefPtr mBackingSurface; nsRefPtr mUpdateContext; nsIntRect mUpdateRect; @@ -355,19 +375,6 @@ struct THEBES_API ContextFormat int colorBits() const { return red + green + blue; } }; -enum ShaderProgramType { - RGBALayerProgramType, - BGRALayerProgramType, - RGBXLayerProgramType, - BGRXLayerProgramType, - RGBARectLayerProgramType, - ColorLayerProgramType, - YCbCrLayerProgramType, - Copy2DProgramType, - Copy2DRectProgramType, - NumProgramTypes -}; - class GLContext : public LibrarySymbolLoader { diff --git a/gfx/thebes/GLContextProviderCGL.mm b/gfx/thebes/GLContextProviderCGL.mm index e9235c7fe17a..00d3e56f1ea3 100644 --- a/gfx/thebes/GLContextProviderCGL.mm +++ b/gfx/thebes/GLContextProviderCGL.mm @@ -305,9 +305,8 @@ protected: else format = gfxASurface::ImageFormatARGB32; - if (!mTextureInited || !mBackingSurface || !mUpdateSurface || - nsIntSize(mBackingSurface->Width(), mBackingSurface->Height()) < mSize || - mBackingSurface->Format() != format) + if (!mTextureInited || !mUpdateSurface || + mUpdateSurface->GetContentType() != GetContentType()) { mUpdateSurface = nsnull; mUpdateOffset = nsIntPoint(0, 0); @@ -315,6 +314,15 @@ protected: return BasicTextureImage::BeginUpdate(aRegion); } + nsRefPtr imageSurface = mUpdateSurface->GetAsImageSurface(); + if (!imageSurface || + nsIntSize(imageSurface->Width(), imageSurface->Height()) < mSize) { + mUpdateSurface = nsnull; + mUpdateOffset = nsIntPoint(0, 0); + // We need to (re)create our backing store. Let the base class to that. + return BasicTextureImage::BeginUpdate(aRegion); + } + // the basic impl can only upload updates to rectangles mUpdateRect = aRegion.GetBounds(); aRegion = nsIntRegion(mUpdateRect); @@ -354,31 +362,6 @@ protected: return gfxPlatform::GetPlatform()->CreateOffscreenSurface(aSize, gfxASurface::ContentFromFormat(aFmt)); } - virtual already_AddRefed - GetImageForUpload(gfxASurface* aUpdateSurface) - { - nsRefPtr image = aUpdateSurface->GetAsImageSurface(); - - if (image && image->Format() != mUpdateFormat) { - image = nsnull; - } - - // If we don't get an image directly from the quartz surface, we have - // to take the slow boat. - if (!image) { - image = new gfxImageSurface(gfxIntSize(mUpdateRect.width, - mUpdateRect.height), - mUpdateFormat); - nsRefPtr tmpContext = new gfxContext(image); - - tmpContext->SetSource(aUpdateSurface); - tmpContext->SetOperator(gfxContext::OPERATOR_SOURCE); - tmpContext->Paint(); - } - - return image.forget(); - } - private: TextureImageCGL(GLuint aTexture, const nsIntSize& aSize, diff --git a/gfx/thebes/GLContextProviderEGL.cpp b/gfx/thebes/GLContextProviderEGL.cpp index 7744198ce234..922336cbbf3a 100644 --- a/gfx/thebes/GLContextProviderEGL.cpp +++ b/gfx/thebes/GLContextProviderEGL.cpp @@ -970,6 +970,9 @@ public: if (gUseBackingSurface) { CreateBackingSurface(gfxIntSize(aSize.width, aSize.height)); } + + // We currently always use BGRA type textures + mShaderType = BGRALayerProgramType; } virtual ~TextureImageEGL() diff --git a/gfx/thebes/GLContextProviderGLX.cpp b/gfx/thebes/GLContextProviderGLX.cpp index 0352849486d8..5a13b35eede2 100644 --- a/gfx/thebes/GLContextProviderGLX.cpp +++ b/gfx/thebes/GLContextProviderGLX.cpp @@ -426,22 +426,6 @@ protected: return gfxPlatform::GetPlatform()->CreateOffscreenSurface(aSize, gfxASurface::ContentFromFormat(aFmt)); } - virtual already_AddRefed - GetImageForUpload(gfxASurface* aUpdateSurface) - { - nsRefPtr image = - new gfxImageSurface(gfxIntSize(mUpdateRect.width, - mUpdateRect.height), - mUpdateFormat); - nsRefPtr tmpContext = new gfxContext(image); - - tmpContext->SetSource(aUpdateSurface); - tmpContext->SetOperator(gfxContext::OPERATOR_SOURCE); - tmpContext->Paint(); - - return image.forget(); - } - private: TextureImageGLX(GLuint aTexture, const nsIntSize& aSize, diff --git a/gfx/thebes/GLContextProviderWGL.cpp b/gfx/thebes/GLContextProviderWGL.cpp index 51ba1ab3b9e5..7231afbc57fa 100644 --- a/gfx/thebes/GLContextProviderWGL.cpp +++ b/gfx/thebes/GLContextProviderWGL.cpp @@ -464,24 +464,6 @@ protected: return gfxPlatform::GetPlatform()->CreateOffscreenSurface(aSize, gfxASurface::ContentFromFormat(aFmt)); } - virtual already_AddRefed - GetImageForUpload(gfxASurface* aUpdateSurface) - { - nsRefPtr uploadImage; - - if (aUpdateSurface->GetType() == gfxASurface::SurfaceTypeWin32) { - uploadImage = aUpdateSurface->GetAsImageSurface(); - } else { - uploadImage = new gfxImageSurface(mUpdateSize, mUpdateFormat); - nsRefPtr cx(new gfxContext(uploadImage)); - cx->SetSource(aUpdateSurface); - cx->SetOperator(gfxContext::OPERATOR_SOURCE); - cx->Paint(); - } - - return uploadImage.forget(); - } - private: TextureImageWGL(GLuint aTexture, const nsIntSize& aSize,