зеркало из https://github.com/mozilla/pjs.git
b=567626; fix up opengl layers; r=bas
This commit is contained in:
Родитель
d1cc2143ff
Коммит
e7b67e3ac6
|
@ -62,6 +62,7 @@ EXPORTS = \
|
|||
ImageLayers.h \
|
||||
Layers.h \
|
||||
LayerManagerOGL.h \
|
||||
LayerManagerOGLProgram.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
|
@ -90,6 +91,21 @@ CPPSRCS += \
|
|||
endif
|
||||
endif
|
||||
|
||||
# Enable GLES2.0 under maemo
|
||||
ifdef MOZ_X11
|
||||
ifdef MOZ_PLATFORM_MAEMO
|
||||
DEFINES += -DUSE_GLES2
|
||||
endif
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
CXXFLAGS += $(MOZ_CAIRO_CFLAGS)
|
||||
|
||||
LayerManagerOGLShaders.h: LayerManagerOGLShaders.txt genshaders.py
|
||||
$(PYTHON) $(srcdir)/opengl/genshaders.py $< $@
|
||||
|
||||
LayerManagerOGL.$(OBJ_SUFFIX): LayerManagerOGLShaders.h
|
||||
|
||||
GARBAGE += LayerManagerOGLShaders.h
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-/
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
|
@ -55,25 +55,22 @@ using namespace mozilla::gl;
|
|||
|
||||
CanvasLayerOGL::~CanvasLayerOGL()
|
||||
{
|
||||
LayerManagerOGL *glManager = static_cast<LayerManagerOGL*>(mManager);
|
||||
GLContext *gl = glManager->gl();
|
||||
glManager->MakeCurrent();
|
||||
mOGLManager->MakeCurrent();
|
||||
|
||||
if (mTexture) {
|
||||
gl->fDeleteTextures(1, &mTexture);
|
||||
}
|
||||
if (mTexture)
|
||||
gl()->fDeleteTextures(1, &mTexture);
|
||||
}
|
||||
|
||||
void
|
||||
CanvasLayerOGL::Initialize(const Data& aData)
|
||||
{
|
||||
NS_ASSERTION(mSurface == nsnull, "BasicCanvasLayer::Initialize called twice!");
|
||||
NS_ASSERTION(mCanvasSurface == nsnull, "BasicCanvasLayer::Initialize called twice!");
|
||||
|
||||
if (aData.mSurface) {
|
||||
mSurface = aData.mSurface;
|
||||
mCanvasSurface = aData.mSurface;
|
||||
NS_ASSERTION(aData.mGLContext == nsnull,
|
||||
"CanvasLayerOGL can't have both surface and GLContext");
|
||||
mNeedsYFlip = PR_TRUE;
|
||||
mNeedsYFlip = PR_FALSE;
|
||||
} else if (aData.mGLContext) {
|
||||
// this must be a pbuffer context
|
||||
void *pbuffer = aData.mGLContext->GetNativeData(GLContext::NativePBuffer);
|
||||
|
@ -82,9 +79,9 @@ CanvasLayerOGL::Initialize(const Data& aData)
|
|||
return;
|
||||
}
|
||||
|
||||
mGLContext = aData.mGLContext;
|
||||
mCanvasGLContext = aData.mGLContext;
|
||||
mGLBufferIsPremultiplied = aData.mGLBufferIsPremultiplied;
|
||||
mNeedsYFlip = PR_FALSE;
|
||||
mNeedsYFlip = PR_TRUE;
|
||||
} else {
|
||||
NS_WARNING("CanvasLayerOGL::Initialize called without surface or GL context!");
|
||||
return;
|
||||
|
@ -96,46 +93,46 @@ CanvasLayerOGL::Initialize(const Data& aData)
|
|||
void
|
||||
CanvasLayerOGL::Updated(const nsIntRect& aRect)
|
||||
{
|
||||
LayerManagerOGL *glManager = static_cast<LayerManagerOGL*>(mManager);
|
||||
GLContext *gl = glManager->gl();
|
||||
glManager->MakeCurrent();
|
||||
NS_ASSERTION(mUpdatedRect.IsEmpty(),
|
||||
"CanvasLayer::Updated called more than once during a transaction!");
|
||||
|
||||
NS_ASSERTION(mUpdatedRect.IsEmpty(), "CanvasLayer::Updated called more than once during a transaction!");
|
||||
mOGLManager->MakeCurrent();
|
||||
|
||||
mUpdatedRect.UnionRect(mUpdatedRect, aRect);
|
||||
|
||||
if (mSurface) {
|
||||
if (mCanvasSurface) {
|
||||
if (mTexture == 0) {
|
||||
gl->fGenTextures(1, (GLuint*)&mTexture);
|
||||
gl()->fGenTextures(1, &mTexture);
|
||||
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
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);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
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);
|
||||
|
||||
mUpdatedRect = mBounds;
|
||||
} else {
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
}
|
||||
|
||||
nsRefPtr<gfxImageSurface> updatedAreaImageSurface;
|
||||
nsRefPtr<gfxASurface> sourceSurface = mSurface;
|
||||
nsRefPtr<gfxASurface> sourceSurface = mCanvasSurface;
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (sourceSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
|
||||
sourceSurface = static_cast<gfxWindowsSurface*>(sourceSurface.get())->GetImageSurface();
|
||||
if (!sourceSurface)
|
||||
sourceSurface = mSurface;
|
||||
sourceSurface = mCanvasSurface;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// XXX don't copy, blah.
|
||||
// but need to deal with stride on the gl side; do this later.
|
||||
if (mSurface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
gfxImageSurface *s = static_cast<gfxImageSurface*>(mSurface.get());
|
||||
if (mCanvasSurface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
gfxImageSurface *s = static_cast<gfxImageSurface*>(mCanvasSurface.get());
|
||||
if (s->Format() == gfxASurface::ImageFormatARGB32 ||
|
||||
s->Format() == gfxASurface::ImageFormatRGB24)
|
||||
{
|
||||
|
@ -147,8 +144,9 @@ CanvasLayerOGL::Updated(const nsIntRect& aRect)
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
updatedAreaImageSurface = new gfxImageSurface(gfxIntSize(mUpdatedRect.width, mUpdatedRect.height),
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
updatedAreaImageSurface =
|
||||
new gfxImageSurface(gfxIntSize(mUpdatedRect.width, mUpdatedRect.height),
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(updatedAreaImageSurface);
|
||||
ctx->Translate(gfxPoint(-mUpdatedRect.x, -mUpdatedRect.y));
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
|
@ -157,87 +155,70 @@ CanvasLayerOGL::Updated(const nsIntRect& aRect)
|
|||
}
|
||||
|
||||
if (mUpdatedRect == mBounds) {
|
||||
gl->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
mUpdatedRect.width,
|
||||
mUpdatedRect.height,
|
||||
0,
|
||||
LOCAL_GL_BGRA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
updatedAreaImageSurface->Data());
|
||||
gl()->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
mUpdatedRect.width,
|
||||
mUpdatedRect.height,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
updatedAreaImageSurface->Data());
|
||||
} else {
|
||||
gl->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
mUpdatedRect.x,
|
||||
mUpdatedRect.y,
|
||||
mUpdatedRect.width,
|
||||
mUpdatedRect.height,
|
||||
LOCAL_GL_BGRA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
updatedAreaImageSurface->Data());
|
||||
gl()->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
mUpdatedRect.x,
|
||||
mUpdatedRect.y,
|
||||
mUpdatedRect.width,
|
||||
mUpdatedRect.height,
|
||||
LOCAL_GL_RGBA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
updatedAreaImageSurface->Data());
|
||||
}
|
||||
} else if (mGLContext) {
|
||||
} else if (mCanvasGLContext) {
|
||||
// we just need to create a texture that we'll use, the first time through
|
||||
if (mTexture == 0) {
|
||||
gl->fGenTextures(1, (GLuint*)&mTexture);
|
||||
gl()->fGenTextures(1, (GLuint*)&mTexture);
|
||||
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
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);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
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);
|
||||
|
||||
mUpdatedRect = mBounds;
|
||||
}
|
||||
}
|
||||
|
||||
// sanity
|
||||
NS_ASSERTION(mUpdatedRect.IsEmpty() || mBounds.Contains(mUpdatedRect), "CanvasLayer: Updated rect bigger than bounds!");
|
||||
NS_ASSERTION(mUpdatedRect.IsEmpty() || mBounds.Contains(mUpdatedRect),
|
||||
"CanvasLayer: Updated rect bigger than bounds!");
|
||||
}
|
||||
|
||||
void
|
||||
CanvasLayerOGL::RenderLayer(int aPreviousDestination,
|
||||
DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
const nsIntPoint& aOffset)
|
||||
{
|
||||
LayerManagerOGL *glManager = static_cast<LayerManagerOGL*>(mManager);
|
||||
GLContext *gl = glManager->gl();
|
||||
glManager->MakeCurrent();
|
||||
|
||||
float quadTransform[4][4];
|
||||
// Transform the quad to the size of the canvas.
|
||||
memset(&quadTransform, 0, sizeof(quadTransform));
|
||||
quadTransform[0][0] = (float)mBounds.width;
|
||||
quadTransform[1][1] = (float)mBounds.height;
|
||||
quadTransform[2][2] = 1.0f;
|
||||
quadTransform[3][3] = 1.0f;
|
||||
mOGLManager->MakeCurrent();
|
||||
|
||||
// XXX We're going to need a different program depending on if
|
||||
// mGLBufferIsPremultiplied is TRUE or not. The RGBLayerProgram
|
||||
// assumes that it's true.
|
||||
|
||||
// XXX this function needs to handle both mNeedsYFlip -- right now,
|
||||
// as written, PBuffer canvas layers will be drawn upside-down.
|
||||
ColorTextureLayerProgram *program = nsnull;
|
||||
|
||||
RGBLayerProgram *program = glManager->GetRGBLayerProgram();
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
program->Activate();
|
||||
|
||||
program->SetLayerQuadTransform(&quadTransform[0][0]);
|
||||
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
if (mGLContext) {
|
||||
if (mCanvasGLContext) {
|
||||
#if defined(XP_MACOSX)
|
||||
CGLError err;
|
||||
err = CGLTexImagePBuffer((CGLContextObj) gl->GetNativeData(GLContext::NativeCGLContext),
|
||||
(CGLPBufferObj) mGLContext->GetNativeData(GLContext::NativePBuffer),
|
||||
err = CGLTexImagePBuffer((CGLContextObj) mCanvasGLContext->GetNativeData(GLContext::NativeCGLContext),
|
||||
(CGLPBufferObj) mCanvasGLContext->GetNativeData(GLContext::NativePBuffer),
|
||||
LOCAL_GL_BACK);
|
||||
#elif defined(XP_WIN)
|
||||
if (!sWGLLibrary.fBindTexImage((HANDLE) mGLContext->GetNativeData(GLContext::NativePBuffer),
|
||||
if (!sWGLLibrary.fBindTexImage((HANDLE) mCanvasGLContext->GetNativeData(GLContext::NativePBuffer),
|
||||
LOCAL_WGL_FRONT_LEFT_ARB))
|
||||
{
|
||||
NS_WARNING("CanvasLayerOGL::RenderLayer wglBindTexImageARB failed");
|
||||
|
@ -246,17 +227,24 @@ CanvasLayerOGL::RenderLayer(int aPreviousDestination,
|
|||
#else
|
||||
NS_WARNING("CanvasLayerOGL::RenderLayer with GL context, but I don't know how to render on this platform!");
|
||||
#endif
|
||||
|
||||
program = mOGLManager->GetRGBALayerProgram();
|
||||
} else {
|
||||
program = mOGLManager->GetBGRALayerProgram();
|
||||
}
|
||||
|
||||
program->Activate();
|
||||
program->SetLayerQuadRect(mBounds);
|
||||
program->SetLayerTransform(mTransform);
|
||||
program->SetLayerOpacity(GetOpacity());
|
||||
program->SetLayerTransform(&mTransform._11);
|
||||
program->Apply();
|
||||
program->SetRenderOffset(aOffset);
|
||||
program->SetTextureUnit(0);
|
||||
|
||||
gl->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
|
||||
mOGLManager->BindAndDrawQuad(program, mNeedsYFlip ? true : false);
|
||||
|
||||
if (mGLContext) {
|
||||
if (mCanvasGLContext) {
|
||||
#if defined(XP_WIN)
|
||||
sWGLLibrary.fReleaseTexImage((HANDLE) mGLContext->GetNativeData(GLContext::NativePBuffer),
|
||||
sWGLLibrary.fReleaseTexImage((HANDLE) mCanvasGLContext->GetNativeData(GLContext::NativePBuffer),
|
||||
LOCAL_WGL_FRONT_LEFT_ARB);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -66,15 +66,14 @@ public:
|
|||
// LayerOGL implementation
|
||||
virtual LayerType GetType() { return TYPE_CANVAS; }
|
||||
virtual Layer* GetLayer() { return this; }
|
||||
virtual void RenderLayer(int aPreviousDestination,
|
||||
DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset);
|
||||
|
||||
protected:
|
||||
nsRefPtr<gfxASurface> mSurface;
|
||||
nsRefPtr<GLContext> mGLContext;
|
||||
nsRefPtr<gfxASurface> mCanvasSurface;
|
||||
nsRefPtr<GLContext> mCanvasGLContext;
|
||||
|
||||
unsigned int mTexture;
|
||||
GLuint mTexture;
|
||||
|
||||
nsIntRect mBounds;
|
||||
nsIntRect mUpdatedRect;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Robert O'Callahan <robert@ocallahan.org>
|
||||
* Vladimir Vukicevic <vladimir@pobox.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -53,41 +54,37 @@ ColorLayerOGL::GetLayer()
|
|||
}
|
||||
|
||||
void
|
||||
ColorLayerOGL::RenderLayer(int, DrawThebesLayerCallback, void*)
|
||||
ColorLayerOGL::RenderLayer(int,
|
||||
const nsIntPoint& aOffset)
|
||||
{
|
||||
static_cast<LayerManagerOGL*>(mManager)->MakeCurrent();
|
||||
mOGLManager->MakeCurrent();
|
||||
|
||||
// XXX we might be able to improve performance by using glClear
|
||||
|
||||
float quadTransform[4][4];
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
// Transform the quad to the size of the visible area.
|
||||
memset(&quadTransform, 0, sizeof(quadTransform));
|
||||
quadTransform[0][0] = (float)visibleRect.width;
|
||||
quadTransform[1][1] = (float)visibleRect.height;
|
||||
quadTransform[2][2] = 1.0f;
|
||||
quadTransform[3][0] = (float)visibleRect.x;
|
||||
quadTransform[3][1] = (float)visibleRect.y;
|
||||
quadTransform[3][3] = 1.0f;
|
||||
|
||||
ColorLayerProgram *program =
|
||||
static_cast<LayerManagerOGL*>(mManager)->GetColorLayerProgram();
|
||||
/* Multiply color by the layer opacity, as the shader
|
||||
* ignores layer opacity and expects a final color to
|
||||
* write to the color buffer. This saves a needless
|
||||
* multiply in the fragment shader.
|
||||
*/
|
||||
float opacity = GetOpacity();
|
||||
gfxRGBA color(mColor);
|
||||
color.r *= opacity;
|
||||
color.g *= opacity;
|
||||
color.b *= opacity;
|
||||
color.a *= opacity;
|
||||
|
||||
SolidColorLayerProgram *program = mOGLManager->GetColorLayerProgram();
|
||||
program->Activate();
|
||||
program->SetLayerQuadRect(visibleRect);
|
||||
program->SetLayerTransform(mTransform);
|
||||
program->SetRenderOffset(aOffset);
|
||||
program->SetRenderColor(color);
|
||||
|
||||
program->SetLayerQuadTransform(&quadTransform[0][0]);
|
||||
mOGLManager->BindAndDrawQuad(program);
|
||||
|
||||
gfxRGBA color = mColor;
|
||||
// color is premultiplied, so we need to adjust all channels
|
||||
color.r *= GetOpacity();
|
||||
color.g *= GetOpacity();
|
||||
color.b *= GetOpacity();
|
||||
color.a *= GetOpacity();
|
||||
program->SetLayerColor(color);
|
||||
program->SetLayerTransform(&mTransform._11);
|
||||
program->Apply();
|
||||
|
||||
gl()->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
}
|
||||
|
||||
} /* layers */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-/
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
|
@ -61,9 +61,8 @@ public:
|
|||
|
||||
virtual Layer* GetLayer();
|
||||
|
||||
virtual void RenderLayer(int aPreviousDestination,
|
||||
DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset);
|
||||
|
||||
protected:
|
||||
nsIntRegion mVisibleRegion;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -139,70 +139,29 @@ ContainerLayerOGL::GetFirstChildOGL()
|
|||
|
||||
void
|
||||
ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer,
|
||||
DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
const nsIntPoint& aOffset)
|
||||
{
|
||||
/**
|
||||
* Setup our temporary texture for rendering the contents of this container.
|
||||
*/
|
||||
GLuint containerSurface;
|
||||
GLuint frameBuffer;
|
||||
RGBLayerProgram *rgbProgram =
|
||||
static_cast<LayerManagerOGL*>(mManager)->GetRGBLayerProgram();
|
||||
ColorLayerProgram *colorProgram =
|
||||
static_cast<LayerManagerOGL*>(mManager)->GetColorLayerProgram();
|
||||
YCbCrLayerProgram *yCbCrProgram =
|
||||
static_cast<LayerManagerOGL*>(mManager)->GetYCbCrLayerProgram();
|
||||
|
||||
nsIntPoint childOffset(aOffset);
|
||||
bool needsFramebuffer = false;
|
||||
|
||||
float opacity = GetOpacity();
|
||||
if (opacity != 1.0) {
|
||||
gl()->fGenTextures(1, &containerSurface);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, containerSurface);
|
||||
gl()->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
mVisibleRect.width,
|
||||
mVisibleRect.height,
|
||||
0,
|
||||
LOCAL_GL_BGRA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
NULL);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
|
||||
/**
|
||||
* Create the framebuffer and bind it to make our content render into our
|
||||
* framebuffer.
|
||||
*/
|
||||
gl()->fGenFramebuffers(1, &frameBuffer);
|
||||
gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, frameBuffer);
|
||||
gl()->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_COLOR_ATTACHMENT0,
|
||||
LOCAL_GL_TEXTURE_2D,
|
||||
containerSurface,
|
||||
0);
|
||||
|
||||
NS_ASSERTION(
|
||||
gl()->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) ==
|
||||
LOCAL_GL_FRAMEBUFFER_COMPLETE, "Error setting up framebuffer.");
|
||||
|
||||
/**
|
||||
* Store old shader program variables and set the ones used for rendering
|
||||
* this container's content.
|
||||
*/
|
||||
|
||||
rgbProgram->Activate();
|
||||
rgbProgram->PushRenderTargetOffset((GLfloat)GetVisibleRect().x, (GLfloat)GetVisibleRect().y);
|
||||
|
||||
colorProgram->Activate();
|
||||
colorProgram->PushRenderTargetOffset((GLfloat)GetVisibleRect().x, (GLfloat)GetVisibleRect().y);
|
||||
|
||||
yCbCrProgram->Activate();
|
||||
yCbCrProgram->PushRenderTargetOffset((GLfloat)GetVisibleRect().x, (GLfloat)GetVisibleRect().y);
|
||||
mOGLManager->CreateFBOWithTexture(mVisibleRect.width,
|
||||
mVisibleRect.height,
|
||||
&frameBuffer,
|
||||
&containerSurface);
|
||||
childOffset.x = mVisibleRect.x;
|
||||
childOffset.y = mVisibleRect.y;
|
||||
} else {
|
||||
frameBuffer = aPreviousFrameBuffer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render this container's contents.
|
||||
*/
|
||||
|
@ -210,15 +169,16 @@ ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer,
|
|||
while (layerToRender) {
|
||||
const nsIntRect *clipRect = layerToRender->GetLayer()->GetClipRect();
|
||||
if (clipRect) {
|
||||
gl()->fScissor(clipRect->x - GetVisibleRect().x,
|
||||
clipRect->y - GetVisibleRect().y,
|
||||
clipRect->width,
|
||||
clipRect->height);
|
||||
gl()->fScissor(clipRect->x - mVisibleRect.x,
|
||||
clipRect->y - mVisibleRect.y,
|
||||
clipRect->width,
|
||||
clipRect->height);
|
||||
} else {
|
||||
gl()->fScissor(0, 0, GetVisibleRect().width, GetVisibleRect().height);
|
||||
gl()->fScissor(0, 0, mVisibleRect.width, mVisibleRect.height);
|
||||
}
|
||||
|
||||
layerToRender->RenderLayer(frameBuffer, aCallback, aCallbackData);
|
||||
layerToRender->RenderLayer(frameBuffer, childOffset);
|
||||
|
||||
layerToRender = layerToRender->GetNextSibling();
|
||||
}
|
||||
|
||||
|
@ -227,44 +187,36 @@ ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer,
|
|||
gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer);
|
||||
gl()->fDeleteFramebuffers(1, &frameBuffer);
|
||||
|
||||
// Restore old shader program variables.
|
||||
yCbCrProgram->Activate();
|
||||
yCbCrProgram->PopRenderTargetOffset();
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
|
||||
colorProgram->Activate();
|
||||
colorProgram->PopRenderTargetOffset();
|
||||
gl()->fBindTexture(mOGLManager->FBOTextureTarget(), containerSurface);
|
||||
|
||||
rgbProgram->Activate();
|
||||
rgbProgram->PopRenderTargetOffset();
|
||||
ColorTextureLayerProgram *rgb = mOGLManager->GetFBOLayerProgram();
|
||||
|
||||
/**
|
||||
* Render the contents of this container to our destination.
|
||||
*/
|
||||
float quadTransform[4][4];
|
||||
/*
|
||||
* Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
|
||||
* and size.
|
||||
*/
|
||||
memset(&quadTransform, 0, sizeof(quadTransform));
|
||||
quadTransform[0][0] = (float)GetVisibleRect().width;
|
||||
quadTransform[1][1] = (float)GetVisibleRect().height;
|
||||
quadTransform[2][2] = 1.0f;
|
||||
quadTransform[3][0] = (float)GetVisibleRect().x;
|
||||
quadTransform[3][1] = (float)GetVisibleRect().y;
|
||||
quadTransform[3][3] = 1.0f;
|
||||
rgb->Activate();
|
||||
rgb->SetLayerQuadRect(mVisibleRect);
|
||||
rgb->SetLayerTransform(mTransform);
|
||||
rgb->SetLayerOpacity(opacity);
|
||||
rgb->SetRenderOffset(aOffset);
|
||||
rgb->SetTextureUnit(0);
|
||||
|
||||
rgbProgram->SetLayerQuadTransform(&quadTransform[0][0]);
|
||||
if (rgb->GetTexCoordMultiplierUniformLocation() != -1) {
|
||||
// 2DRect case, get the multiplier right for a sampler2DRect
|
||||
float f[] = { float(mVisibleRect.width), float(mVisibleRect.height) };
|
||||
rgb->SetUniform(rgb->GetTexCoordMultiplierUniformLocation(),
|
||||
2, f);
|
||||
}
|
||||
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, containerSurface);
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
|
||||
rgbProgram->SetLayerOpacity(opacity);
|
||||
rgbProgram->SetLayerTransform(&mTransform._11);
|
||||
rgbProgram->Apply();
|
||||
mOGLManager->BindAndDrawQuad(rgb);
|
||||
|
||||
gl()->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
|
||||
// Clean up resources.
|
||||
// Clean up resources. This also unbinds the texture.
|
||||
gl()->fDeleteTextures(1, &containerSurface);
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,9 +69,8 @@ public:
|
|||
|
||||
PRBool IsEmpty();
|
||||
|
||||
void RenderLayer(int aPreviousFrameBuffer,
|
||||
DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset);
|
||||
private:
|
||||
nsIntRect mVisibleRect;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Bas Schouten <bschouten@mozilla.org>
|
||||
* Vladimir Vukicevic <vladimir@pobox.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -269,15 +270,13 @@ ImageLayerOGL::GetLayer()
|
|||
}
|
||||
|
||||
void
|
||||
ImageLayerOGL::RenderLayer(int, DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
ImageLayerOGL::RenderLayer(int,
|
||||
const nsIntPoint& aOffset)
|
||||
{
|
||||
if (!GetContainer()) {
|
||||
if (!GetContainer())
|
||||
return;
|
||||
}
|
||||
|
||||
LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(mManager);
|
||||
manager->MakeCurrent();
|
||||
mOGLManager->MakeCurrent();
|
||||
|
||||
nsRefPtr<Image> image = GetContainer()->GetCurrentImage();
|
||||
|
||||
|
@ -285,28 +284,12 @@ ImageLayerOGL::RenderLayer(int, DrawThebesLayerCallback aCallback,
|
|||
PlanarYCbCrImageOGL *yuvImage =
|
||||
static_cast<PlanarYCbCrImageOGL*>(image.get());
|
||||
|
||||
if (!yuvImage->HasData()) {
|
||||
if (!yuvImage->HasData())
|
||||
return;
|
||||
}
|
||||
|
||||
if (!yuvImage->HasTextures()) {
|
||||
yuvImage->AllocateTextures(manager);
|
||||
}
|
||||
if (!yuvImage->HasTextures())
|
||||
yuvImage->AllocateTextures(mOGLManager);
|
||||
|
||||
float quadTransform[4][4];
|
||||
// Transform the quad to the size of the video.
|
||||
memset(&quadTransform, 0, sizeof(quadTransform));
|
||||
quadTransform[0][0] = (float)yuvImage->mSize.width;
|
||||
quadTransform[1][1] = (float)yuvImage->mSize.height;
|
||||
quadTransform[2][2] = 1.0f;
|
||||
quadTransform[3][3] = 1.0f;
|
||||
|
||||
YCbCrLayerProgram *program = manager->GetYCbCrLayerProgram();
|
||||
|
||||
program->Activate();
|
||||
|
||||
program->SetLayerQuadTransform(&quadTransform[0][0]);
|
||||
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, yuvImage->mTextures[0].GetTextureID());
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE1);
|
||||
|
@ -314,40 +297,46 @@ ImageLayerOGL::RenderLayer(int, DrawThebesLayerCallback aCallback,
|
|||
gl()->fActiveTexture(LOCAL_GL_TEXTURE2);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, yuvImage->mTextures[2].GetTextureID());
|
||||
|
||||
YCbCrTextureLayerProgram *program = mOGLManager->GetYCbCrLayerProgram();
|
||||
|
||||
program->Activate();
|
||||
program->SetLayerQuadRect(nsIntRect(0, 0,
|
||||
yuvImage->mSize.width,
|
||||
yuvImage->mSize.height));
|
||||
program->SetLayerTransform(mTransform);
|
||||
program->SetLayerOpacity(GetOpacity());
|
||||
program->SetLayerTransform(&mTransform._11);
|
||||
program->Apply();
|
||||
program->SetRenderOffset(aOffset);
|
||||
program->SetYCbCrTextureUnits(0, 1, 2);
|
||||
|
||||
gl()->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
|
||||
mOGLManager->BindAndDrawQuad(program);
|
||||
|
||||
// We shouldn't need to do this, but do it anyway just in case
|
||||
// someone else forgets.
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
|
||||
} else if (image->GetFormat() == Image::CAIRO_SURFACE) {
|
||||
CairoImageOGL *cairoImage =
|
||||
static_cast<CairoImageOGL*>(image.get());
|
||||
|
||||
float quadTransform[4][4];
|
||||
// Transform the quad to the size of the video.
|
||||
memset(&quadTransform, 0, sizeof(quadTransform));
|
||||
quadTransform[0][0] = (float)cairoImage->mSize.width;
|
||||
quadTransform[1][1] = (float)cairoImage->mSize.height;
|
||||
quadTransform[2][2] = 1.0f;
|
||||
quadTransform[3][3] = 1.0f;
|
||||
|
||||
RGBLayerProgram *program = manager->GetRGBLayerProgram();
|
||||
|
||||
program->Activate();
|
||||
|
||||
program->SetLayerQuadTransform(&quadTransform[0][0]);
|
||||
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, cairoImage->mTexture.GetTextureID());
|
||||
program->SetLayerOpacity(GetOpacity());
|
||||
program->SetLayerTransform(&mTransform._11);
|
||||
program->Apply();
|
||||
|
||||
ColorTextureLayerProgram *program = mOGLManager->GetBGRALayerProgram();
|
||||
|
||||
gl()->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
|
||||
program->Activate();
|
||||
program->SetLayerQuadRect(nsIntRect(0, 0,
|
||||
cairoImage->mSize.width,
|
||||
cairoImage->mSize.height));
|
||||
program->SetLayerTransform(mTransform);
|
||||
program->SetLayerOpacity(GetOpacity());
|
||||
program->SetRenderOffset(aOffset);
|
||||
program->SetTextureUnit(0);
|
||||
|
||||
mOGLManager->BindAndDrawQuad(program);
|
||||
}
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
}
|
||||
|
||||
PlanarYCbCrImageOGL::PlanarYCbCrImageOGL(RecycleBin *aRecycleBin)
|
||||
|
@ -552,6 +541,8 @@ CairoImageOGL::SetData(const CairoImage::Data &aData)
|
|||
|
||||
// XXX This could be a lot more efficient if we already have an image-compatible
|
||||
// surface
|
||||
// XXX if we ever create an ImageFormatRGB24 surface, make sure that we use
|
||||
// a BGRX program in that case (instead of BGRA)
|
||||
nsRefPtr<gfxImageSurface> imageSurface =
|
||||
new gfxImageSurface(aData.mSize, gfxASurface::ImageFormatARGB32);
|
||||
nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
|
||||
|
@ -559,6 +550,7 @@ CairoImageOGL::SetData(const CairoImage::Data &aData)
|
|||
context->SetSource(aData.mSurface);
|
||||
context->Paint();
|
||||
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture.GetTextureID());
|
||||
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
|
@ -572,7 +564,7 @@ CairoImageOGL::SetData(const CairoImage::Data &aData)
|
|||
mSize.width,
|
||||
mSize.height,
|
||||
0,
|
||||
LOCAL_GL_BGRA,
|
||||
LOCAL_GL_RGBA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
imageSurface->Data());
|
||||
}
|
||||
|
|
|
@ -175,9 +175,8 @@ public:
|
|||
|
||||
virtual Layer* GetLayer();
|
||||
|
||||
virtual void RenderLayer(int aPreviousDestination,
|
||||
DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset);
|
||||
};
|
||||
|
||||
class THEBES_API PlanarYCbCrImageOGL : public PlanarYCbCrImage
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -20,6 +20,8 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Bas Schouten <bschouten@mozilla.org>
|
||||
* Frederic Plourde <frederic.plourde@collabora.co.uk>
|
||||
* Vladimir Vukicevic <vladimir@pobox.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -57,126 +59,17 @@ typedef int GLsizei;
|
|||
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
||||
|
||||
#include "gfxContext.h"
|
||||
#include "gfx3DMatrix.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "GLContext.h"
|
||||
|
||||
#include "LayerManagerOGLProgram.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class LayerOGL;
|
||||
|
||||
struct GLvec2
|
||||
{
|
||||
GLfloat mX;
|
||||
GLfloat mY;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class for Layer Programs.
|
||||
*/
|
||||
class LayerProgram
|
||||
{
|
||||
public:
|
||||
LayerProgram();
|
||||
virtual ~LayerProgram();
|
||||
|
||||
PRBool Initialize(GLuint aVertexShader,
|
||||
GLuint aFragmentShader,
|
||||
mozilla::gl::GLContext *aContext);
|
||||
|
||||
virtual void UpdateLocations();
|
||||
|
||||
void Activate();
|
||||
|
||||
void SetMatrixUniform(GLint aLocation, const GLfloat *aValue);
|
||||
void SetInt(GLint aLocation, GLint aValue);
|
||||
void SetColor(GLint aLocation, const gfxRGBA& aColor);
|
||||
|
||||
void SetMatrixProj(GLfloat *aValue)
|
||||
{
|
||||
SetMatrixUniform(mMatrixProjLocation, aValue);
|
||||
}
|
||||
|
||||
void SetLayerQuadTransform(GLfloat *aValue)
|
||||
{
|
||||
SetMatrixUniform(mLayerQuadTransformLocation, aValue);
|
||||
}
|
||||
|
||||
void SetLayerTransform(const GLfloat *aValue)
|
||||
{
|
||||
SetMatrixUniform(mLayerTransformLocation, aValue);
|
||||
}
|
||||
|
||||
void SetLayerOpacity(GLfloat aValue);
|
||||
|
||||
void PushRenderTargetOffset(GLfloat aValueX, GLfloat aValueY);
|
||||
void PopRenderTargetOffset();
|
||||
|
||||
void Apply();
|
||||
|
||||
protected:
|
||||
mozilla::gl::GLContext *mGLContext;
|
||||
|
||||
GLuint mProgram;
|
||||
GLint mMatrixProjLocation;
|
||||
GLint mLayerQuadTransformLocation;
|
||||
GLint mLayerTransformLocation;
|
||||
GLint mRenderTargetOffsetLocation;
|
||||
GLint mLayerOpacityLocation;
|
||||
|
||||
nsTArray<GLvec2> mRenderTargetOffsetStack;
|
||||
};
|
||||
|
||||
class RGBLayerProgram : public LayerProgram
|
||||
{
|
||||
public:
|
||||
void UpdateLocations();
|
||||
|
||||
void SetLayerTexture(GLint aValue)
|
||||
{
|
||||
SetInt(mLayerTextureLocation, aValue);
|
||||
}
|
||||
protected:
|
||||
GLint mLayerTextureLocation;
|
||||
};
|
||||
|
||||
class ColorLayerProgram : public LayerProgram
|
||||
{
|
||||
public:
|
||||
void UpdateLocations();
|
||||
|
||||
void SetLayerColor(const gfxRGBA& aColor)
|
||||
{
|
||||
SetColor(mRenderColorLocation, aColor);
|
||||
}
|
||||
|
||||
protected:
|
||||
GLint mRenderColorLocation;
|
||||
};
|
||||
|
||||
class YCbCrLayerProgram : public LayerProgram
|
||||
{
|
||||
public:
|
||||
void UpdateLocations();
|
||||
|
||||
void SetYTexture(GLint aValue)
|
||||
{
|
||||
SetInt(mYTextureLocation, aValue);
|
||||
}
|
||||
void SetCbTexture(GLint aValue)
|
||||
{
|
||||
SetInt(mCbTextureLocation, aValue);
|
||||
}
|
||||
void SetCrTexture(GLint aValue)
|
||||
{
|
||||
SetInt(mCrTextureLocation, aValue);
|
||||
}
|
||||
protected:
|
||||
GLint mYTextureLocation;
|
||||
GLint mCbTextureLocation;
|
||||
GLint mCrTextureLocation;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is the LayerManager used for OpenGL 2.1. For now this will render on
|
||||
* the main thread.
|
||||
|
@ -185,7 +78,7 @@ class THEBES_API LayerManagerOGL : public LayerManager {
|
|||
public:
|
||||
LayerManagerOGL(nsIWidget *aWidget);
|
||||
virtual ~LayerManagerOGL();
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the layer manager, this is when the layer manager will
|
||||
* actually access the device and attempt to create the swap chain used
|
||||
|
@ -238,18 +131,134 @@ public:
|
|||
/**
|
||||
* Helper methods.
|
||||
*/
|
||||
void SetClippingEnabled(PRBool aEnabled);
|
||||
|
||||
void MakeCurrent();
|
||||
|
||||
RGBLayerProgram *GetRGBLayerProgram() { return mRGBLayerProgram; }
|
||||
ColorLayerProgram *GetColorLayerProgram() { return mColorLayerProgram; }
|
||||
YCbCrLayerProgram *GetYCbCrLayerProgram() { return mYCbCrLayerProgram; }
|
||||
ColorTextureLayerProgram *GetRGBALayerProgram() {
|
||||
return static_cast<ColorTextureLayerProgram*>(mPrograms[RGBALayerProgramType]);
|
||||
}
|
||||
ColorTextureLayerProgram *GetBGRALayerProgram() {
|
||||
return static_cast<ColorTextureLayerProgram*>(mPrograms[BGRALayerProgramType]);
|
||||
}
|
||||
ColorTextureLayerProgram *GetRGBXLayerProgram() {
|
||||
return static_cast<ColorTextureLayerProgram*>(mPrograms[RGBXLayerProgramType]);
|
||||
}
|
||||
ColorTextureLayerProgram *GetBGRXLayerProgram() {
|
||||
return static_cast<ColorTextureLayerProgram*>(mPrograms[BGRXLayerProgramType]);
|
||||
}
|
||||
ColorTextureLayerProgram *GetRGBARectLayerProgram() {
|
||||
return static_cast<ColorTextureLayerProgram*>(mPrograms[RGBARectLayerProgramType]);
|
||||
}
|
||||
SolidColorLayerProgram *GetColorLayerProgram() {
|
||||
return static_cast<SolidColorLayerProgram*>(mPrograms[ColorLayerProgramType]);
|
||||
}
|
||||
YCbCrTextureLayerProgram *GetYCbCrLayerProgram() {
|
||||
return static_cast<YCbCrTextureLayerProgram*>(mPrograms[YCbCrLayerProgramType]);
|
||||
}
|
||||
CopyProgram *GetCopy2DProgram() {
|
||||
return static_cast<CopyProgram*>(mPrograms[Copy2DProgramType]);
|
||||
}
|
||||
CopyProgram *GetCopy2DRectProgram() {
|
||||
return static_cast<CopyProgram*>(mPrograms[Copy2DRectProgramType]);
|
||||
}
|
||||
|
||||
ColorTextureLayerProgram *GetFBOLayerProgram() {
|
||||
if (mFBOTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB)
|
||||
return static_cast<ColorTextureLayerProgram*>(mPrograms[RGBARectLayerProgramType]);
|
||||
return static_cast<ColorTextureLayerProgram*>(mPrograms[RGBALayerProgramType]);
|
||||
}
|
||||
|
||||
typedef mozilla::gl::GLContext GLContext;
|
||||
|
||||
GLContext *gl() const { return mGLContext; }
|
||||
|
||||
/*
|
||||
* Helper functions for our layers
|
||||
*/
|
||||
void CallThebesLayerDrawCallback(ThebesLayer* aLayer,
|
||||
gfxContext* aContext,
|
||||
const nsIntRegion& aRegionToDraw)
|
||||
{
|
||||
NS_ASSERTION(mThebesLayerCallback,
|
||||
"CallThebesLayerDrawCallback without callback!");
|
||||
mThebesLayerCallback(aLayer, aContext,
|
||||
aRegionToDraw, mThebesLayerCallbackData);
|
||||
}
|
||||
|
||||
GLenum FBOTextureTarget() { return mFBOTextureTarget; }
|
||||
|
||||
/* Create a FBO backed by a texture; will leave the FBO
|
||||
* bound. Note that the texture target type will be
|
||||
* of the type returned by FBOTextureTarget; different
|
||||
* shaders are required to sample from the different
|
||||
* texture types.
|
||||
*/
|
||||
void CreateFBOWithTexture(int aWidth, int aHeight,
|
||||
GLuint *aFBO, GLuint *aTexture);
|
||||
|
||||
GLuint QuadVBO() { return mQuadVBO; }
|
||||
GLintptr QuadVBOVertexOffset() { return 0; }
|
||||
GLintptr QuadVBOTexCoordOffset() { return sizeof(float)*4*2; }
|
||||
GLintptr QuadVBOFlippedTexCoordOffset() { return sizeof(float)*8*2; }
|
||||
|
||||
void BindQuadVBO() {
|
||||
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO);
|
||||
}
|
||||
|
||||
void QuadVBOVerticesAttrib(GLuint aAttribIndex) {
|
||||
mGLContext->fVertexAttribPointer(aAttribIndex, 2,
|
||||
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
|
||||
(GLvoid*) QuadVBOVertexOffset());
|
||||
}
|
||||
|
||||
void QuadVBOTexCoordsAttrib(GLuint aAttribIndex) {
|
||||
mGLContext->fVertexAttribPointer(aAttribIndex, 2,
|
||||
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
|
||||
(GLvoid*) QuadVBOTexCoordOffset());
|
||||
}
|
||||
|
||||
void QuadVBOFlippedTexCoordsAttrib(GLuint aAttribIndex) {
|
||||
mGLContext->fVertexAttribPointer(aAttribIndex, 2,
|
||||
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
|
||||
(GLvoid*) QuadVBOFlippedTexCoordOffset());
|
||||
}
|
||||
|
||||
// Super common
|
||||
|
||||
void BindAndDrawQuad(GLuint aVertAttribIndex,
|
||||
GLuint aTexCoordAttribIndex,
|
||||
bool aFlipped = false)
|
||||
{
|
||||
BindQuadVBO();
|
||||
QuadVBOVerticesAttrib(aVertAttribIndex);
|
||||
|
||||
if (aTexCoordAttribIndex != -1) {
|
||||
if (aFlipped)
|
||||
QuadVBOFlippedTexCoordsAttrib(aTexCoordAttribIndex);
|
||||
else
|
||||
QuadVBOTexCoordsAttrib(aTexCoordAttribIndex);
|
||||
|
||||
mGLContext->fEnableVertexAttribArray(aTexCoordAttribIndex);
|
||||
}
|
||||
|
||||
mGLContext->fEnableVertexAttribArray(aVertAttribIndex);
|
||||
|
||||
mGLContext->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
mGLContext->fDisableVertexAttribArray(aVertAttribIndex);
|
||||
|
||||
if (aTexCoordAttribIndex != -1) {
|
||||
mGLContext->fDisableVertexAttribArray(aTexCoordAttribIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void BindAndDrawQuad(LayerProgram *aProg,
|
||||
bool aFlipped = false)
|
||||
{
|
||||
BindAndDrawQuad(aProg->AttribLocation(LayerProgram::VertexAttrib),
|
||||
aProg->AttribLocation(LayerProgram::TexCoordAttrib),
|
||||
aFlipped);
|
||||
}
|
||||
|
||||
private:
|
||||
/** Widget associated with this layer manager */
|
||||
nsIWidget *mWidget;
|
||||
|
@ -260,56 +269,80 @@ private:
|
|||
|
||||
nsRefPtr<GLContext> mGLContext;
|
||||
|
||||
/** Backbuffer */
|
||||
GLuint mBackBuffer;
|
||||
/** Backbuffer size */
|
||||
nsIntSize mBackBufferSize;
|
||||
/** Framebuffer */
|
||||
GLuint mFrameBuffer;
|
||||
/** RGB Layer Program */
|
||||
RGBLayerProgram *mRGBLayerProgram;
|
||||
/** Color Layer Program */
|
||||
ColorLayerProgram *mColorLayerProgram;
|
||||
/** YUV Layer Program */
|
||||
YCbCrLayerProgram *mYCbCrLayerProgram;
|
||||
/** Vertex Shader */
|
||||
GLuint mVertexShader;
|
||||
/** RGB fragment shader */
|
||||
GLuint mRGBShader;
|
||||
/** Solid color shader */
|
||||
GLuint mColorShader;
|
||||
/** YUV fragment shader */
|
||||
GLuint mYUVShader;
|
||||
enum ProgramType {
|
||||
RGBALayerProgramType,
|
||||
BGRALayerProgramType,
|
||||
RGBXLayerProgramType,
|
||||
BGRXLayerProgramType,
|
||||
RGBARectLayerProgramType,
|
||||
ColorLayerProgramType,
|
||||
YCbCrLayerProgramType,
|
||||
Copy2DProgramType,
|
||||
Copy2DRectProgramType,
|
||||
NumProgramTypes
|
||||
};
|
||||
|
||||
static ProgramType sLayerProgramTypes[];
|
||||
|
||||
/** Current root layer. */
|
||||
LayerOGL *mRootLayer;
|
||||
/** Vertex buffer */
|
||||
GLuint mVBO;
|
||||
|
||||
/** Backbuffer */
|
||||
GLuint mBackBufferFBO;
|
||||
GLuint mBackBufferTexture;
|
||||
nsIntSize mBackBufferSize;
|
||||
|
||||
/** Shader Programs */
|
||||
nsTArray<LayerManagerOGLProgram*> mPrograms;
|
||||
|
||||
/** Texture target to use for FBOs */
|
||||
GLenum mFBOTextureTarget;
|
||||
|
||||
/**
|
||||
* Region we're clipping our current drawing to.
|
||||
*/
|
||||
/** VBO that has some basics in it for a textured quad,
|
||||
* including vertex coords and texcoords for both
|
||||
* flipped and unflipped textures */
|
||||
GLuint mQuadVBO;
|
||||
|
||||
/** Region we're clipping our current drawing to. */
|
||||
nsIntRegion mClippingRegion;
|
||||
|
||||
/** Misc */
|
||||
PRPackedBool mHasBGRA;
|
||||
|
||||
/**
|
||||
* Render the current layer tree to the active target.
|
||||
*/
|
||||
void Render(DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
void Render();
|
||||
/**
|
||||
* Setup the pipeline.
|
||||
* Setup the viewport and projection matrix for rendering
|
||||
* to a window of the given dimensions.
|
||||
*/
|
||||
void SetupPipeline();
|
||||
void SetupPipeline(int aWidth, int aHeight);
|
||||
/**
|
||||
* Setup the backbuffer.
|
||||
*
|
||||
* \return PR_TRUE if setup was succesful
|
||||
* Setup a backbuffer of the given dimensions.
|
||||
*/
|
||||
PRBool SetupBackBuffer();
|
||||
void SetupBackBuffer(int aWidth, int aHeight);
|
||||
/**
|
||||
* Copies the content of our backbuffer to the set transaction target.
|
||||
*/
|
||||
void CopyToTarget();
|
||||
|
||||
/**
|
||||
* Updates all layer programs with a new projection matrix.
|
||||
*
|
||||
* XXX we need a way to be able to delay setting this until
|
||||
* the program is actually used. Maybe a DelayedSetUniform
|
||||
* on Program, that will delay the set until the next Activate?
|
||||
*
|
||||
* XXX this is only called once per frame, so it's not awful.
|
||||
* If we have any more similar updates, then we should delay.
|
||||
*/
|
||||
void SetLayerProgramProjectionMatrix(const gfx3DMatrix& aMatrix);
|
||||
|
||||
/* Thebes layer callbacks; valid at the end of a transaciton,
|
||||
* while rendering */
|
||||
DrawThebesLayerCallback mThebesLayerCallback;
|
||||
void *mThebesLayerCallbackData;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -318,9 +351,9 @@ private:
|
|||
class LayerOGL
|
||||
{
|
||||
public:
|
||||
typedef LayerManager::DrawThebesLayerCallback DrawThebesLayerCallback;
|
||||
|
||||
LayerOGL(LayerManagerOGL *aManager);
|
||||
LayerOGL(LayerManagerOGL *aManager)
|
||||
: mOGLManager(aManager), mNextSibling(nsnull)
|
||||
{ }
|
||||
|
||||
enum LayerType {
|
||||
TYPE_THEBES,
|
||||
|
@ -332,16 +365,22 @@ public:
|
|||
|
||||
virtual LayerType GetType() = 0;
|
||||
|
||||
LayerOGL *GetNextSibling();
|
||||
virtual LayerOGL *GetFirstChildOGL() { return nsnull; }
|
||||
LayerOGL *GetNextSibling() {
|
||||
return mNextSibling;
|
||||
}
|
||||
|
||||
void SetNextSibling(LayerOGL *aParent);
|
||||
void SetFirstChild(LayerOGL *aParent);
|
||||
void SetNextSibling(LayerOGL *aSibling) {
|
||||
mNextSibling = aSibling;
|
||||
}
|
||||
|
||||
virtual LayerOGL *GetFirstChildOGL() {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
virtual Layer* GetLayer() = 0;
|
||||
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer, DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData) = 0;
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset) = 0;
|
||||
|
||||
typedef mozilla::gl::GLContext GLContext;
|
||||
|
||||
|
@ -351,6 +390,16 @@ protected:
|
|||
LayerOGL *mNextSibling;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUG_GL_ERROR_CHECK(cx) do { \
|
||||
/*fprintf (stderr, "trace %s %d\n", __FILE__, __LINE__);*/ \
|
||||
GLenum err = (cx)->fGetError(); \
|
||||
if (err) { fprintf (stderr, "GL ERROR: 0x%04x at %s:%d\n", err, __FILE__, __LINE__); } \
|
||||
} while (0)
|
||||
#else
|
||||
#define DEBUG_GL_ERROR_CHECK(cx) do { } while (0)
|
||||
#endif
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
|
||||
|
|
|
@ -0,0 +1,764 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef GFX_LAYERMANAGEROGLPROGRAM_H
|
||||
#define GFX_LAYERMANAGEROGLPROGRAM_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "prenv.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "GLContext.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
#define ASSERT_THIS_PROGRAM \
|
||||
do { \
|
||||
NS_ASSERTION(mGL->GetUserData(&sCurrentProgramKey) == this, \
|
||||
"SetUniform with wrong program active!"); \
|
||||
} while (0)
|
||||
|
||||
struct UniformValue {
|
||||
UniformValue() {
|
||||
memset(this, 0, sizeof(UniformValue));
|
||||
}
|
||||
|
||||
void setInt(const int i) {
|
||||
value.i[0] = i;
|
||||
}
|
||||
|
||||
void setFloat(const float f) {
|
||||
value.f[0] = f;
|
||||
}
|
||||
|
||||
void setFloatN(const float *f, const int n) {
|
||||
memcpy(value.f, f, sizeof(float)*n);
|
||||
}
|
||||
|
||||
void setColor(const gfxRGBA& c) {
|
||||
value.f[0] = float(c.r);
|
||||
value.f[1] = float(c.g);
|
||||
value.f[2] = float(c.b);
|
||||
value.f[3] = float(c.a);
|
||||
}
|
||||
|
||||
bool equalsInt(const int i) {
|
||||
return i == value.i[0];
|
||||
}
|
||||
|
||||
bool equalsFloat(const float f) {
|
||||
return f == value.f[0];
|
||||
}
|
||||
|
||||
bool equalsFloatN(const float *f, const int n) {
|
||||
return memcmp(f, value.f, sizeof(float)*n) == 0;
|
||||
}
|
||||
|
||||
bool equalsColor(const gfxRGBA& c) {
|
||||
return value.f[0] == float(c.r) &&
|
||||
value.f[1] == float(c.g) &&
|
||||
value.f[2] == float(c.b) &&
|
||||
value.f[3] == float(c.a);
|
||||
}
|
||||
|
||||
union {
|
||||
int i[1];
|
||||
float f[16];
|
||||
} value;
|
||||
};
|
||||
|
||||
class LayerManagerOGLProgram {
|
||||
protected:
|
||||
static int sCurrentProgramKey;
|
||||
|
||||
public:
|
||||
typedef mozilla::gl::GLContext GLContext;
|
||||
|
||||
// common attrib locations
|
||||
enum {
|
||||
VertexAttrib = 0,
|
||||
TexCoordAttrib = 1
|
||||
};
|
||||
|
||||
LayerManagerOGLProgram(GLContext *aGL)
|
||||
: mGL(aGL), mProgram(0)
|
||||
{ }
|
||||
|
||||
virtual ~LayerManagerOGLProgram() { }
|
||||
|
||||
void Activate() {
|
||||
NS_ASSERTION(mProgram != 0, "Attempting to activate a program that's not in use!");
|
||||
mGL->fUseProgram(mProgram);
|
||||
mGL->SetUserData(&sCurrentProgramKey, this);
|
||||
}
|
||||
|
||||
void SetUniform(GLuint aUniform, float aFloatValue) {
|
||||
ASSERT_THIS_PROGRAM;
|
||||
|
||||
if (aUniform == -1)
|
||||
return;
|
||||
|
||||
if (!mUniformValues[aUniform].equalsFloat(aFloatValue)) {
|
||||
mGL->fUniform1f(aUniform, aFloatValue);
|
||||
mUniformValues[aUniform].setFloat(aFloatValue);
|
||||
}
|
||||
}
|
||||
|
||||
void SetUniform(GLuint aUniform, const gfxRGBA& aColor) {
|
||||
ASSERT_THIS_PROGRAM;
|
||||
|
||||
if (aUniform == -1)
|
||||
return;
|
||||
|
||||
if (!mUniformValues[aUniform].equalsColor(aColor)) {
|
||||
mGL->fUniform4f(aUniform, float(aColor.r), float(aColor.g), float(aColor.b), float(aColor.a));
|
||||
mUniformValues[aUniform].setColor(aColor);
|
||||
}
|
||||
}
|
||||
|
||||
void SetUniform(GLuint aUniform, int aLength, float *aFloatValues) {
|
||||
ASSERT_THIS_PROGRAM;
|
||||
|
||||
if (aUniform == -1)
|
||||
return;
|
||||
|
||||
if (!mUniformValues[aUniform].equalsFloatN(aFloatValues, aLength)) {
|
||||
if (aLength == 1) {
|
||||
mGL->fUniform1fv(aUniform, 1, aFloatValues);
|
||||
} else if (aLength == 2) {
|
||||
mGL->fUniform2fv(aUniform, 1, aFloatValues);
|
||||
} else if (aLength == 3) {
|
||||
mGL->fUniform3fv(aUniform, 1, aFloatValues);
|
||||
} else if (aLength == 4) {
|
||||
mGL->fUniform4fv(aUniform, 1, aFloatValues);
|
||||
} else {
|
||||
NS_NOTREACHED("Bogus aLength param");
|
||||
}
|
||||
mUniformValues[aUniform].setFloatN(aFloatValues, aLength);
|
||||
}
|
||||
}
|
||||
|
||||
void SetUniform(GLuint aUniform, GLint aIntValue) {
|
||||
ASSERT_THIS_PROGRAM;
|
||||
|
||||
if (aUniform == -1)
|
||||
return;
|
||||
|
||||
if (!mUniformValues[aUniform].equalsInt(aIntValue)) {
|
||||
mGL->fUniform1i(aUniform, aIntValue);
|
||||
mUniformValues[aUniform].setInt(aIntValue);
|
||||
}
|
||||
}
|
||||
|
||||
void SetMatrixUniform(GLuint aUniform, const float *aFloatValues) {
|
||||
ASSERT_THIS_PROGRAM;
|
||||
|
||||
if (aUniform == -1)
|
||||
return;
|
||||
|
||||
if (!mUniformValues[aUniform].equalsFloatN(aFloatValues, 16)) {
|
||||
mGL->fUniformMatrix4fv(aUniform, 1, false, aFloatValues);
|
||||
mUniformValues[aUniform].setFloatN(aFloatValues, 16);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
GLContext *mGL;
|
||||
|
||||
GLuint mProgram;
|
||||
GLuint mFragmentShader;
|
||||
GLuint mVertexShader;
|
||||
|
||||
nsTArray<UniformValue> mUniformValues;
|
||||
|
||||
GLint CreateShader(GLenum aShaderType,
|
||||
const char *aShaderSource)
|
||||
{
|
||||
GLint success, len = 0;
|
||||
|
||||
GLint sh = mGL->fCreateShader(aShaderType);
|
||||
mGL->fShaderSource(sh, 1, (const GLchar**)&aShaderSource, NULL);
|
||||
mGL->fCompileShader(sh);
|
||||
mGL->fGetShaderiv(sh, LOCAL_GL_COMPILE_STATUS, &success);
|
||||
mGL->fGetShaderiv(sh, LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
|
||||
/* Even if compiling is successful, there may still be warnings. Print them
|
||||
* in a debug build. The > 10 is to catch silly compilers that might put
|
||||
* some whitespace in the log but otherwise leave it empty.
|
||||
*/
|
||||
if (!success
|
||||
#ifdef DEBUG
|
||||
|| (len > 10 && PR_GetEnv("MOZ_DEBUG_SHADERS"))
|
||||
#endif
|
||||
)
|
||||
{
|
||||
nsCAutoString log;
|
||||
log.SetCapacity(len);
|
||||
mGL->fGetShaderInfoLog(sh, len, (GLint*) &len, (char*) log.BeginWriting());
|
||||
log.SetLength(len);
|
||||
|
||||
if (!success) {
|
||||
fprintf (stderr, "=== SHADER COMPILATION FAILED ===\n");
|
||||
} else {
|
||||
fprintf (stderr, "=== SHADER COMPILATION WARNINGS ===\n");
|
||||
}
|
||||
|
||||
fprintf (stderr, "=== Source:\n%s\n", aShaderSource);
|
||||
fprintf (stderr, "=== Log:\n%s\n", nsPromiseFlatCString(log).get());
|
||||
fprintf (stderr, "============\n");
|
||||
|
||||
if (!success) {
|
||||
mGL->fDeleteShader(sh);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return sh;
|
||||
}
|
||||
|
||||
bool CreateProgram(const char *aVertexShaderString,
|
||||
const char *aFragmentShaderString)
|
||||
{
|
||||
mVertexShader = CreateShader(LOCAL_GL_VERTEX_SHADER, aVertexShaderString);
|
||||
mFragmentShader = CreateShader(LOCAL_GL_FRAGMENT_SHADER, aFragmentShaderString);
|
||||
|
||||
if (!mVertexShader || !mFragmentShader)
|
||||
return false;
|
||||
|
||||
mProgram = mGL->fCreateProgram();
|
||||
mGL->fAttachShader(mProgram, mVertexShader);
|
||||
mGL->fAttachShader(mProgram, mFragmentShader);
|
||||
|
||||
// bind common attribs to consistent indices
|
||||
mGL->fBindAttribLocation(mProgram, VertexAttrib, "aVertex");
|
||||
mGL->fBindAttribLocation(mProgram, TexCoordAttrib, "aTexCoord");
|
||||
|
||||
mGL->fLinkProgram(mProgram);
|
||||
|
||||
GLint success, len;
|
||||
mGL->fGetProgramiv(mProgram, LOCAL_GL_LINK_STATUS, &success);
|
||||
mGL->fGetProgramiv(mProgram, LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
|
||||
/* Even if linking is successful, there may still be warnings. Print them
|
||||
* in a debug build. The > 10 is to catch silly compilers that might put
|
||||
* some whitespace in the log but otherwise leave it empty.
|
||||
*/
|
||||
if (!success
|
||||
#ifdef DEBUG
|
||||
|| (len > 10 && PR_GetEnv("MOZ_DEBUG_SHADERS"))
|
||||
#endif
|
||||
)
|
||||
{
|
||||
nsCAutoString log;
|
||||
log.SetCapacity(len);
|
||||
mGL->fGetProgramInfoLog(mProgram, len, (GLint*) &len, (char*) log.BeginWriting());
|
||||
log.SetLength(len);
|
||||
|
||||
if (!success) {
|
||||
fprintf (stderr, "=== PROGRAM LINKING FAILED ===\n");
|
||||
} else {
|
||||
fprintf (stderr, "=== PROGRAM LINKING WARNINGS ===\n");
|
||||
}
|
||||
fprintf (stderr, "=== Log:\n%s\n", nsPromiseFlatCString(log).get());
|
||||
fprintf (stderr, "============\n");
|
||||
|
||||
if (!success) {
|
||||
mGL->fDeleteProgram(mProgram);
|
||||
mGL->fDeleteShader(mVertexShader);
|
||||
mGL->fDeleteShader(mFragmentShader);
|
||||
|
||||
mProgram = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Now query uniforms, so that we can initialize mUniformValues
|
||||
// note that for simplicity, mUniformLocations is indexed by the
|
||||
// uniform -location-, and not the uniform -index-. This means
|
||||
// that it might have a bunch of unused space as locations dense
|
||||
// like indices are; however, there are unlikely to be enough for
|
||||
// our shaders for this to become a significant memory issue.
|
||||
GLint count, maxnamelen;
|
||||
nsCAutoString uname;
|
||||
GLint maxloc = 0;
|
||||
mGL->fGetProgramiv(mProgram, LOCAL_GL_ACTIVE_UNIFORMS, &count);
|
||||
mGL->fGetProgramiv(mProgram, LOCAL_GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxnamelen);
|
||||
uname.SetCapacity(maxnamelen);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
GLsizei namelen;
|
||||
GLint usize;
|
||||
GLenum utype;
|
||||
|
||||
mGL->fGetActiveUniform(mProgram, i, maxnamelen, &namelen, &usize, &utype, uname.BeginWriting());
|
||||
uname.SetLength(namelen);
|
||||
GLint uloc = mGL->fGetUniformLocation(mProgram, uname.BeginReading());
|
||||
if (maxloc < uloc)
|
||||
maxloc = uloc;
|
||||
}
|
||||
|
||||
// Note +1: the last valid index needs to be 'maxloc', so we need
|
||||
// to set the array length to 1 more than that.
|
||||
mUniformValues.SetLength(maxloc+1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GetAttribLocations(const char **aAttribNames,
|
||||
GLint *aAttribLocations)
|
||||
{
|
||||
NS_ASSERTION(mProgram != 0, "GetAttribLocations called with no program!");
|
||||
|
||||
for (int i = 0; aAttribNames[i] != nsnull; ++i) {
|
||||
aAttribLocations[i] = mGL->fGetAttribLocation(mProgram, aAttribNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void GetUniformLocations(const char **aUniformNames,
|
||||
GLint *aUniformLocations)
|
||||
{
|
||||
NS_ASSERTION(mProgram != 0, "GetUniformLocations called with no program!");
|
||||
|
||||
for (int i = 0; aUniformNames[i] != nsnull; ++i) {
|
||||
aUniformLocations[i] = mGL->fGetUniformLocation(mProgram, aUniformNames[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* A LayerProgram is the base of all further LayerPrograms.
|
||||
*
|
||||
* It has a number of attributes and uniforms common to all layer programs.
|
||||
*
|
||||
* Attribute inputs:
|
||||
* aVertexCoord - vertex coordinate
|
||||
*
|
||||
* Uniforms:
|
||||
* uTransformMatrix - a transform matrix
|
||||
* uQuadTransform
|
||||
* uProjMatrix - projection matrix
|
||||
* uOffset - a vec4 offset to apply to the transformed coordinates
|
||||
* uLayerOpacity - a float, the layer opacity (final colors will be multiplied by this)
|
||||
*/
|
||||
|
||||
class LayerProgram :
|
||||
public LayerManagerOGLProgram
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
TransformMatrixUniform = 0,
|
||||
QuadTransformUniform,
|
||||
ProjectionMatrixUniform,
|
||||
OffsetUniform,
|
||||
LayerOpacityUniform,
|
||||
NumLayerUniforms
|
||||
};
|
||||
|
||||
enum {
|
||||
VertexCoordAttrib = 0,
|
||||
NumLayerAttribs
|
||||
};
|
||||
|
||||
LayerProgram(GLContext *aGL)
|
||||
: LayerManagerOGLProgram(aGL)
|
||||
{ }
|
||||
|
||||
bool Initialize(const char *aVertexShaderString,
|
||||
const char *aFragmentShaderString)
|
||||
{
|
||||
if (!CreateProgram(aVertexShaderString, aFragmentShaderString))
|
||||
return false;
|
||||
|
||||
const char *uniformNames[] = {
|
||||
"uLayerTransform",
|
||||
"uLayerQuadTransform",
|
||||
"uMatrixProj",
|
||||
"uRenderTargetOffset",
|
||||
"uLayerOpacity",
|
||||
NULL
|
||||
};
|
||||
|
||||
mUniformLocations.SetLength(NumLayerUniforms);
|
||||
GetUniformLocations(uniformNames, &mUniformLocations[0]);
|
||||
|
||||
const char *attribNames[] = {
|
||||
"aVertexCoord",
|
||||
NULL
|
||||
};
|
||||
|
||||
mAttribLocations.SetLength(NumLayerAttribs);
|
||||
GetAttribLocations(attribNames, &mAttribLocations[0]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GLint AttribLocation(int aWhich) {
|
||||
if (aWhich < 0 || aWhich >= int(mAttribLocations.Length()))
|
||||
return -1;
|
||||
return mAttribLocations[aWhich];
|
||||
}
|
||||
|
||||
void SetLayerTransform(const gfx3DMatrix& aMatrix) {
|
||||
SetLayerTransform(&aMatrix._11);
|
||||
}
|
||||
|
||||
void SetLayerTransform(const float *aMatrix) {
|
||||
SetMatrixUniform(mUniformLocations[TransformMatrixUniform], aMatrix);
|
||||
}
|
||||
|
||||
void SetLayerQuadRect(const nsIntRect& aRect) {
|
||||
gfx3DMatrix m;
|
||||
m._11 = float(aRect.width);
|
||||
m._22 = float(aRect.height);
|
||||
m._41 = float(aRect.x);
|
||||
m._42 = float(aRect.y);
|
||||
SetMatrixUniform(mUniformLocations[QuadTransformUniform], &m._11);
|
||||
}
|
||||
|
||||
void SetProjectionMatrix(const gfx3DMatrix& aMatrix) {
|
||||
SetProjectionMatrix(&aMatrix._11);
|
||||
}
|
||||
|
||||
void SetProjectionMatrix(const float *aMatrix) {
|
||||
SetMatrixUniform(mUniformLocations[ProjectionMatrixUniform], aMatrix);
|
||||
}
|
||||
|
||||
void SetRenderOffset(const nsIntPoint& aOffset) {
|
||||
float vals[4] = { float(aOffset.x), float(aOffset.y), 0.0f, 0.0f };
|
||||
SetUniform(mUniformLocations[OffsetUniform], 4, vals);
|
||||
}
|
||||
|
||||
void SetRenderOffset(float aX, float aY) {
|
||||
float vals[4] = { aX, aY, 0.0f, 0.0f };
|
||||
SetUniform(mUniformLocations[OffsetUniform], 4, vals);
|
||||
}
|
||||
|
||||
void SetLayerOpacity(float aOpacity) {
|
||||
SetUniform(mUniformLocations[LayerOpacityUniform], aOpacity);
|
||||
}
|
||||
|
||||
protected:
|
||||
nsTArray<GLint> mUniformLocations;
|
||||
nsTArray<GLint> mAttribLocations;
|
||||
};
|
||||
|
||||
/*
|
||||
* A ColorTextureLayerProgram is a LayerProgram that renders
|
||||
* a single texture. It adds the following attributes and uniforms:
|
||||
*
|
||||
* Attribute inputs:
|
||||
* aTexCoord - texture coordinate
|
||||
*
|
||||
* Uniforms:
|
||||
* uTexture - 2D texture unit which to sample
|
||||
*/
|
||||
|
||||
class ColorTextureLayerProgram :
|
||||
public LayerProgram
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
TextureUniform = NumLayerUniforms,
|
||||
NumUniforms
|
||||
};
|
||||
|
||||
enum {
|
||||
TexCoordAttrib = NumLayerAttribs,
|
||||
NumAttribs
|
||||
};
|
||||
|
||||
ColorTextureLayerProgram(GLContext *aGL)
|
||||
: LayerProgram(aGL)
|
||||
{ }
|
||||
|
||||
bool Initialize(const char *aVertexShaderString,
|
||||
const char *aFragmentShaderString)
|
||||
{
|
||||
if (!LayerProgram::Initialize(aVertexShaderString, aFragmentShaderString))
|
||||
return false;
|
||||
|
||||
const char *uniformNames[] = {
|
||||
"uTexture",
|
||||
NULL
|
||||
};
|
||||
|
||||
mUniformLocations.SetLength(NumUniforms);
|
||||
GetUniformLocations(uniformNames, &mUniformLocations[NumLayerUniforms]);
|
||||
|
||||
const char *attribNames[] = {
|
||||
"aTexCoord",
|
||||
NULL
|
||||
};
|
||||
|
||||
mAttribLocations.SetLength(NumAttribs);
|
||||
GetAttribLocations(attribNames, &mAttribLocations[NumLayerAttribs]);
|
||||
|
||||
// this is a one-off that's present in the 2DRect versions of some shaders.
|
||||
mTexCoordMultiplierUniformLocation =
|
||||
mGL->fGetUniformLocation(mProgram, "uTexCoordMultiplier");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetTextureUnit(GLint aUnit) {
|
||||
SetUniform(mUniformLocations[TextureUniform], aUnit);
|
||||
}
|
||||
|
||||
GLint GetTexCoordMultiplierUniformLocation() {
|
||||
return mTexCoordMultiplierUniformLocation;
|
||||
}
|
||||
|
||||
protected:
|
||||
GLint mTexCoordMultiplierUniformLocation;
|
||||
};
|
||||
|
||||
/*
|
||||
* A YCbCrTextureLayerProgram is a LayerProgram that renders a YCbCr
|
||||
* image, reading from three texture units. The textures are assumed
|
||||
* to be single-channel textures.
|
||||
*
|
||||
* Attribute inputs:
|
||||
* aTexCoord - texture coordinate
|
||||
*
|
||||
* Uniforms:
|
||||
* uYTexture - 2D texture unit which to sample Y
|
||||
* uCbTexture - 2D texture unit which to sample Cb
|
||||
* uCrTexture - 2D texture unit which to sample Cr
|
||||
*/
|
||||
|
||||
class YCbCrTextureLayerProgram :
|
||||
public LayerProgram
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
YTextureUniform = NumLayerUniforms,
|
||||
CbTextureUniform,
|
||||
CrTextureUniform,
|
||||
NumUniforms
|
||||
};
|
||||
|
||||
enum {
|
||||
TexCoordAttrib = NumLayerAttribs,
|
||||
NumAttribs
|
||||
};
|
||||
|
||||
YCbCrTextureLayerProgram(GLContext *aGL)
|
||||
: LayerProgram(aGL)
|
||||
{ }
|
||||
|
||||
bool Initialize(const char *aVertexShaderString,
|
||||
const char *aFragmentShaderString)
|
||||
{
|
||||
if (!LayerProgram::Initialize(aVertexShaderString, aFragmentShaderString))
|
||||
return false;
|
||||
|
||||
const char *uniformNames[] = {
|
||||
"uYTexture",
|
||||
"uCbTexture",
|
||||
"uCrTexture",
|
||||
NULL
|
||||
};
|
||||
|
||||
mUniformLocations.SetLength(NumUniforms);
|
||||
GetUniformLocations(uniformNames, &mUniformLocations[NumLayerUniforms]);
|
||||
|
||||
const char *attribNames[] = {
|
||||
"aTexCoord",
|
||||
NULL
|
||||
};
|
||||
|
||||
mAttribLocations.SetLength(NumAttribs);
|
||||
GetAttribLocations(attribNames, &mAttribLocations[NumLayerAttribs]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetYTextureUnit(GLint aUnit) {
|
||||
SetUniform(mUniformLocations[YTextureUniform], aUnit);
|
||||
}
|
||||
|
||||
void SetCbTextureUnit(GLint aUnit) {
|
||||
SetUniform(mUniformLocations[CbTextureUniform], aUnit);
|
||||
}
|
||||
|
||||
void SetCrTextureUnit(GLint aUnit) {
|
||||
SetUniform(mUniformLocations[CrTextureUniform], aUnit);
|
||||
}
|
||||
|
||||
void SetYCbCrTextureUnits(GLint aYUnit, GLint aCbUnit, GLint aCrUnit) {
|
||||
SetUniform(mUniformLocations[YTextureUniform], aYUnit);
|
||||
SetUniform(mUniformLocations[CbTextureUniform], aCbUnit);
|
||||
SetUniform(mUniformLocations[CrTextureUniform], aCrUnit);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* A SolidColorLayerProgram is a LayerProgram that renders
|
||||
* a solid color. It adds the following attributes and uniforms:
|
||||
*
|
||||
* Uniforms:
|
||||
* uRenderColor - solid color to render;
|
||||
* This should be with premultiplied opacity, as it's written
|
||||
* to the color buffer directly. Layer Opacity is ignored.
|
||||
*/
|
||||
|
||||
class SolidColorLayerProgram :
|
||||
public LayerProgram
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
RenderColorUniform = NumLayerUniforms,
|
||||
NumUniforms
|
||||
};
|
||||
|
||||
enum {
|
||||
NumAttribs = NumLayerAttribs
|
||||
};
|
||||
|
||||
SolidColorLayerProgram(GLContext *aGL)
|
||||
: LayerProgram(aGL)
|
||||
{ }
|
||||
|
||||
bool Initialize(const char *aVertexShaderString,
|
||||
const char *aFragmentShaderString)
|
||||
{
|
||||
if (!LayerProgram::Initialize(aVertexShaderString, aFragmentShaderString))
|
||||
return false;
|
||||
|
||||
const char *uniformNames[] = {
|
||||
"uRenderColor",
|
||||
NULL
|
||||
};
|
||||
|
||||
mUniformLocations.SetLength(NumUniforms);
|
||||
GetUniformLocations(uniformNames, &mUniformLocations[NumLayerUniforms]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetRenderColor(const gfxRGBA& aColor) {
|
||||
SetUniform(mUniformLocations[RenderColorUniform], aColor);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* A CopyProgram is an OpenGL program that copies a 4-channel texture
|
||||
* to the destination, making no attempt to transform any incoming
|
||||
* vertices. It has the following attributes and uniforms:
|
||||
*
|
||||
* Attribute inputs:
|
||||
* aVertex - vertex coordinate
|
||||
* aTexCoord - texture coordinate
|
||||
*
|
||||
* Uniforms:
|
||||
* uTexture - 2D texture unit which to sample
|
||||
*/
|
||||
|
||||
class CopyProgram :
|
||||
public LayerManagerOGLProgram
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
TextureUniform = 0,
|
||||
NumUniforms
|
||||
};
|
||||
|
||||
enum {
|
||||
VertexCoordAttrib = 0,
|
||||
TexCoordAttrib,
|
||||
NumAttribs
|
||||
};
|
||||
|
||||
CopyProgram(GLContext *aGL)
|
||||
: LayerManagerOGLProgram(aGL)
|
||||
{ }
|
||||
|
||||
bool Initialize(const char *aVertexShaderString,
|
||||
const char *aFragmentShaderString)
|
||||
{
|
||||
if (!CreateProgram(aVertexShaderString, aFragmentShaderString))
|
||||
return false;
|
||||
|
||||
const char *uniformNames[] = {
|
||||
"uTexture",
|
||||
NULL
|
||||
};
|
||||
|
||||
mUniformLocations.SetLength(NumUniforms);
|
||||
GetUniformLocations(uniformNames, &mUniformLocations[0]);
|
||||
|
||||
const char *attribNames[] = {
|
||||
"aVertexCoord",
|
||||
"aTexCoord",
|
||||
NULL
|
||||
};
|
||||
|
||||
mAttribLocations.SetLength(NumAttribs);
|
||||
GetAttribLocations(attribNames, &mAttribLocations[0]);
|
||||
|
||||
// this is a one-off that's present in the 2DRect versions of some shaders.
|
||||
mTexCoordMultiplierUniformLocation =
|
||||
mGL->fGetUniformLocation(mProgram, "uTexCoordMultiplier");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GLint AttribLocation(int aWhich) {
|
||||
if (aWhich < 0 || aWhich >= int(mAttribLocations.Length()))
|
||||
return -1;
|
||||
return mAttribLocations[aWhich];
|
||||
}
|
||||
|
||||
void SetTextureUnit(GLint aUnit) {
|
||||
SetUniform(mUniformLocations[TextureUniform], aUnit);
|
||||
}
|
||||
|
||||
GLint GetTexCoordMultiplierUniformLocation() {
|
||||
return mTexCoordMultiplierUniformLocation;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsTArray<GLint> mUniformLocations;
|
||||
nsTArray<GLint> mAttribLocations;
|
||||
|
||||
GLint mTexCoordMultiplierUniformLocation;
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
|
||||
#endif /* GFX_LAYERMANAGEROGLPROGRAM_H */
|
|
@ -1,48 +0,0 @@
|
|||
#define SHADER_GLOBAL_VARS "uniform mat4 uMatrixProj; \
|
||||
uniform mat4 uLayerQuadTransform; \
|
||||
uniform mat4 uLayerTransform; \
|
||||
uniform vec4 uRenderTargetOffset; \
|
||||
uniform vec4 uRenderColor; \
|
||||
uniform float uLayerOpacity; \
|
||||
\
|
||||
uniform sampler2D uLayerTexture; \
|
||||
uniform sampler2D uYTexture; \
|
||||
uniform sampler2D uCbTexture; \
|
||||
uniform sampler2D uCrTexture; \
|
||||
varying vec2 vTextureCoordinate;"
|
||||
|
||||
static const GLchar *sVertexShader = SHADER_GLOBAL_VARS "attribute vec4 aVertex; \
|
||||
void main() \
|
||||
{ \
|
||||
vec4 finalPosition = aVertex; \
|
||||
finalPosition = uLayerQuadTransform * finalPosition; \
|
||||
finalPosition = uLayerTransform * finalPosition; \
|
||||
finalPosition = finalPosition - uRenderTargetOffset; \
|
||||
finalPosition = uMatrixProj * finalPosition; \
|
||||
gl_Position = finalPosition; \
|
||||
vTextureCoordinate = vec2(aVertex); \
|
||||
}";
|
||||
|
||||
static const GLchar *sRGBLayerPS = SHADER_GLOBAL_VARS "void main() \
|
||||
{ \
|
||||
gl_FragColor = texture2D(uLayerTexture, vTextureCoordinate) * uLayerOpacity; \
|
||||
}";
|
||||
|
||||
static const GLchar *sColorLayerPS = SHADER_GLOBAL_VARS "void main() \
|
||||
{ \
|
||||
gl_FragColor = uRenderColor; \
|
||||
}";
|
||||
|
||||
static const GLchar *sYUVLayerPS = SHADER_GLOBAL_VARS "void main() \
|
||||
{ \
|
||||
vec4 yuv; \
|
||||
vec4 color; \
|
||||
yuv.r = texture2D(uCrTexture, vTextureCoordinate).r - 0.5; \
|
||||
yuv.g = texture2D(uYTexture, vTextureCoordinate).r - 0.0625; \
|
||||
yuv.b = texture2D(uCbTexture, vTextureCoordinate).r - 0.5; \
|
||||
color.r = yuv.g * 1.164 + yuv.r * 1.596; \
|
||||
color.g = yuv.g * 1.164 - 0.813 * yuv.r - 0.391 * yuv.b; \
|
||||
color.b = yuv.g * 1.164 + yuv.b * 2.018; \
|
||||
color.a = 1.0; \
|
||||
gl_FragColor = color * uLayerOpacity; \
|
||||
}";
|
|
@ -0,0 +1,279 @@
|
|||
// -*- Mode: glsl; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40; -*-
|
||||
// ***** BEGIN LICENSE BLOCK *****
|
||||
// Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
//
|
||||
// The contents of this file are subject to the Mozilla Public License Version
|
||||
// 1.1 (the "License"); you may not use this file except in compliance with
|
||||
// the License. You may obtain a copy of the License at
|
||||
// http://www.mozilla.org/MPL/
|
||||
//
|
||||
// Software distributed under the License is distributed on an "AS IS" basis,
|
||||
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
// for the specific language governing rights and limitations under the
|
||||
// License.
|
||||
//
|
||||
// The Original Code is Mozilla Foundation code.
|
||||
//
|
||||
// The Initial Developer of the Original Code is
|
||||
// Mozilla Foundation.
|
||||
// Portions created by the Initial Developer are Copyright (C) 2010
|
||||
// the Initial Developer. All Rights Reserved.
|
||||
//
|
||||
// Contributor(s):
|
||||
// Bas Schouten <bschouten@mozilla.org>
|
||||
// Vladimir Vukicevic <vladimir@pobox.com>
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the terms of
|
||||
// either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
// in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
// of those above. If you wish to allow use of your version of this file only
|
||||
// under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
// use your version of this file under the terms of the MPL, indicate your
|
||||
// decision by deleting the provisions above and replace them with the notice
|
||||
// and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
// the provisions above, a recipient may use your version of this file under
|
||||
// the terms of any one of the MPL, the GPL or the LGPL.
|
||||
//
|
||||
// ***** END LICENSE BLOCK *****
|
||||
|
||||
//
|
||||
// Syntax:
|
||||
//
|
||||
// // comments (only at the start of a line)
|
||||
//
|
||||
// (@ is used because # is valid inside GLSL)
|
||||
//
|
||||
// multi-line:
|
||||
// @define FOO
|
||||
// ...
|
||||
// @end
|
||||
//
|
||||
// single:
|
||||
// @define FOO 123
|
||||
//
|
||||
// $FOO$ to paste
|
||||
//
|
||||
// To generate a constant string named ShaderName:
|
||||
// @shader ShaderName
|
||||
// ...
|
||||
// @end
|
||||
//
|
||||
//
|
||||
|
||||
@define VERTEX_SHADER_HEADER
|
||||
/* Vertex Shader */
|
||||
@end
|
||||
|
||||
@define FRAGMENT_SHADER_HEADER
|
||||
/* Fragment Shader */
|
||||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
@end
|
||||
|
||||
// fragment shader header for all layers
|
||||
@define LAYER_FRAGMENT
|
||||
$FRAGMENT_SHADER_HEADER$
|
||||
|
||||
#ifndef NO_LAYER_OPACITY
|
||||
uniform float uLayerOpacity;
|
||||
#endif
|
||||
|
||||
varying vec2 vTexCoord;
|
||||
@end
|
||||
|
||||
// This is a basic Layer vertex shader. It's used for all
|
||||
// the Layer programs.
|
||||
|
||||
@shader sLayerVS
|
||||
$VERTEX_SHADER_HEADER$
|
||||
|
||||
uniform mat4 uMatrixProj;
|
||||
uniform mat4 uLayerQuadTransform;
|
||||
uniform mat4 uLayerTransform;
|
||||
uniform vec4 uRenderTargetOffset;
|
||||
|
||||
attribute vec4 aVertexCoord;
|
||||
attribute vec2 aTexCoord;
|
||||
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 finalPosition = aVertexCoord;
|
||||
finalPosition = uLayerQuadTransform * finalPosition;
|
||||
finalPosition = uLayerTransform * finalPosition;
|
||||
finalPosition = finalPosition - uRenderTargetOffset;
|
||||
finalPosition = uMatrixProj * finalPosition;
|
||||
|
||||
vTexCoord = aTexCoord;
|
||||
gl_Position = finalPosition;
|
||||
}
|
||||
@end
|
||||
|
||||
// Solid color rendering.
|
||||
// texcoords are ignored (no texture to sample).
|
||||
// The layer opacity is baked in to the color.
|
||||
@shader sSolidColorLayerFS
|
||||
#define NO_LAYER_OPACITY 1
|
||||
$LAYER_FRAGMENT$
|
||||
uniform vec4 uRenderColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = uRenderColor;
|
||||
}
|
||||
@end
|
||||
|
||||
// Single texture in RGBA format
|
||||
@shader sRGBATextureLayerFS
|
||||
$LAYER_FRAGMENT$
|
||||
uniform sampler2D uTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = texture2D(uTexture, vTexCoord) * uLayerOpacity;
|
||||
}
|
||||
@end
|
||||
|
||||
// Single texture in RGBA format, but with a Rect texture.
|
||||
// Container layer needs this to render a FBO group.
|
||||
@shader sRGBARectTextureLayerFS
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
|
||||
$LAYER_FRAGMENT$
|
||||
|
||||
/* This should not be used on GL ES */
|
||||
#ifndef GL_ES
|
||||
uniform sampler2DRect uTexture;
|
||||
uniform vec2 uTexCoordMultiplier;
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = texture2DRect(uTexture, vec2(vTexCoord * uTexCoordMultiplier)) * uLayerOpacity;
|
||||
}
|
||||
#else
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
#endif
|
||||
@end
|
||||
|
||||
// Single texture in BGRA format (via swizzle)
|
||||
@shader sBGRATextureLayerFS
|
||||
$LAYER_FRAGMENT$
|
||||
uniform sampler2D uTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = texture2D(uTexture, vTexCoord).bgra * uLayerOpacity;
|
||||
}
|
||||
@end
|
||||
|
||||
// Single texture in RGBX format
|
||||
@shader sRGBXTextureLayerFS
|
||||
$LAYER_FRAGMENT$
|
||||
uniform sampler2D uTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(texture2D(uTexture, vTexCoord).rgb, 1.0) * uLayerOpacity;
|
||||
}
|
||||
@end
|
||||
|
||||
// Single texture in BGRX format (via swizzle)
|
||||
@shader sBGRXTextureLayerFS
|
||||
$LAYER_FRAGMENT$
|
||||
uniform sampler2D uTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(texture2D(uTexture, vTexCoord).bgr, 1.0) * uLayerOpacity;
|
||||
}
|
||||
@end
|
||||
|
||||
// Three textures, representing YCbCr planes of a video image
|
||||
@shader sYCbCrTextureLayerFS
|
||||
$LAYER_FRAGMENT$
|
||||
uniform sampler2D uYTexture;
|
||||
uniform sampler2D uCbTexture;
|
||||
uniform sampler2D uCrTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 yuv;
|
||||
vec4 color;
|
||||
yuv.r = texture2D(uCrTexture, vTexCoord).r - 0.5;
|
||||
yuv.g = texture2D(uYTexture, vTexCoord).r - 0.0625;
|
||||
yuv.b = texture2D(uCbTexture, vTexCoord).r - 0.5;
|
||||
color.r = yuv.g * 1.164 + yuv.r * 1.596;
|
||||
color.g = yuv.g * 1.164 - 0.813 * yuv.r - 0.391 * yuv.b;
|
||||
color.b = yuv.g * 1.164 + yuv.b * 2.018;
|
||||
color.a = 1.0;
|
||||
gl_FragColor = color * uLayerOpacity;
|
||||
}
|
||||
@end
|
||||
|
||||
//
|
||||
// The "Copy" program is used for blitting a texture to a destination
|
||||
// with no transforms or any other manipulation. They're used for
|
||||
// blitting the contents of a FBO-rendered texture to a destination.
|
||||
//
|
||||
// There are two variants of the fragment shader: one that uses 2D
|
||||
// textures and one that uses 2DRect textures (for when
|
||||
// EXT_TEXTURE_RECTANGLE is used for FBOs).
|
||||
//
|
||||
// On GL ES, EXT_TEXTURE_RECTANGLE isn't available, so we still
|
||||
// compile the shader but have it render pure red. It should never
|
||||
// be used.
|
||||
//
|
||||
|
||||
@shader sCopyVS
|
||||
$VERTEX_SHADER_HEADER$
|
||||
|
||||
attribute vec4 aVertexCoord;
|
||||
attribute vec2 aTexCoord;
|
||||
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = aVertexCoord;
|
||||
vTexCoord = aTexCoord;
|
||||
}
|
||||
@end
|
||||
|
||||
@shader sCopy2DFS
|
||||
$FRAGMENT_SHADER_HEADER$
|
||||
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
uniform sampler2D uTexture;
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = texture2D(uTexture, vTexCoord);
|
||||
}
|
||||
@end
|
||||
|
||||
@shader sCopy2DRectFS
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
|
||||
$FRAGMENT_SHADER_HEADER$
|
||||
|
||||
varying vec2 vTexCoord;
|
||||
uniform vec2 uTexCoordMultiplier;
|
||||
|
||||
#ifndef GL_ES
|
||||
uniform sampler2DRect uTexture;
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = texture2DRect(uTexture, vTexCoord * uTexCoordMultiplier);
|
||||
}
|
||||
#else
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
#endif
|
||||
@end
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Bas Schouten <bschouten@mozilla.org>
|
||||
* Vladimir Vukicevic <vladimir@pobox.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -79,7 +80,7 @@ ThebesLayerOGL::ThebesLayerOGL(LayerManagerOGL *aManager)
|
|||
|
||||
ThebesLayerOGL::~ThebesLayerOGL()
|
||||
{
|
||||
static_cast<LayerManagerOGL*>(mManager)->MakeCurrent();
|
||||
mOGLManager->MakeCurrent();
|
||||
if (mTexture) {
|
||||
gl()->fDeleteTextures(1, &mTexture);
|
||||
}
|
||||
|
@ -88,35 +89,35 @@ ThebesLayerOGL::~ThebesLayerOGL()
|
|||
void
|
||||
ThebesLayerOGL::SetVisibleRegion(const nsIntRegion &aRegion)
|
||||
{
|
||||
if (aRegion.GetBounds() == mVisibleRect) {
|
||||
if (aRegion.GetBounds() == mVisibleRect)
|
||||
return;
|
||||
}
|
||||
|
||||
mVisibleRect = aRegion.GetBounds();
|
||||
|
||||
static_cast<LayerManagerOGL*>(mManager)->MakeCurrent();
|
||||
|
||||
if (!mTexture) {
|
||||
gl()->fGenTextures(1, &mTexture);
|
||||
}
|
||||
|
||||
mInvalidatedRect = mVisibleRect;
|
||||
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
mOGLManager->MakeCurrent();
|
||||
|
||||
if (!mTexture)
|
||||
gl()->fGenTextures(1, &mTexture);
|
||||
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
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);
|
||||
|
||||
gl()->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
mVisibleRect.width,
|
||||
mVisibleRect.height,
|
||||
0,
|
||||
LOCAL_GL_BGRA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
NULL);
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
mVisibleRect.width,
|
||||
mVisibleRect.height,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
NULL);
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -142,12 +143,15 @@ ThebesLayerOGL::GetVisibleRect()
|
|||
|
||||
void
|
||||
ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer,
|
||||
DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
const nsIntPoint& aOffset)
|
||||
{
|
||||
if (!mTexture) {
|
||||
if (!mTexture)
|
||||
return;
|
||||
}
|
||||
|
||||
mOGLManager->MakeCurrent();
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
|
||||
bool needsTextureBind = true;
|
||||
|
||||
if (!mInvalidatedRect.IsEmpty()) {
|
||||
gfxASurface::gfxImageFormat imageFormat;
|
||||
|
@ -166,10 +170,12 @@ ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer,
|
|||
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(surface);
|
||||
ctx->Translate(gfxPoint(-mInvalidatedRect.x, -mInvalidatedRect.y));
|
||||
aCallback(this, ctx, mInvalidatedRect, aCallbackData);
|
||||
|
||||
static_cast<LayerManagerOGL*>(mManager)->MakeCurrent();
|
||||
/* Call the thebes layer callback */
|
||||
mOGLManager->CallThebesLayerDrawCallback(this, ctx, mInvalidatedRect);
|
||||
|
||||
/* Then take its results and put it in an image surface,
|
||||
* in preparation for a texture upload */
|
||||
nsRefPtr<gfxImageSurface> imageSurface;
|
||||
|
||||
switch (surface->GetType()) {
|
||||
|
@ -207,36 +213,33 @@ ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer,
|
|||
mInvalidatedRect.y - mVisibleRect.y,
|
||||
mInvalidatedRect.width,
|
||||
mInvalidatedRect.height,
|
||||
LOCAL_GL_BGRA,
|
||||
LOCAL_GL_RGBA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
imageSurface->Data());
|
||||
|
||||
needsTextureBind = false;
|
||||
}
|
||||
|
||||
float quadTransform[4][4];
|
||||
/*
|
||||
* Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
|
||||
* and size.
|
||||
*/
|
||||
memset(&quadTransform, 0, sizeof(quadTransform));
|
||||
quadTransform[0][0] = (float)GetVisibleRect().width;
|
||||
quadTransform[1][1] = (float)GetVisibleRect().height;
|
||||
quadTransform[2][2] = 1.0f;
|
||||
quadTransform[3][0] = (float)GetVisibleRect().x;
|
||||
quadTransform[3][1] = (float)GetVisibleRect().y;
|
||||
quadTransform[3][3] = 1.0f;
|
||||
if (needsTextureBind)
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
RGBLayerProgram *program =
|
||||
static_cast<LayerManagerOGL*>(mManager)->GetRGBLayerProgram();
|
||||
// Note BGR: Cairo's image surfaces are always in what
|
||||
// OpenGL and our shaders consider BGR format.
|
||||
ColorTextureLayerProgram *program =
|
||||
UseOpaqueSurface(this)
|
||||
? mOGLManager->GetBGRXLayerProgram()
|
||||
: mOGLManager->GetBGRALayerProgram();
|
||||
|
||||
program->Activate();
|
||||
program->SetLayerQuadTransform(&quadTransform[0][0]);
|
||||
program->SetLayerQuadRect(mVisibleRect);
|
||||
program->SetLayerOpacity(GetOpacity());
|
||||
program->SetLayerTransform(&mTransform._11);
|
||||
program->Apply();
|
||||
program->SetLayerTransform(mTransform);
|
||||
program->SetRenderOffset(aOffset);
|
||||
program->SetTextureUnit(0);
|
||||
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
mOGLManager->BindAndDrawQuad(program);
|
||||
|
||||
gl()->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
}
|
||||
|
||||
const nsIntRect&
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-/
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
|
@ -64,8 +64,7 @@ public:
|
|||
Layer* GetLayer();
|
||||
virtual PRBool IsEmpty();
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
const nsIntPoint& aOffset);
|
||||
|
||||
/** ThebesLayerOGL */
|
||||
const nsIntRect &GetVisibleRect();
|
||||
|
@ -86,7 +85,6 @@ private:
|
|||
* OpenGL Texture
|
||||
*/
|
||||
GLuint mTexture;
|
||||
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Mozilla Foundation code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2010
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Vladimir Vukicevic <vladimir@pobox.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
import sys
|
||||
import re
|
||||
import string
|
||||
|
||||
defines = dict()
|
||||
|
||||
def emitShader(fp, shadername, shaderlines):
|
||||
eolContinue = "\\n\\\n";
|
||||
fp.write("const char %s[] = \"/* %s */%s" % (shadername,shadername,eolContinue))
|
||||
for line in shaderlines:
|
||||
line.replace("\\", "\\\\")
|
||||
while line.find('$') != -1:
|
||||
expansions = re.findall('\$\S+\$', line)
|
||||
for m in expansions:
|
||||
mkey = m[1:-1]
|
||||
if not defines.has_key(mkey):
|
||||
print "Error: Undefined expansion used: '%s'" % (m,)
|
||||
sys.exit(1)
|
||||
mval = defines[mkey]
|
||||
if type(mval) == str:
|
||||
line = line.replace(m, mval)
|
||||
elif type(mval) == list:
|
||||
line = line.replace(m, eolContinue.join(mval) + eolContinue);
|
||||
else:
|
||||
print "Internal Error: Unknown type in defines array: '%s'" % (str(type(mval)),)
|
||||
|
||||
fp.write("%s%s" % (line,eolContinue))
|
||||
fp.write("\";\n\n");
|
||||
|
||||
def genShaders(infile, outfile):
|
||||
source = open(infile, "r").readlines()
|
||||
desthdr = open(outfile, "w+")
|
||||
|
||||
desthdr.write("/* AUTOMATICALLY GENERATED */\n");
|
||||
desthdr.write("/* DO NOT EDIT! */\n\n");
|
||||
|
||||
global defines
|
||||
|
||||
indefine = None
|
||||
inshader = None
|
||||
|
||||
inblock = False
|
||||
linebuffer = []
|
||||
|
||||
for line in source:
|
||||
# strip comments, if not inblock
|
||||
if not inblock and line.startswith("//"):
|
||||
continue
|
||||
line = string.strip(line)
|
||||
|
||||
if len(line) == 0:
|
||||
continue
|
||||
|
||||
if line[0] == '@':
|
||||
cmd = line
|
||||
rest = ''
|
||||
|
||||
if line.find(' ') != -1:
|
||||
cmd = line[0:line.find(' ')]
|
||||
rest = string.strip(line[len(cmd) + 1:])
|
||||
|
||||
if cmd == "@define":
|
||||
if inblock:
|
||||
raise Exception("@define inside a block!")
|
||||
space = rest.find(' ')
|
||||
if space != -1:
|
||||
defines[rest[0:space]] = rest[space+1:]
|
||||
else:
|
||||
indefine = rest
|
||||
inblock = True
|
||||
elif cmd == "@shader":
|
||||
if inblock:
|
||||
raise Exception("@shader inside a block!")
|
||||
if len(rest) == 0:
|
||||
raise Exception("@shader without a name!")
|
||||
inshader = rest
|
||||
inblock = True
|
||||
elif cmd == "@end":
|
||||
if indefine is not None:
|
||||
if type(linebuffer) == list:
|
||||
for i in range(len(linebuffer)):
|
||||
linebuffer[i] = linebuffer[i].replace("\\", "\\\\")
|
||||
defines[indefine] = linebuffer
|
||||
elif inshader is not None:
|
||||
emitShader(desthdr, inshader, linebuffer)
|
||||
else:
|
||||
raise Exception("@end outside of a block!")
|
||||
indefine = None
|
||||
inshader = None
|
||||
inblock = None
|
||||
linebuffer = []
|
||||
else:
|
||||
raise Exception("Unknown command: %s" % (cmd,))
|
||||
else:
|
||||
if inblock:
|
||||
linebuffer.append(line)
|
||||
|
||||
if (len(sys.argv) != 3):
|
||||
print "Usage: %s infile.txt outfile.h" % (sys.argv[0],)
|
||||
sys.exit(1)
|
||||
|
||||
genShaders(sys.argv[1], sys.argv[2])
|
|
@ -49,6 +49,9 @@
|
|||
#include "nsISupportsImpl.h"
|
||||
#include "prlink.h"
|
||||
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
#ifndef GLAPIENTRY
|
||||
#ifdef XP_WIN
|
||||
#define GLAPIENTRY __stdcall
|
||||
|
@ -110,13 +113,27 @@ class GLContext
|
|||
{
|
||||
THEBES_INLINE_DECL_THREADSAFE_REFCOUNTING(GLContext)
|
||||
public:
|
||||
GLContext() : mInitialized(PR_FALSE) { }
|
||||
GLContext()
|
||||
: mInitialized(PR_FALSE)
|
||||
{
|
||||
mUserData.Init();
|
||||
}
|
||||
|
||||
virtual ~GLContext() { }
|
||||
|
||||
virtual PRBool MakeCurrent() = 0;
|
||||
virtual PRBool SetupLookupFunction() = 0;
|
||||
|
||||
void *GetUserData(void *aKey) {
|
||||
void *result = nsnull;
|
||||
mUserData.Get(aKey, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void SetUserData(void *aKey, void *aValue) {
|
||||
mUserData.Put(aKey, aValue);
|
||||
}
|
||||
|
||||
enum NativeDataType {
|
||||
NativeGLContext,
|
||||
NativeCGLContext,
|
||||
|
@ -129,6 +146,7 @@ public:
|
|||
protected:
|
||||
|
||||
PRBool mInitialized;
|
||||
nsDataHashtable<nsVoidPtrHashKey, void*> mUserData;
|
||||
|
||||
PRBool InitWithPrefix(const char *prefix, PRBool trygl);
|
||||
|
||||
|
@ -136,8 +154,9 @@ protected:
|
|||
// the wrapped functions
|
||||
//
|
||||
public:
|
||||
/* One would think that this would live in some nice perl-or-python-or-js script somewhere and would be autogenerated;
|
||||
* one would be wrong.
|
||||
/* One would think that this would live in some nice
|
||||
* perl-or-python-or-js script somewhere and would be
|
||||
* autogenerated; one would be wrong.
|
||||
*/
|
||||
typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture);
|
||||
PFNGLACTIVETEXTUREPROC fActiveTexture;
|
||||
|
|
|
@ -106,6 +106,11 @@ public:
|
|||
*/
|
||||
static inline gfx3DMatrix Scale(float aFactor);
|
||||
|
||||
/**
|
||||
* Create a scale matrix.
|
||||
*/
|
||||
static inline gfx3DMatrix Scale(float aX, float aY, float aZ);
|
||||
|
||||
/** Matrix elements */
|
||||
float _11, _12, _13, _14;
|
||||
float _21, _22, _23, _24;
|
||||
|
@ -190,4 +195,16 @@ gfx3DMatrix::Scale(float aFactor)
|
|||
return matrix;
|
||||
}
|
||||
|
||||
inline gfx3DMatrix
|
||||
gfx3DMatrix::Scale(float aX, float aY, float aZ)
|
||||
{
|
||||
gfx3DMatrix matrix;
|
||||
|
||||
matrix._11 = aX;
|
||||
matrix._22 = aY;
|
||||
matrix._33 = aZ;
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
#endif /* GFX_3DMATRIX_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче