diff --git a/gfx/layers/opengl/LayerManagerOGL.cpp b/gfx/layers/opengl/LayerManagerOGL.cpp index 9547cc7ad22..5a36ce87cb3 100644 --- a/gfx/layers/opengl/LayerManagerOGL.cpp +++ b/gfx/layers/opengl/LayerManagerOGL.cpp @@ -848,13 +848,13 @@ LayerManagerOGL::CopyToTarget() } LayerManagerOGL::ProgramType LayerManagerOGL::sLayerProgramTypes[] = { - LayerManagerOGL::RGBALayerProgramType, - LayerManagerOGL::BGRALayerProgramType, - LayerManagerOGL::RGBXLayerProgramType, - LayerManagerOGL::BGRXLayerProgramType, - LayerManagerOGL::RGBARectLayerProgramType, - LayerManagerOGL::ColorLayerProgramType, - LayerManagerOGL::YCbCrLayerProgramType + gl::RGBALayerProgramType, + gl::BGRALayerProgramType, + gl::RGBXLayerProgramType, + gl::BGRXLayerProgramType, + gl::RGBARectLayerProgramType, + gl::ColorLayerProgramType, + gl::YCbCrLayerProgramType }; #define FOR_EACH_LAYER_PROGRAM(vname) \ diff --git a/gfx/layers/opengl/LayerManagerOGL.h b/gfx/layers/opengl/LayerManagerOGL.h index 798acf42145..a22be3123a1 100644 --- a/gfx/layers/opengl/LayerManagerOGL.h +++ b/gfx/layers/opengl/LayerManagerOGL.h @@ -91,6 +91,7 @@ class THEBES_API LayerManagerOGL : #endif { typedef mozilla::gl::GLContext GLContext; + typedef mozilla::gl::ShaderProgramType ProgramType; public: LayerManagerOGL(nsIWidget *aWidget); @@ -180,17 +181,21 @@ public: mGLContext->MakeCurrent(aForce); } + ColorTextureLayerProgram *GetColorTextureLayerProgram(ProgramType type){ + return static_cast(mPrograms[type]); + } + ColorTextureLayerProgram *GetRGBALayerProgram() { - return static_cast(mPrograms[RGBALayerProgramType]); + return static_cast(mPrograms[gl::RGBALayerProgramType]); } ColorTextureLayerProgram *GetBGRALayerProgram() { - return static_cast(mPrograms[BGRALayerProgramType]); + return static_cast(mPrograms[gl::BGRALayerProgramType]); } ColorTextureLayerProgram *GetRGBXLayerProgram() { - return static_cast(mPrograms[RGBXLayerProgramType]); + return static_cast(mPrograms[gl::RGBXLayerProgramType]); } ColorTextureLayerProgram *GetBGRXLayerProgram() { - return static_cast(mPrograms[BGRXLayerProgramType]); + return static_cast(mPrograms[gl::BGRXLayerProgramType]); } ColorTextureLayerProgram *GetBasicLayerProgram(PRBool aOpaque, PRBool aIsRGB) { @@ -206,25 +211,25 @@ public: } ColorTextureLayerProgram *GetRGBARectLayerProgram() { - return static_cast(mPrograms[RGBARectLayerProgramType]); + return static_cast(mPrograms[gl::RGBARectLayerProgramType]); } SolidColorLayerProgram *GetColorLayerProgram() { - return static_cast(mPrograms[ColorLayerProgramType]); + return static_cast(mPrograms[gl::ColorLayerProgramType]); } YCbCrTextureLayerProgram *GetYCbCrLayerProgram() { - return static_cast(mPrograms[YCbCrLayerProgramType]); + return static_cast(mPrograms[gl::YCbCrLayerProgramType]); } CopyProgram *GetCopy2DProgram() { - return static_cast(mPrograms[Copy2DProgramType]); + return static_cast(mPrograms[gl::Copy2DProgramType]); } CopyProgram *GetCopy2DRectProgram() { - return static_cast(mPrograms[Copy2DRectProgramType]); + return static_cast(mPrograms[gl::Copy2DRectProgramType]); } ColorTextureLayerProgram *GetFBOLayerProgram() { if (mFBOTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) - return static_cast(mPrograms[RGBARectLayerProgramType]); - return static_cast(mPrograms[RGBALayerProgramType]); + return static_cast(mPrograms[gl::RGBARectLayerProgramType]); + return static_cast(mPrograms[gl::RGBALayerProgramType]); } GLContext *gl() const { return mGLContext; } @@ -341,7 +346,7 @@ public: const nsIntSize& GetWigetSize() { return mWidgetSize; } - + /** * Setup the viewport and projection matrix for rendering * to a window of the given dimensions. @@ -365,19 +370,6 @@ private: // it from the list. nsTArray mImageContainers; - enum ProgramType { - RGBALayerProgramType, - BGRALayerProgramType, - RGBXLayerProgramType, - BGRXLayerProgramType, - RGBARectLayerProgramType, - ColorLayerProgramType, - YCbCrLayerProgramType, - Copy2DProgramType, - Copy2DRectProgramType, - NumProgramTypes - }; - static ProgramType sLayerProgramTypes[]; /** Backbuffer */ diff --git a/gfx/thebes/GLContext.cpp b/gfx/thebes/GLContext.cpp index f5255e3f5fe..7936f798223 100644 --- a/gfx/thebes/GLContext.cpp +++ b/gfx/thebes/GLContext.cpp @@ -1263,6 +1263,161 @@ GLContext::BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect, PopViewportRect(); } + +ShaderProgramType +GLContext::UploadSurfaceToTexture(gfxASurface *aSurface, + const nsIntRect& aSrcRect, + GLuint& aTexture, + bool aOverwrite, + const nsIntPoint& aDstPoint) +{ + bool textureInited = aOverwrite ? false : true; + MakeCurrent(); + fActiveTexture(LOCAL_GL_TEXTURE0); + + if (!aTexture) { + fGenTextures(1, &aTexture); + fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture); + fTexParameteri(LOCAL_GL_TEXTURE_2D, + LOCAL_GL_TEXTURE_MIN_FILTER, + LOCAL_GL_LINEAR); + fTexParameteri(LOCAL_GL_TEXTURE_2D, + LOCAL_GL_TEXTURE_MAG_FILTER, + LOCAL_GL_LINEAR); + 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); + textureInited = false; + } else { + fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture); + } + + nsRefPtr imageSurface = aSurface->GetAsImageSurface(); + unsigned char* data; + + if (!imageSurface || + (imageSurface->Format() != gfxASurface::ImageFormatARGB32 && + imageSurface->Format() != gfxASurface::ImageFormatRGB24 && + imageSurface->Format() != gfxASurface::ImageFormatRGB16_565)) { + // We can't get suitable pixel data for the surface, make a copy + imageSurface = + new gfxImageSurface(gfxIntSize(aSrcRect.width, aSrcRect.height), + gfxASurface::ImageFormatARGB32); + + nsRefPtr context = new gfxContext(imageSurface); + + context->Translate(-gfxPoint(aSrcRect.x, aSrcRect.y)); + context->SetSource(aSurface); + context->Paint(); + data = imageSurface->Data(); + } else { + data = imageSurface->Data(); + data += aSrcRect.y * imageSurface->Stride(); + data += aSrcRect.x * 4; + } + + GLenum format; + GLenum internalformat; + GLenum type; + PRInt32 pixelSize = gfxASurface::BytePerPixelFromFormat(imageSurface->Format()); + ShaderProgramType shader; + + switch (imageSurface->Format()) { + case gfxASurface::ImageFormatARGB32: + format = LOCAL_GL_RGBA; + type = LOCAL_GL_UNSIGNED_BYTE; + shader = BGRALayerProgramType; + break; + case gfxASurface::ImageFormatRGB24: + // Treat RGB24 surfaces as RGBA32 except for the shader + // program used. + format = LOCAL_GL_RGBA; + type = LOCAL_GL_UNSIGNED_BYTE; + shader = BGRXLayerProgramType; + break; + case gfxASurface::ImageFormatRGB16_565: + format = LOCAL_GL_RGB; + type = LOCAL_GL_UNSIGNED_SHORT_5_6_5; + shader = RGBALayerProgramType; + break; + default: + NS_ASSERTION(false, "Unhandled image surface format!"); + } + +#ifndef USE_GLES2 + fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, + imageSurface->Stride() / pixelSize); + + internalformat = LOCAL_GL_RGBA; +#else + internalformat = format; + + if (imageSurface->Stride() != aSrcRect.width * pixelSize) { + // Not using the whole row of texture data and GLES doesn't + // support GL_UNPACK_ROW_LENGTH. We need to upload each row + // separately. + if (!textureInited) { + fTexImage2D(LOCAL_GL_TEXTURE_2D, + 0, + internalformat, + aSrcRect.width, + aSrcRect.height, + 0, + format, + type, + NULL); + } + + for (int h = 0; h < aSrcRect.height; h++) { + fTexSubImage2D(LOCAL_GL_TEXTURE_2D, + 0, + aDstPoint.x, + aDstPoint.y+h, + aSrcRect.width, + 1, + format, + type, + data); + data += imageSurface->Stride(); + } + + return shader; + } +#endif + + + if (textureInited) { + fTexSubImage2D(LOCAL_GL_TEXTURE_2D, + 0, + aDstPoint.x, + aDstPoint.y, + aSrcRect.width, + aSrcRect.height, + format, + type, + data); + } else { + fTexImage2D(LOCAL_GL_TEXTURE_2D, + 0, + internalformat, + aSrcRect.width, + aSrcRect.height, + 0, + format, + type, + data); + } + +#ifndef USE_GLES2 + fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0); +#endif + + return shader; +} + void GLContext::RectTriangles::addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1) diff --git a/gfx/thebes/GLContext.h b/gfx/thebes/GLContext.h index d51417536ef..f489cd1830f 100644 --- a/gfx/thebes/GLContext.h +++ b/gfx/thebes/GLContext.h @@ -355,6 +355,19 @@ 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 { @@ -705,6 +718,35 @@ public: void BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect, TextureImage *aDst, const nsIntRect& aDstRect); + /** + * Creates a RGB/RGBA texture (or uses one provided) and uploads the surface + * contents to it within aSrcRect. + * + * aSrcRect.x/y will be uploaded to 0/0 in the texture, and the size + * of the texture with be aSrcRect.width/height. + * + * If an existing texture is passed through aTexture, it is assumed it + * has already been initialised with glTexImage2D (or this function), + * and that its size is equal to or greater than aSrcRect + aDstPoint. + * You can alternatively set the overwrite flag to true and have a new + * texture memory block allocated. + * + * The aDstPoint parameter is ignored if no texture was provided + * or aOverwrite is true. + * + * \param aSurface Surface to upload. + * \param aSrcRect Region of aSurface to upload. + * \param aTexture Texture to use, or 0 to have one created for you. + * \param aOverwrite Over an existing texture with a new one. + * \param aDstPoint Offset into existing texture to upload contents. + * \return Shader program needed to render this texture. + */ + ShaderProgramType UploadSurfaceToTexture(gfxASurface *aSurface, + const nsIntRect& aSrcRect, + GLuint& aTexture, + bool aOverwrite = false, + const nsIntPoint& aDstPoint = nsIntPoint(0, 0)); + /** Helper for DecomposeIntoNoRepeatTriangles */ struct RectTriangles {