mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-17 22:32:51 +00:00
Bug 628566 - Implement basic tiling of ImageLayerOGL. r=joe
This commit is contained in:
parent
2bbc61681d
commit
9b0ef26bc8
@ -213,10 +213,6 @@ LayerManager::CreateOptimalSurface(const gfxIntSize &aSize,
|
||||
void
|
||||
LayerManager::Mutated(Layer* aLayer)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(!aLayer->GetTileSourceRect() ||
|
||||
(LAYERS_BASIC == GetBackendType() &&
|
||||
Layer::TYPE_IMAGE == aLayer->GetType()),
|
||||
"Tiling not supported for this manager/layer type");
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
|
@ -441,6 +441,11 @@ ImageLayerOGL::RenderLayer(int,
|
||||
CairoImageOGL *cairoImage =
|
||||
static_cast<CairoImageOGL*>(image.get());
|
||||
|
||||
cairoImage->SetTiling(mUseTileSourceRect);
|
||||
gl()->MakeCurrent();
|
||||
unsigned int iwidth = cairoImage->mSize.width;
|
||||
unsigned int iheight = cairoImage->mSize.height;
|
||||
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, cairoImage->mTexture.GetTextureID());
|
||||
|
||||
@ -452,23 +457,108 @@ ImageLayerOGL::RenderLayer(int,
|
||||
sGLXLibrary.BindTexImage(pixmap);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
ColorTextureLayerProgram *program =
|
||||
mOGLManager->GetColorTextureLayerProgram(cairoImage->mLayerProgram);
|
||||
|
||||
ApplyFilter(mFilter);
|
||||
|
||||
program->Activate();
|
||||
program->SetLayerQuadRect(nsIntRect(0, 0,
|
||||
cairoImage->mSize.width,
|
||||
cairoImage->mSize.height));
|
||||
// The following uniform controls the scaling of the vertex coords.
|
||||
// Instead of setting the scale here and using coords in the range [0,1], we
|
||||
// set an identity transform and use pixel coordinates below
|
||||
program->SetLayerQuadRect(nsIntRect(0, 0, 1, 1));
|
||||
program->SetLayerTransform(GetEffectiveTransform());
|
||||
program->SetLayerOpacity(GetEffectiveOpacity());
|
||||
program->SetRenderOffset(aOffset);
|
||||
program->SetTextureUnit(0);
|
||||
|
||||
mOGLManager->BindAndDrawQuad(program);
|
||||
nsIntRect rect = GetVisibleRegion().GetBounds();
|
||||
|
||||
bool tileIsWholeImage = (mTileSourceRect == nsIntRect(0, 0, iwidth, iheight))
|
||||
|| !mUseTileSourceRect;
|
||||
bool imageIsPowerOfTwo = ((iwidth & (iwidth - 1)) == 0 &&
|
||||
(iheight & (iheight - 1)) == 0);
|
||||
bool canDoNPOT = (
|
||||
gl()->IsExtensionSupported(GLContext::ARB_texture_non_power_of_two) ||
|
||||
gl()->IsExtensionSupported(GLContext::OES_texture_npot));
|
||||
|
||||
GLContext::RectTriangles triangleBuffer;
|
||||
// do GL_REPEAT if we can - should be the fastest option.
|
||||
// draw a single rect for the whole region, a little overdraw
|
||||
// on the gpu should be faster than tesselating
|
||||
// maybe we can write a shader that can also handle texture subrects
|
||||
// and repeat?
|
||||
if (tileIsWholeImage && (imageIsPowerOfTwo || canDoNPOT)) {
|
||||
// we need to anchor the repeating texture appropriately
|
||||
// otherwise it will start from the region border instead
|
||||
// of the layer origin. This is the offset into the texture
|
||||
// that the region border represents
|
||||
float tex_offset_u = (float)(rect.x % iwidth) / iwidth;
|
||||
float tex_offset_v = (float)(rect.y % iheight) / iheight;
|
||||
triangleBuffer.addRect(rect.x, rect.y,
|
||||
rect.x + rect.width, rect.y + rect.height,
|
||||
tex_offset_u, tex_offset_v,
|
||||
tex_offset_u + (float)rect.width / (float)iwidth,
|
||||
tex_offset_v + (float)rect.height / (float)iheight);
|
||||
}
|
||||
// can't do fast path via GL_REPEAT - we have to tessellate individual rects.
|
||||
else {
|
||||
unsigned int twidth = mTileSourceRect.width;
|
||||
unsigned int theight = mTileSourceRect.height;
|
||||
|
||||
nsIntRegion region = GetVisibleRegion();
|
||||
// image subrect in texture coordinates
|
||||
float subrect_tl_u = float(mTileSourceRect.x) / float(iwidth);
|
||||
float subrect_tl_v = float(mTileSourceRect.y) / float(iheight);
|
||||
float subrect_br_u = float(mTileSourceRect.width + mTileSourceRect.x) / float(iwidth);
|
||||
float subrect_br_v = float(mTileSourceRect.height + mTileSourceRect.y) / float(iheight);
|
||||
|
||||
// round rect position down to multiples of texture size
|
||||
// this way we start at multiples of rect positions
|
||||
rect.x = (rect.x / iwidth) * iwidth;
|
||||
rect.y = (rect.y / iheight) * iheight;
|
||||
// round up size to accomodate for rounding down above
|
||||
rect.width = (rect.width / iwidth + 2) * iwidth;
|
||||
rect.height = (rect.height / iheight + 2) * iheight;
|
||||
|
||||
// tesselate the visible region with tiles of subrect size
|
||||
for (int y = rect.y; y < rect.y + rect.height; y += theight) {
|
||||
for (int x = rect.x; x < rect.x + rect.width; x += twidth) {
|
||||
// when we already tessellate, we might as well save on overdraw here
|
||||
if (!region.Intersects(nsIntRect(x, y, twidth, theight))) {
|
||||
continue;
|
||||
}
|
||||
triangleBuffer.addRect(x, y,
|
||||
x + twidth, y + theight,
|
||||
subrect_tl_u, subrect_tl_v,
|
||||
subrect_br_u, subrect_br_v);
|
||||
}
|
||||
}
|
||||
}
|
||||
GLuint vertAttribIndex =
|
||||
program->AttribLocation(LayerProgram::VertexAttrib);
|
||||
GLuint texCoordAttribIndex =
|
||||
program->AttribLocation(LayerProgram::TexCoordAttrib);
|
||||
NS_ASSERTION(texCoordAttribIndex != GLuint(-1), "no texture coords?");
|
||||
|
||||
gl()->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||
gl()->fVertexAttribPointer(vertAttribIndex, 2,
|
||||
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
|
||||
triangleBuffer.vertexPointer());
|
||||
|
||||
gl()->fVertexAttribPointer(texCoordAttribIndex, 2,
|
||||
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
|
||||
triangleBuffer.texCoordPointer());
|
||||
{
|
||||
gl()->fEnableVertexAttribArray(texCoordAttribIndex);
|
||||
{
|
||||
gl()->fEnableVertexAttribArray(vertAttribIndex);
|
||||
gl()->fDrawArrays(LOCAL_GL_TRIANGLES, 0, triangleBuffer.elements());
|
||||
gl()->fDisableVertexAttribArray(vertAttribIndex);
|
||||
}
|
||||
gl()->fDisableVertexAttribArray(texCoordAttribIndex);
|
||||
}
|
||||
#if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
|
||||
if (cairoImage->mSurface) {
|
||||
sGLXLibrary.ReleaseTexImage(pixmap);
|
||||
@ -741,7 +831,7 @@ PlanarYCbCrImageOGL::UpdateTextures(GLContext *gl)
|
||||
}
|
||||
|
||||
CairoImageOGL::CairoImageOGL(LayerManagerOGL *aManager)
|
||||
: CairoImage(nsnull), mSize(0, 0)
|
||||
: CairoImage(nsnull), mSize(0, 0), mTiling(false)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread to create a cairo image");
|
||||
|
||||
@ -788,6 +878,25 @@ CairoImageOGL::SetData(const CairoImage::Data &aData)
|
||||
tex);
|
||||
}
|
||||
|
||||
void CairoImageOGL::SetTiling(bool aTiling)
|
||||
{
|
||||
if (aTiling == mTiling)
|
||||
return;
|
||||
mozilla::gl::GLContext *gl = mTexture.GetGLContext();
|
||||
gl->MakeCurrent();
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture.GetTextureID());
|
||||
mTiling = aTiling;
|
||||
|
||||
if (aTiling) {
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_REPEAT);
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_REPEAT);
|
||||
} else {
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
}
|
||||
|
||||
ShadowImageLayerOGL::ShadowImageLayerOGL(LayerManagerOGL* aManager)
|
||||
: ShadowImageLayer(aManager, nsnull)
|
||||
, LayerOGL(aManager)
|
||||
|
@ -233,6 +233,9 @@ public:
|
||||
#if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
|
||||
nsRefPtr<gfxASurface> mSurface;
|
||||
#endif
|
||||
void SetTiling(bool aTiling);
|
||||
private:
|
||||
bool mTiling;
|
||||
};
|
||||
|
||||
class ShadowImageLayerOGL : public ShadowImageLayer,
|
||||
|
@ -80,7 +80,11 @@ $FRAGMENT_SHADER_HEADER$
|
||||
uniform float uLayerOpacity;
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES // for tiling, texcoord can be greater than the lowfp range
|
||||
varying mediump vec2 vTexCoord;
|
||||
#else
|
||||
varying vec2 vTexCoord;
|
||||
#endif
|
||||
@end
|
||||
|
||||
// This is a basic Layer vertex shader. It's used for all
|
||||
@ -97,7 +101,11 @@ uniform vec4 uRenderTargetOffset;
|
||||
attribute vec4 aVertexCoord;
|
||||
attribute vec2 aTexCoord;
|
||||
|
||||
#ifdef GL_ES // for tiling, texcoord can be greater than the lowfp range
|
||||
varying mediump vec2 vTexCoord;
|
||||
#else
|
||||
varying vec2 vTexCoord;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
|
@ -120,20 +120,22 @@ BindAndDrawQuadWithTextureRect(GLContext* aGl,
|
||||
GLContext::DecomposeIntoNoRepeatTriangles(aTexCoordRect, aTexSize, rects);
|
||||
}
|
||||
|
||||
// vertex position buffer is 2 floats, not normalized, 0 stride.
|
||||
aGl->fVertexAttribPointer(vertAttribIndex, 2,
|
||||
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
|
||||
rects.vertexCoords);
|
||||
rects.vertexPointer());
|
||||
|
||||
// texture coord buffer is 2 floats, not normalized, 0 stride.
|
||||
aGl->fVertexAttribPointer(texCoordAttribIndex, 2,
|
||||
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
|
||||
rects.texCoords);
|
||||
rects.texCoordPointer());
|
||||
|
||||
{
|
||||
aGl->fEnableVertexAttribArray(texCoordAttribIndex);
|
||||
{
|
||||
aGl->fEnableVertexAttribArray(vertAttribIndex);
|
||||
|
||||
aGl->fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.numRects * 6);
|
||||
aGl->fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
|
||||
|
||||
aGl->fDisableVertexAttribArray(vertAttribIndex);
|
||||
}
|
||||
|
@ -1217,10 +1217,10 @@ GLContext::BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect,
|
||||
|
||||
// now put the coords into the d[xy]0 .. d[xy]1 coordinate space
|
||||
// from the 0..1 that it comes out of decompose
|
||||
GLfloat *v = rects.vertexCoords;
|
||||
for (int i = 0; i < rects.numRects * 6; ++i) {
|
||||
v[i*2] = (v[i*2] * (dx1 - dx0)) + dx0;
|
||||
v[i*2+1] = (v[i*2+1] * (dy1 - dy0)) + dy0;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1230,13 +1230,13 @@ GLContext::BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect,
|
||||
|
||||
fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||
|
||||
fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.vertexCoords);
|
||||
fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.texCoords);
|
||||
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.numRects * 6);
|
||||
fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
|
||||
|
||||
fDisableVertexAttribArray(0);
|
||||
fDisableVertexAttribArray(1);
|
||||
@ -1462,28 +1462,35 @@ void
|
||||
GLContext::RectTriangles::addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
|
||||
GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1)
|
||||
{
|
||||
NS_ASSERTION(numRects < 4, "Overflow in number of rectangles, max 4!");
|
||||
vert_coord v;
|
||||
v.x = x0; v.y = y0;
|
||||
vertexCoords.AppendElement(v);
|
||||
v.x = x1; v.y = y0;
|
||||
vertexCoords.AppendElement(v);
|
||||
v.x = x0; v.y = y1;
|
||||
vertexCoords.AppendElement(v);
|
||||
|
||||
GLfloat *v = &vertexCoords[numRects*6*2];
|
||||
GLfloat *t = &texCoords[numRects*6*2];
|
||||
v.x = x0; v.y = y1;
|
||||
vertexCoords.AppendElement(v);
|
||||
v.x = x1; v.y = y0;
|
||||
vertexCoords.AppendElement(v);
|
||||
v.x = x1; v.y = y1;
|
||||
vertexCoords.AppendElement(v);
|
||||
|
||||
*v++ = x0; *v++ = y0;
|
||||
*v++ = x1; *v++ = y0;
|
||||
*v++ = x0; *v++ = y1;
|
||||
tex_coord t;
|
||||
t.u = tx0; t.v = ty0;
|
||||
texCoords.AppendElement(t);
|
||||
t.u = tx1; t.v = ty0;
|
||||
texCoords.AppendElement(t);
|
||||
t.u = tx0; t.v = ty1;
|
||||
texCoords.AppendElement(t);
|
||||
|
||||
*v++ = x0; *v++ = y1;
|
||||
*v++ = x1; *v++ = y0;
|
||||
*v++ = x1; *v++ = y1;
|
||||
|
||||
*t++ = tx0; *t++ = ty0;
|
||||
*t++ = tx1; *t++ = ty0;
|
||||
*t++ = tx0; *t++ = ty1;
|
||||
|
||||
*t++ = tx0; *t++ = ty1;
|
||||
*t++ = tx1; *t++ = ty0;
|
||||
*t++ = tx1; *t++ = ty1;
|
||||
|
||||
numRects++;
|
||||
t.u = tx0; t.v = ty1;
|
||||
texCoords.AppendElement(t);
|
||||
t.u = tx1; t.v = ty0;
|
||||
texCoords.AppendElement(t);
|
||||
t.u = tx1; t.v = ty1;
|
||||
texCoords.AppendElement(t);
|
||||
}
|
||||
|
||||
static GLfloat
|
||||
|
@ -807,15 +807,34 @@ public:
|
||||
/** Helper for DecomposeIntoNoRepeatTriangles
|
||||
*/
|
||||
struct RectTriangles {
|
||||
RectTriangles() : numRects(0) { }
|
||||
RectTriangles() { }
|
||||
|
||||
void addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
|
||||
GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1);
|
||||
|
||||
int numRects;
|
||||
/* max is 4 rectangles, each made up of 2 triangles (3 2-coord vertices each) */
|
||||
GLfloat vertexCoords[4*3*2*2];
|
||||
GLfloat texCoords[4*3*2*2];
|
||||
/**
|
||||
* these return a float pointer to the start of each array respectively.
|
||||
* Use it for glVertexAttribPointer calls.
|
||||
* We can return NULL if we choose to use Vertex Buffer Objects here.
|
||||
*/
|
||||
float* vertexPointer() {
|
||||
return &vertexCoords[0].x;
|
||||
};
|
||||
|
||||
float* texCoordPointer() {
|
||||
return &texCoords[0].u;
|
||||
};
|
||||
|
||||
unsigned int elements() {
|
||||
return vertexCoords.Length();
|
||||
};
|
||||
|
||||
typedef struct { GLfloat x,y; } vert_coord;
|
||||
typedef struct { GLfloat u,v; } tex_coord;
|
||||
private:
|
||||
// default is 4 rectangles, each made up of 2 triangles (3 coord vertices each)
|
||||
nsAutoTArray<vert_coord, 6> vertexCoords;
|
||||
nsAutoTArray<tex_coord, 6> texCoords;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "nsFrameLoader.h"
|
||||
#include "nsViewportFrame.h"
|
||||
#include "nsSubDocumentFrame.h"
|
||||
#include "nsIObserver.h"
|
||||
|
||||
typedef nsContentView::ViewConfig ViewConfig;
|
||||
using namespace mozilla::layers;
|
||||
@ -58,6 +59,28 @@ namespace layout {
|
||||
typedef FrameMetrics::ViewID ViewID;
|
||||
typedef RenderFrameParent::ViewMap ViewMap;
|
||||
|
||||
nsRefPtr<ImageContainer> sCheckerboard = nsnull;
|
||||
|
||||
class CheckerBoardPatternDeleter : public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_ISUPPORTS
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(CheckerBoardPatternDeleter, nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
CheckerBoardPatternDeleter::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const PRUnichar* aData)
|
||||
{
|
||||
if (!strcmp(aTopic, "xpcom-shutdown")) {
|
||||
sCheckerboard = nsnull;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Represents (affine) transforms that are calculated from a content view.
|
||||
struct ViewTransform {
|
||||
ViewTransform(nsIntPoint aTranslation = nsIntPoint(0, 0), float aXScale = 1, float aYScale = 1)
|
||||
@ -389,64 +412,34 @@ BuildViewMap(ViewMap& oldContentViews, ViewMap& newContentViews,
|
||||
}
|
||||
}
|
||||
|
||||
#define BOARDSIZE 32
|
||||
#define CHECKERSIZE 16
|
||||
already_AddRefed<gfxASurface>
|
||||
GetBackgroundImage()
|
||||
{
|
||||
// XXX TODO FIXME/bug XXXXXX: this is obviously a hacky placeloader
|
||||
// impl. Unclear how the background pattern source should be set.
|
||||
#define WHT 0xffff
|
||||
#define GRY 0xD69A
|
||||
#define WLINE8 WHT,WHT,WHT,WHT,WHT,WHT,WHT,WHT
|
||||
#define GLINE8 GRY,GRY,GRY,GRY,GRY,GRY,GRY,GRY
|
||||
#define WROW16 WLINE8, GLINE8
|
||||
#define GROW16 GLINE8, WLINE8
|
||||
static const unsigned short kCheckerboard[] = {
|
||||
WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,
|
||||
WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,
|
||||
WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,
|
||||
WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,
|
||||
|
||||
GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,
|
||||
GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,
|
||||
GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,
|
||||
GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,
|
||||
|
||||
WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,
|
||||
WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,
|
||||
WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,
|
||||
WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,
|
||||
|
||||
GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,
|
||||
GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,
|
||||
GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,
|
||||
GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,
|
||||
|
||||
WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,
|
||||
WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,
|
||||
WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,
|
||||
WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,
|
||||
|
||||
GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,
|
||||
GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,
|
||||
GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,
|
||||
GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,
|
||||
|
||||
WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,
|
||||
WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,
|
||||
WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,
|
||||
WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,WROW16,
|
||||
|
||||
GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,
|
||||
GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,
|
||||
GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,
|
||||
GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16,GROW16
|
||||
};
|
||||
static unsigned int data[BOARDSIZE * BOARDSIZE];
|
||||
static bool initialized = false;
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
for (unsigned int y = 0; y < BOARDSIZE; y++) {
|
||||
for (unsigned int x = 0; x < BOARDSIZE; x++) {
|
||||
bool col_odd = (x / CHECKERSIZE) & 1;
|
||||
bool row_odd = (y / CHECKERSIZE) & 1;
|
||||
if (col_odd ^ row_odd) { // xor
|
||||
data[y * BOARDSIZE + x] = 0xFFFFFFFF;
|
||||
}
|
||||
else {
|
||||
data[y * BOARDSIZE + x] = 0xFFDDDDDD;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<gfxASurface> s =
|
||||
new gfxImageSurface((unsigned char*)kCheckerboard,
|
||||
gfxIntSize(64, 64),
|
||||
64 * 2,
|
||||
gfxASurface::ImageFormatRGB16_565);
|
||||
new gfxImageSurface((unsigned char*) data,
|
||||
gfxIntSize(BOARDSIZE, BOARDSIZE),
|
||||
BOARDSIZE * sizeof(unsigned int),
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
return s.forget();
|
||||
}
|
||||
|
||||
@ -505,15 +498,26 @@ BuildBackgroundPatternFor(ContainerLayer* aContainer,
|
||||
gfxIntSize bgImageSize = bgImage->GetSize();
|
||||
|
||||
// Set up goop needed to get a cairo image into its own layer
|
||||
nsRefPtr<ImageContainer> c = aManager->CreateImageContainer();
|
||||
const Image::Format fmts[] = { Image::CAIRO_SURFACE };
|
||||
nsRefPtr<Image> img = c->CreateImage(fmts, 1);
|
||||
CairoImage::Data data = { bgImage.get(), bgImageSize };
|
||||
static_cast<CairoImage*>(img.get())->SetData(data);
|
||||
c->SetCurrentImage(img);
|
||||
if (!sCheckerboard) {
|
||||
sCheckerboard = aManager->CreateImageContainer().get();
|
||||
const Image::Format fmts[] = { Image::CAIRO_SURFACE };
|
||||
nsRefPtr<Image> img = sCheckerboard->CreateImage(fmts, 1);
|
||||
CairoImage::Data data = { bgImage.get(), bgImageSize };
|
||||
static_cast<CairoImage*>(img.get())->SetData(data);
|
||||
sCheckerboard->SetCurrentImage(img);
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
if (!observerService) {
|
||||
return;
|
||||
}
|
||||
nsresult rv = observerService->AddObserver(new CheckerBoardPatternDeleter, "xpcom-shutdown", PR_FALSE);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<ImageLayer> layer = aManager->CreateImageLayer();
|
||||
layer->SetContainer(c);
|
||||
layer->SetContainer(sCheckerboard);
|
||||
|
||||
// The tile source is the entire background image
|
||||
nsIntRect tileSource(0, 0, bgImageSize.width, bgImageSize.height);
|
||||
|
Loading…
x
Reference in New Issue
Block a user