Bug 604101 - Part 1 - Add UploadSurfaceToTexture. r=joe a=blocking2.0

This commit is contained in:
Matt Woodrow 2010-12-16 23:23:07 -08:00
parent 58d947701c
commit fce27bc281
4 changed files with 221 additions and 32 deletions

View File

@ -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) \

View File

@ -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<ColorTextureLayerProgram*>(mPrograms[type]);
}
ColorTextureLayerProgram *GetRGBALayerProgram() {
return static_cast<ColorTextureLayerProgram*>(mPrograms[RGBALayerProgramType]);
return static_cast<ColorTextureLayerProgram*>(mPrograms[gl::RGBALayerProgramType]);
}
ColorTextureLayerProgram *GetBGRALayerProgram() {
return static_cast<ColorTextureLayerProgram*>(mPrograms[BGRALayerProgramType]);
return static_cast<ColorTextureLayerProgram*>(mPrograms[gl::BGRALayerProgramType]);
}
ColorTextureLayerProgram *GetRGBXLayerProgram() {
return static_cast<ColorTextureLayerProgram*>(mPrograms[RGBXLayerProgramType]);
return static_cast<ColorTextureLayerProgram*>(mPrograms[gl::RGBXLayerProgramType]);
}
ColorTextureLayerProgram *GetBGRXLayerProgram() {
return static_cast<ColorTextureLayerProgram*>(mPrograms[BGRXLayerProgramType]);
return static_cast<ColorTextureLayerProgram*>(mPrograms[gl::BGRXLayerProgramType]);
}
ColorTextureLayerProgram *GetBasicLayerProgram(PRBool aOpaque, PRBool aIsRGB)
{
@ -206,25 +211,25 @@ public:
}
ColorTextureLayerProgram *GetRGBARectLayerProgram() {
return static_cast<ColorTextureLayerProgram*>(mPrograms[RGBARectLayerProgramType]);
return static_cast<ColorTextureLayerProgram*>(mPrograms[gl::RGBARectLayerProgramType]);
}
SolidColorLayerProgram *GetColorLayerProgram() {
return static_cast<SolidColorLayerProgram*>(mPrograms[ColorLayerProgramType]);
return static_cast<SolidColorLayerProgram*>(mPrograms[gl::ColorLayerProgramType]);
}
YCbCrTextureLayerProgram *GetYCbCrLayerProgram() {
return static_cast<YCbCrTextureLayerProgram*>(mPrograms[YCbCrLayerProgramType]);
return static_cast<YCbCrTextureLayerProgram*>(mPrograms[gl::YCbCrLayerProgramType]);
}
CopyProgram *GetCopy2DProgram() {
return static_cast<CopyProgram*>(mPrograms[Copy2DProgramType]);
return static_cast<CopyProgram*>(mPrograms[gl::Copy2DProgramType]);
}
CopyProgram *GetCopy2DRectProgram() {
return static_cast<CopyProgram*>(mPrograms[Copy2DRectProgramType]);
return static_cast<CopyProgram*>(mPrograms[gl::Copy2DRectProgramType]);
}
ColorTextureLayerProgram *GetFBOLayerProgram() {
if (mFBOTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB)
return static_cast<ColorTextureLayerProgram*>(mPrograms[RGBARectLayerProgramType]);
return static_cast<ColorTextureLayerProgram*>(mPrograms[RGBALayerProgramType]);
return static_cast<ColorTextureLayerProgram*>(mPrograms[gl::RGBARectLayerProgramType]);
return static_cast<ColorTextureLayerProgram*>(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<ImageContainer*> mImageContainers;
enum ProgramType {
RGBALayerProgramType,
BGRALayerProgramType,
RGBXLayerProgramType,
BGRXLayerProgramType,
RGBARectLayerProgramType,
ColorLayerProgramType,
YCbCrLayerProgramType,
Copy2DProgramType,
Copy2DRectProgramType,
NumProgramTypes
};
static ProgramType sLayerProgramTypes[];
/** Backbuffer */

View File

@ -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<gfxImageSurface> 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<gfxContext> 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)

View File

@ -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 {