Bug 546517: The layers OpenGL backend. r=vlad

This commit is contained in:
Bas Schouten 2010-03-30 06:48:52 +02:00
parent 0bf0dea2fb
commit 926f20d238
13 changed files with 5634 additions and 0 deletions

View File

@ -41,6 +41,7 @@ srcdir = @srcdir@
VPATH = \
$(srcdir) \
$(srcdir)/basic \
$(srcdir)/opengl \
$(NULL)
include $(DEPTH)/config/autoconf.mk
@ -56,11 +57,17 @@ EXPORTS = \
BasicLayers.h \
ImageLayers.h \
Layers.h \
LayerManagerOGL.h \
$(NULL)
CPPSRCS = \
BasicImages.cpp \
BasicLayers.cpp \
glWrapper.cpp \
LayerManagerOGL.cpp \
ThebesLayerOGL.cpp \
ContainerLayerOGL.cpp \
ImageLayerOGL.cpp \
$(NULL)
EXTRA_DSO_LIBS = \

View File

@ -0,0 +1,239 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** 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) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.org>
*
* 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 ***** */
#include "ContainerLayerOGL.h"
#include "glWrapper.h"
namespace mozilla {
namespace layers {
ContainerLayerOGL::ContainerLayerOGL(LayerManager *aManager)
: ContainerLayer(aManager, NULL)
{
mImplData = static_cast<LayerOGL*>(this);
}
const nsIntRect&
ContainerLayerOGL::GetVisibleRect()
{
return mVisibleRect;
}
void
ContainerLayerOGL::SetVisibleRegion(const nsIntRegion &aRegion)
{
mVisibleRect = aRegion.GetBounds();
}
void
ContainerLayerOGL::InsertAfter(Layer* aChild, Layer* aAfter)
{
LayerOGL *newChild = static_cast<LayerOGL*>(aChild->ImplData());
aChild->SetParent(this);
if (!aAfter) {
LayerOGL *oldFirstChild = GetFirstChildOGL();
mFirstChild = newChild->GetLayer();
newChild->SetNextSibling(oldFirstChild);
return;
}
for (LayerOGL *child = GetFirstChildOGL();
child; child = child->GetNextSibling()) {
if (aAfter == child->GetLayer()) {
LayerOGL *oldNextSibling = child->GetNextSibling();
child->SetNextSibling(newChild);
child->GetNextSibling()->SetNextSibling(oldNextSibling);
return;
}
}
NS_WARNING("Failed to find aAfter layer!");
}
void
ContainerLayerOGL::RemoveChild(Layer *aChild)
{
if (GetFirstChild() == aChild) {
mFirstChild = GetFirstChildOGL()->GetNextSibling()->GetLayer();
return;
}
LayerOGL *lastChild = NULL;
for (LayerOGL *child = GetFirstChildOGL(); child;
child = child->GetNextSibling()) {
if (child->GetLayer() == aChild) {
// We're sure this is not our first child. So lastChild != NULL.
lastChild->SetNextSibling(child->GetNextSibling());
child->SetNextSibling(NULL);
child->GetLayer()->SetParent(NULL);
return;
}
lastChild = child;
}
}
LayerOGL::LayerType
ContainerLayerOGL::GetType()
{
return TYPE_CONTAINER;
}
Layer*
ContainerLayerOGL::GetLayer()
{
return this;
}
LayerOGL*
ContainerLayerOGL::GetFirstChildOGL()
{
if (!mFirstChild) {
return nsnull;
}
return static_cast<LayerOGL*>(mFirstChild->ImplData());
}
void
ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer)
{
/**
* Setup our temporary texture for rendering the contents of this container.
*/
GLuint containerSurface;
sglWrapper.GenTextures(1, &containerSurface);
sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, containerSurface);
sglWrapper.TexImage2D(LOCAL_GL_TEXTURE_2D,
0,
LOCAL_GL_RGBA,
mVisibleRect.width,
mVisibleRect.height,
0,
LOCAL_GL_BGRA,
LOCAL_GL_UNSIGNED_BYTE,
NULL);
/**
* Create the framebuffer and bind it to make our content render into our
* framebuffer.
*/
GLuint frameBuffer;
sglWrapper.GenFramebuffersEXT(1, &frameBuffer);
sglWrapper.BindFramebufferEXT(LOCAL_GL_FRAMEBUFFER_EXT, frameBuffer);
sglWrapper.FramebufferTexture2DEXT(LOCAL_GL_FRAMEBUFFER_EXT,
LOCAL_GL_COLOR_ATTACHMENT0_EXT,
LOCAL_GL_TEXTURE_2D,
containerSurface,
0);
RGBLayerProgram *rgbProgram =
static_cast<LayerManagerOGL*>(mManager)->GetRGBLayerProgram();
YCbCrLayerProgram *yCbCrProgram =
static_cast<LayerManagerOGL*>(mManager)->GetYCbCrLayerProgram();
/**
* 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);
yCbCrProgram->Activate();
yCbCrProgram->PushRenderTargetOffset((GLfloat)GetVisibleRect().x,
(GLfloat)GetVisibleRect().y);
/**
* Render this container's contents.
*/
LayerOGL *layerToRender = GetFirstChildOGL();
while (layerToRender) {
const nsIntRect *clipRect = layerToRender->GetLayer()->GetClipRect();
if (clipRect) {
sglWrapper.Scissor(clipRect->x - GetVisibleRect().x,
clipRect->y - GetVisibleRect().y,
clipRect->width,
clipRect->height);
} else {
sglWrapper.Scissor(0, 0, GetVisibleRect().width, GetVisibleRect().height);
}
layerToRender->RenderLayer(frameBuffer);
layerToRender = layerToRender->GetNextSibling();
}
// Unbind the current framebuffer and rebind the previous one.
sglWrapper.BindFramebufferEXT(LOCAL_GL_FRAMEBUFFER_EXT, aPreviousFrameBuffer);
sglWrapper.DeleteFramebuffersEXT(1, &frameBuffer);
// Restore old shader program variables.
yCbCrProgram->Activate();
yCbCrProgram->PopRenderTargetOffset();
rgbProgram->Activate();
rgbProgram->PopRenderTargetOffset();
/**
* 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;
rgbProgram->SetLayerQuadTransform(&quadTransform[0][0]);
sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, containerSurface);
rgbProgram->SetLayerOpacity(GetOpacity());
rgbProgram->SetLayerTransform(&mTransform._11);
rgbProgram->Apply();
sglWrapper.DrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
// Clean up resources.
sglWrapper.DeleteTextures(1, &containerSurface);
}
} /* layers */
} /* mozilla */

View File

@ -0,0 +1,81 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** 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) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.org>
*
* 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_CONTAINERLAYEROGL_H
#define GFX_CONTAINERLAYEROGL_H
#include "Layers.h"
#include "LayerManagerOGL.h"
namespace mozilla {
namespace layers {
class ContainerLayerOGL : public ContainerLayer,
public LayerOGL
{
public:
ContainerLayerOGL(LayerManager *aManager);
const nsIntRect &GetVisibleRect();
/** ContainerLayer implementation */
void SetVisibleRegion(const nsIntRegion& aRegion);
void InsertAfter(Layer* aChild, Layer* aAfter);
void RemoveChild(Layer* aChild);
/** LayerOGL implementation */
LayerType GetType();
Layer* GetLayer();
LayerOGL* GetFirstChildOGL();
PRBool IsEmpty();
void RenderLayer(int aPreviousFrameBuffer);
private:
nsIntRect mVisibleRect;
GLuint mTexture;
};
} /* layers */
} /* mozilla */
#endif /* GFX_CONTAINERLAYEROGL_H */

View File

@ -0,0 +1,331 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** 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) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.org>
*
* 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 ***** */
#include "ImageLayerOGL.h"
#include "gfxImageSurface.h"
#include "glWrapper.h"
namespace mozilla {
namespace layers {
already_AddRefed<Image>
ImageContainerOGL::CreateImage(const Image::Format *aFormats,
PRUint32 aNumFormats)
{
if (!aNumFormats) {
return nsnull;
}
nsRefPtr<Image> img;
if (aFormats[0] == Image::PLANAR_YCBCR) {
img = new PlanarYCbCrImageOGL(static_cast<LayerManagerOGL*>(mManager));
} else if (aFormats[0] == Image::CAIRO_SURFACE) {
img = new CairoImageOGL(static_cast<LayerManagerOGL*>(mManager));
}
return img.forget();
}
void
ImageContainerOGL::SetCurrentImage(Image *aImage)
{
mActiveImage = aImage;
}
already_AddRefed<Image>
ImageContainerOGL::GetCurrentImage()
{
nsRefPtr<Image> retval = mActiveImage;
return retval.forget();
}
already_AddRefed<gfxASurface>
ImageContainerOGL::GetCurrentAsSurface(gfxIntSize *aSize)
{
return nsnull;
}
LayerOGL::LayerType
ImageLayerOGL::GetType()
{
return TYPE_IMAGE;
}
Layer*
ImageLayerOGL::GetLayer()
{
return this;
}
void
ImageLayerOGL::RenderLayer(int)
{
if (!GetContainer()) {
return;
}
static_cast<LayerManagerOGL*>(mManager)->MakeCurrent();
nsRefPtr<Image> image = GetContainer()->GetCurrentImage();
if (image->GetFormat() == Image::PLANAR_YCBCR) {
PlanarYCbCrImageOGL *yuvImage =
static_cast<PlanarYCbCrImageOGL*>(image.get());
if (!yuvImage->HasData()) {
return;
}
yuvImage->AllocateTextures();
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 =
static_cast<LayerManagerOGL*>(mManager)->GetYCbCrLayerProgram();
program->Activate();
program->SetLayerQuadTransform(&quadTransform[0][0]);
sglWrapper.ActiveTexture(LOCAL_GL_TEXTURE0);
sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, yuvImage->mTextures[0]);
sglWrapper.ActiveTexture(LOCAL_GL_TEXTURE1);
sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, yuvImage->mTextures[1]);
sglWrapper.ActiveTexture(LOCAL_GL_TEXTURE2);
sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, yuvImage->mTextures[2]);
program->SetLayerOpacity(GetOpacity());
program->SetLayerTransform(&mTransform._11);
program->Apply();
sglWrapper.DrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
yuvImage->FreeTextures();
sglWrapper.ActiveTexture(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 =
static_cast<LayerManagerOGL*>(mManager)->GetRGBLayerProgram();
program->Activate();
program->SetLayerQuadTransform(&quadTransform[0][0]);
sglWrapper.ActiveTexture(LOCAL_GL_TEXTURE0);
sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, cairoImage->mTexture);
program->SetLayerOpacity(GetOpacity());
program->SetLayerTransform(&mTransform._11);
program->Apply();
sglWrapper.DrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
}
}
PlanarYCbCrImageOGL::PlanarYCbCrImageOGL(mozilla::layers::LayerManagerOGL* aManager)
: PlanarYCbCrImage(NULL)
, mLoaded(PR_FALSE)
, mHasData(PR_FALSE)
, mManager(aManager)
{
memset(mTextures, 0, sizeof(GLuint) * 3);
}
PlanarYCbCrImageOGL::~PlanarYCbCrImageOGL()
{
if (mHasData) {
delete [] mData.mYChannel;
delete [] mData.mCbChannel;
delete [] mData.mCrChannel;
}
}
void
PlanarYCbCrImageOGL::SetData(const PlanarYCbCrImage::Data &aData)
{
/**
* XXX - Should do something more clever here, also introduce thread safety
* there's potential race conditions in this class.
*/
mData = aData;
mData.mCbChannel = new PRUint8[aData.mCbCrStride * aData.mCbCrSize.height];
mData.mCrChannel = new PRUint8[aData.mCbCrStride * aData.mCbCrSize.height];
mData.mYChannel = new PRUint8[aData.mYStride * aData.mYSize.height];
memcpy(mData.mCbChannel, aData.mCbChannel, aData.mCbCrStride * aData.mCbCrSize.height);
memcpy(mData.mCrChannel, aData.mCrChannel, aData.mCbCrStride * aData.mCbCrSize.height);
memcpy(mData.mYChannel, aData.mYChannel, aData.mYStride * aData.mYSize.height);
mSize = aData.mYSize;
mHasData = PR_TRUE;
}
void
PlanarYCbCrImageOGL::AllocateTextures()
{
mManager->MakeCurrent();
sglWrapper.GenTextures(3, mTextures);
sglWrapper.PixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, mData.mYStride);
sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, mTextures[0]);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
sglWrapper.TexImage2D(LOCAL_GL_TEXTURE_2D,
0,
LOCAL_GL_LUMINANCE,
mSize.width,
mSize.height,
0,
LOCAL_GL_LUMINANCE,
LOCAL_GL_UNSIGNED_BYTE,
mData.mYChannel);
sglWrapper.PixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, mData.mCbCrStride);
sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, mTextures[1]);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
sglWrapper.TexImage2D(LOCAL_GL_TEXTURE_2D,
0,
LOCAL_GL_LUMINANCE,
mData.mCbCrSize.width,
mData.mCbCrSize.height,
0,
LOCAL_GL_LUMINANCE,
LOCAL_GL_UNSIGNED_BYTE,
mData.mCbChannel);
sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, mTextures[2]);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
sglWrapper.TexImage2D(LOCAL_GL_TEXTURE_2D,
0,
LOCAL_GL_LUMINANCE,
mData.mCbCrSize.width,
mData.mCbCrSize.height,
0,
LOCAL_GL_LUMINANCE,
LOCAL_GL_UNSIGNED_BYTE,
mData.mCrChannel);
sglWrapper.PixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0);
}
void
PlanarYCbCrImageOGL::FreeTextures()
{
static_cast<LayerManagerOGL*>(mManager)->MakeCurrent();
if (mTextures[0]) {
sglWrapper.DeleteTextures(3, mTextures);
}
}
CairoImageOGL::~CairoImageOGL()
{
static_cast<LayerManagerOGL*>(mManager)->MakeCurrent();
if (mTexture) {
sglWrapper.DeleteTextures(1, &mTexture);
}
}
void
CairoImageOGL::SetData(const CairoImage::Data &aData)
{
/**
* XXX - Should make sure this happens on the correct thread. Since this
* is supposed to be threadsafe.
*/
mSize = aData.mSize;
mManager->MakeCurrent();
nsRefPtr<gfxImageSurface> imageSurface =
new gfxImageSurface(aData.mSize, gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
context->SetSource(aData.mSurface);
context->Paint();
sglWrapper.GenTextures(1, &mTexture);
sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
sglWrapper.TexImage2D(LOCAL_GL_TEXTURE_2D,
0,
LOCAL_GL_RGBA,
mSize.width,
mSize.height,
0,
LOCAL_GL_BGRA,
LOCAL_GL_UNSIGNED_BYTE,
imageSurface->Data());
}
} /* layers */
} /* mozilla */

View File

@ -0,0 +1,136 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** 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) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.org>
*
* 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_IMAGELAYEROGL_H
#define GFX_IMAGELAYEROGL_H
#include "LayerManagerOGL.h"
#include "ImageLayers.h"
namespace mozilla {
namespace layers {
class THEBES_API ImageContainerOGL : public ImageContainer
{
public:
ImageContainerOGL(LayerManagerOGL *aManager)
: ImageContainer(aManager)
{ }
virtual ~ImageContainerOGL() {}
virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
PRUint32 aNumFormats);
virtual void SetCurrentImage(Image* aImage);
virtual already_AddRefed<Image> GetCurrentImage();
virtual already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSize);
private:
nsRefPtr<Image> mActiveImage;
};
class THEBES_API ImageLayerOGL : public ImageLayer,
public LayerOGL
{
public:
ImageLayerOGL(LayerManagerOGL *aManager)
: ImageLayer(aManager, NULL)
{
mImplData = static_cast<LayerOGL*>(this);
}
// LayerOGL Implementation
virtual LayerType GetType();
virtual Layer* GetLayer();
virtual void RenderLayer(int aPreviousDestination);
};
class THEBES_API PlanarYCbCrImageOGL : public PlanarYCbCrImage
{
public:
PlanarYCbCrImageOGL(LayerManagerOGL *aManager);
virtual ~PlanarYCbCrImageOGL();
virtual void SetData(const Data &aData);
/**
* Upload the data from out mData into our textures. For now we use this to
* make sure the textures are created and filled on the main thread.
*/
virtual void AllocateTextures();
/**
* XXX
* Free the textures, we call this from the main thread when we're done
* drawing this frame. We cannot free this from the constructor since it may
* be destroyed off the main-thread and might not be able to properly clean
* up its textures
*/
virtual void FreeTextures();
virtual PRBool HasData() { return mHasData; }
Data mData;
PRBool mLoaded;
PRBool mHasData;
GLuint mTextures[3];
gfxIntSize mSize;
LayerManagerOGL *mManager;
};
class THEBES_API CairoImageOGL : public CairoImage
{
public:
CairoImageOGL(LayerManagerOGL *aManager)
: CairoImage(NULL)
, mManager(aManager)
{ }
~CairoImageOGL();
virtual void SetData(const Data &aData);
GLuint mTexture;
gfxIntSize mSize;
LayerManagerOGL *mManager;
};
} /* layers */
} /* mozilla */
#endif /* GFX_IMAGELAYEROGL_H */

View File

@ -0,0 +1,613 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** 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) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.org>
*
* 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 ***** */
#include "LayerManagerOGL.h"
#include "ThebesLayerOGL.h"
#include "ContainerLayerOGL.h"
#include "ImageLayerOGL.h"
#include "LayerManagerOGLShaders.h"
#include "gfxContext.h"
#include "nsIWidget.h"
#include "glWrapper.h"
static const GLint VERTEX_ATTRIB_LOCATION = 0;
namespace mozilla {
namespace layers {
/**
* LayerManagerOGL
*/
LayerManagerOGL::LayerManagerOGL(nsIWidget *aWidget)
: mWidget(aWidget)
, mBackBuffer(0)
, mFrameBuffer(0)
, mRGBLayerProgram(NULL)
, mYCbCrLayerProgram(NULL)
, mVertexShader(0)
, mRGBShader(0)
, mYUVShader(0)
{
}
LayerManagerOGL::~LayerManagerOGL()
{
MakeCurrent();
delete mRGBLayerProgram;
delete mYCbCrLayerProgram;
#ifdef XP_WIN
BOOL deleted = sglWrapper.wDeleteContext(mContext);
NS_ASSERTION(deleted, "Error deleting OpenGL context!");
::ReleaseDC((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW), mDC);
#endif
}
PRBool
LayerManagerOGL::Initialize()
{
#ifdef XP_WIN
mDC = (HDC)mWidget->GetNativeData(NS_NATIVE_GRAPHIC);
PIXELFORMATDESCRIPTOR pfd;
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 0;
pfd.iLayerType = PFD_MAIN_PLANE;
int iFormat = ChoosePixelFormat(mDC, &pfd);
SetPixelFormat(mDC, iFormat, &pfd);
mContext = sglWrapper.wCreateContext(mDC);
if (!mContext) {
return PR_FALSE;
}
#else
// Don't know how to initialize on this platform!
return PR_FALSE;
#endif
MakeCurrent();
sglWrapper.BlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA, LOCAL_GL_ONE, LOCAL_GL_ONE);
sglWrapper.Enable(LOCAL_GL_BLEND);
sglWrapper.Enable(LOCAL_GL_TEXTURE_2D);
sglWrapper.Enable(LOCAL_GL_SCISSOR_TEST);
mVertexShader = sglWrapper.CreateShader(LOCAL_GL_VERTEX_SHADER);
mRGBShader = sglWrapper.CreateShader(LOCAL_GL_FRAGMENT_SHADER);
mYUVShader = sglWrapper.CreateShader(LOCAL_GL_FRAGMENT_SHADER);
sglWrapper.ShaderSource(mVertexShader, 1, (const GLchar**)&sVertexShader, NULL);
sglWrapper.ShaderSource(mRGBShader, 1, (const GLchar**)&sRGBLayerPS, NULL);
sglWrapper.ShaderSource(mYUVShader, 1, (const GLchar**)&sYUVLayerPS, NULL);
sglWrapper.CompileShader(mVertexShader);
sglWrapper.CompileShader(mRGBShader);
sglWrapper.CompileShader(mYUVShader);
GLint status;
sglWrapper.GetShaderiv(mVertexShader, LOCAL_GL_COMPILE_STATUS, &status);
if (!status) {
return false;
}
sglWrapper.GetShaderiv(mRGBShader, LOCAL_GL_COMPILE_STATUS, &status);
if (!status) {
return false;
}
sglWrapper.GetShaderiv(mYUVShader, LOCAL_GL_COMPILE_STATUS, &status);
if (!status) {
return false;
}
mRGBLayerProgram = new RGBLayerProgram();
if (!mRGBLayerProgram->Initialize(mVertexShader, mRGBShader)) {
return false;
}
mYCbCrLayerProgram = new YCbCrLayerProgram();
if (!mYCbCrLayerProgram->Initialize(mVertexShader, mYUVShader)) {
return false;
}
mRGBLayerProgram->UpdateLocations();
mYCbCrLayerProgram->UpdateLocations();
sglWrapper.GenBuffers(1, &mVBO);
sglWrapper.BindBuffer(LOCAL_GL_ARRAY_BUFFER, mVBO);
sglWrapper.EnableClientState(LOCAL_GL_VERTEX_ARRAY);
sglWrapper.EnableVertexAttribArray(VERTEX_ATTRIB_LOCATION);
GLfloat vertices[] = { 0, 0, 1.0f, 0, 0, 1.0f, 1.0f, 1.0f };
sglWrapper.BufferData(LOCAL_GL_ARRAY_BUFFER, sizeof(vertices), vertices, LOCAL_GL_STATIC_DRAW);
mRGBLayerProgram->Activate();
sglWrapper.VertexAttribPointer(VERTEX_ATTRIB_LOCATION,
2,
LOCAL_GL_FLOAT,
LOCAL_GL_FALSE,
0,
0);
mYCbCrLayerProgram->Activate();
sglWrapper.VertexAttribPointer(VERTEX_ATTRIB_LOCATION,
2,
LOCAL_GL_FLOAT,
LOCAL_GL_FALSE,
0,
0);
mRGBLayerProgram->SetLayerTexture(0);
mYCbCrLayerProgram->SetYTexture(0);
mYCbCrLayerProgram->SetCbTexture(1);
mYCbCrLayerProgram->SetCrTexture(2);
return true;
}
void
LayerManagerOGL::SetClippingRegion(const nsIntRegion& aClippingRegion)
{
mClippingRegion = aClippingRegion;
}
void
LayerManagerOGL::BeginTransaction()
{
}
void
LayerManagerOGL::BeginTransactionWithTarget(gfxContext *aTarget)
{
mTarget = aTarget;
}
void
LayerManagerOGL::EndConstruction()
{
}
void
LayerManagerOGL::EndTransaction()
{
Render();
mTarget = NULL;
}
void
LayerManagerOGL::SetRoot(Layer *aLayer)
{
mRootLayer = static_cast<LayerOGL*>(aLayer->ImplData());;
}
already_AddRefed<ThebesLayer>
LayerManagerOGL::CreateThebesLayer()
{
nsRefPtr<ThebesLayer> layer = new ThebesLayerOGL(this);
return layer.forget();
}
already_AddRefed<ContainerLayer>
LayerManagerOGL::CreateContainerLayer()
{
nsRefPtr<ContainerLayer> layer = new ContainerLayerOGL(this);
return layer.forget();
}
already_AddRefed<ImageContainer>
LayerManagerOGL::CreateImageContainer()
{
nsRefPtr<ImageContainer> container = new ImageContainerOGL(this);
return container.forget();
}
already_AddRefed<ImageLayer>
LayerManagerOGL::CreateImageLayer()
{
nsRefPtr<ImageLayer> layer = new ImageLayerOGL(this);
return layer.forget();
}
void
LayerManagerOGL::SetClippingEnabled(PRBool aEnabled)
{
if (aEnabled) {
sglWrapper.Enable(LOCAL_GL_SCISSOR_TEST);
} else {
sglWrapper.Disable(LOCAL_GL_SCISSOR_TEST);
}
}
void
LayerManagerOGL::MakeCurrent()
{
#ifdef XP_WIN
BOOL succeeded = sglWrapper.wMakeCurrent(mDC, mContext);
NS_ASSERTION(succeeded, "Failed to make GL context current!");
#endif
}
void
LayerManagerOGL::Render()
{
nsIntRect rect;
mWidget->GetBounds(rect);
GLint width = rect.width;
GLint height = rect.height;
MakeCurrent();
SetupBackBuffer();
sglWrapper.BindFramebufferEXT(LOCAL_GL_FRAMEBUFFER_EXT, mFrameBuffer);
sglWrapper.BlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA, LOCAL_GL_ONE, LOCAL_GL_ONE);
sglWrapper.ClearColor(0.0, 0.0, 0.0, 0.0);
sglWrapper.Clear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
SetupPipeline();
SetClippingEnabled(PR_FALSE);
if (mRootLayer) {
const nsIntRect *clipRect = mRootLayer->GetLayer()->GetClipRect();
if (clipRect) {
sglWrapper.Scissor(clipRect->x, clipRect->y, clipRect->width, clipRect->height);
} else {
sglWrapper.Scissor(0, 0, width, height);
}
mRootLayer->RenderLayer(mFrameBuffer);
}
if (mTarget) {
CopyToTarget();
} else {
/**
* Draw our backbuffer to the screen without using vertex or fragment
* shaders. We're fine with just calculating the viewport coordinates
* in software. And nothing special is required for the texture sampling.
*/
sglWrapper.BindFramebufferEXT(LOCAL_GL_FRAMEBUFFER_EXT, 0);
sglWrapper.UseProgram(0);
sglWrapper.DisableVertexAttribArray(VERTEX_ATTRIB_LOCATION);
sglWrapper.BindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
sglWrapper.EnableClientState(LOCAL_GL_VERTEX_ARRAY);
sglWrapper.EnableClientState(LOCAL_GL_TEXTURE_COORD_ARRAY);
sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, mBackBuffer);
const nsIntRect *r;
for (nsIntRegionRectIterator iter(mClippingRegion);
(r = iter.Next()) != nsnull;) {
sglWrapper.BlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ZERO, LOCAL_GL_ONE, LOCAL_GL_ZERO);
float left = (GLfloat)r->x / width;
float right = (GLfloat)r->XMost() / width;
float top = (GLfloat)r->y / height;
float bottom = (GLfloat)r->YMost() / height;
float vertices[] = { left * 2.0f - 1.0f,
-(top * 2.0f - 1.0f),
right * 2.0f - 1.0f,
-(top * 2.0f - 1.0f),
left * 2.0f - 1.0f,
-(bottom * 2.0f - 1.0f),
right * 2.0f - 1.0f,
-(bottom * 2.0f - 1.0f) };
float coords[] = { left, top, right, top, left, bottom, right, bottom };
sglWrapper.VertexPointer(2, LOCAL_GL_FLOAT, 0, vertices);
sglWrapper.TexCoordPointer(2, LOCAL_GL_FLOAT, 0, coords);
sglWrapper.DrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
}
sglWrapper.BindBuffer(LOCAL_GL_ARRAY_BUFFER, mVBO);
sglWrapper.EnableVertexAttribArray(VERTEX_ATTRIB_LOCATION);
sglWrapper.DisableClientState(LOCAL_GL_TEXTURE_COORD_ARRAY);
}
sglWrapper.Finish();
}
void
LayerManagerOGL::SetupPipeline()
{
nsIntRect rect;
mWidget->GetBounds(rect);
sglWrapper.Viewport(0, 0, rect.width, rect.height);
float viewMatrix[4][4];
/**
* Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
* <1.0, -1.0> bottomright)
*/
memset(&viewMatrix, 0, sizeof(viewMatrix));
viewMatrix[0][0] = 2.0f / rect.width;
viewMatrix[1][1] = 2.0f / rect.height;
viewMatrix[2][2] = 1.0f;
viewMatrix[3][0] = -1.0f;
viewMatrix[3][1] = -1.0f;
viewMatrix[3][3] = 1.0f;
mRGBLayerProgram->Activate();
mRGBLayerProgram->SetMatrixProj(&viewMatrix[0][0]);
mYCbCrLayerProgram->Activate();
mYCbCrLayerProgram->SetMatrixProj(&viewMatrix[0][0]);
}
PRBool
LayerManagerOGL::SetupBackBuffer()
{
nsIntRect rect;
mWidget->GetBounds(rect);
GLint width = rect.width;
GLint height = rect.height;
if (width == mBackBufferSize.width && height == mBackBufferSize.height) {
return PR_TRUE;
}
if (!mBackBuffer) {
sglWrapper.GenTextures(1, &mBackBuffer);
}
/**
* Setup the texture used as the backbuffer.
*/
sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, mBackBuffer);
sglWrapper.TexEnvf(LOCAL_GL_TEXTURE_ENV, LOCAL_GL_TEXTURE_ENV_MODE, LOCAL_GL_MODULATE);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
sglWrapper.TexImage2D(LOCAL_GL_TEXTURE_2D,
0,
LOCAL_GL_RGBA,
width,
height,
0,
LOCAL_GL_RGBA,
LOCAL_GL_UNSIGNED_BYTE,
NULL);
/**
* Create the framebuffer and bind it to make our content render into our
* framebuffer.
*/
if (!mFrameBuffer) {
sglWrapper.GenFramebuffersEXT(1, &mFrameBuffer);
}
sglWrapper.BindFramebufferEXT(LOCAL_GL_FRAMEBUFFER_EXT, mFrameBuffer);
sglWrapper.FramebufferTexture2DEXT(LOCAL_GL_FRAMEBUFFER_EXT,
LOCAL_GL_COLOR_ATTACHMENT0_EXT,
LOCAL_GL_TEXTURE_2D,
mBackBuffer,
0);
return PR_TRUE;
}
void
LayerManagerOGL::CopyToTarget()
{
nsIntRect rect;
mWidget->GetBounds(rect);
GLint width = rect.width;
GLint height = rect.height;
if ((PRInt64)width * (PRInt64)height > PR_INT32_MAX) {
NS_ERROR("Widget size too big - integer overflow!");
return;
}
nsRefPtr<gfxImageSurface> imageSurface =
new gfxImageSurface(gfxIntSize(width, height),
gfxASurface::ImageFormatARGB32);
sglWrapper.ReadBuffer(LOCAL_GL_COLOR_ATTACHMENT0_EXT);
if (imageSurface->Stride() != width * 4) {
char *tmpData = new char[width * height * 4];
sglWrapper.ReadPixels(0,
0,
width,
height,
LOCAL_GL_BGRA,
LOCAL_GL_UNSIGNED_BYTE,
tmpData);
sglWrapper.Finish();
for (int y = 0; y < height; y++) {
memcpy(imageSurface->Data() + imageSurface->Stride() * y,
tmpData + width * 4 * y,
width * 4);
}
delete [] tmpData;
} else {
sglWrapper.ReadPixels(0,
0,
width,
height,
LOCAL_GL_BGRA,
LOCAL_GL_UNSIGNED_BYTE,
imageSurface->Data());
sglWrapper.Finish();
}
mTarget->SetOperator(gfxContext::OPERATOR_OVER);
mTarget->SetSource(imageSurface);
mTarget->Paint();
}
LayerOGL::LayerOGL()
: mNextSibling(NULL)
{
}
LayerOGL*
LayerOGL::GetNextSibling()
{
return mNextSibling;
}
void
LayerOGL::SetNextSibling(LayerOGL *aNextSibling)
{
mNextSibling = aNextSibling;
}
/**
* LayerProgram Helpers
*/
LayerProgram::LayerProgram()
: mProgram(0)
{
}
LayerProgram::~LayerProgram()
{
sglWrapper.DeleteProgram(mProgram);
}
PRBool
LayerProgram::Initialize(GLuint aVertexShader, GLuint aFragmentShader)
{
mProgram = sglWrapper.CreateProgram();
sglWrapper.AttachShader(mProgram, aVertexShader);
sglWrapper.AttachShader(mProgram, aFragmentShader);
sglWrapper.BindAttribLocation(mProgram, VERTEX_ATTRIB_LOCATION, "aVertex");
sglWrapper.LinkProgram(mProgram);
GLint status;
sglWrapper.GetProgramiv(mProgram, LOCAL_GL_LINK_STATUS, &status);
if (!status) {
return false;
}
return true;
}
void
LayerProgram::Activate()
{
sglWrapper.UseProgram(mProgram);
}
void
LayerProgram::UpdateLocations()
{
mMatrixProjLocation = sglWrapper.GetUniformLocation(mProgram, "uMatrixProj");
mLayerQuadTransformLocation =
sglWrapper.GetUniformLocation(mProgram, "uLayerQuadTransform");
mLayerTransformLocation = sglWrapper.GetUniformLocation(mProgram, "uLayerTransform");
mRenderTargetOffsetLocation =
sglWrapper.GetUniformLocation(mProgram, "uRenderTargetOffset");
mLayerOpacityLocation = sglWrapper.GetUniformLocation(mProgram, "uLayerOpacity");
}
void
LayerProgram::SetMatrixUniform(GLint aLocation, const GLfloat *aValue)
{
sglWrapper.UniformMatrix4fv(aLocation, 1, false, aValue);
}
void
LayerProgram::SetInt(GLint aLocation, GLint aValue)
{
sglWrapper.Uniform1i(aLocation, aValue);
}
void
LayerProgram::SetLayerOpacity(GLfloat aValue)
{
sglWrapper.Uniform1f(mLayerOpacityLocation, aValue);
}
void
LayerProgram::PushRenderTargetOffset(GLfloat aValueX, GLfloat aValueY)
{
GLvec2 vector;
vector.mX = aValueX;
vector.mY = aValueY;
mRenderTargetOffsetStack.AppendElement(vector);
}
void
LayerProgram::PopRenderTargetOffset()
{
NS_ASSERTION(mRenderTargetOffsetStack.Length(), "Unbalanced push/pops");
mRenderTargetOffsetStack.RemoveElementAt(mRenderTargetOffsetStack.Length() - 1);
}
void
LayerProgram::Apply()
{
if (!mRenderTargetOffsetStack.Length()) {
sglWrapper.Uniform4f(mRenderTargetOffsetLocation, 0, 0, 0, 0);
} else {
GLvec2 vector =
mRenderTargetOffsetStack[mRenderTargetOffsetStack.Length() - 1];
sglWrapper.Uniform4f(mRenderTargetOffsetLocation, vector.mX, vector.mY, 0, 0);
}
}
void
RGBLayerProgram::UpdateLocations()
{
LayerProgram::UpdateLocations();
mLayerTextureLocation = sglWrapper.GetUniformLocation(mProgram, "uLayerTexture");
}
void
YCbCrLayerProgram::UpdateLocations()
{
LayerProgram::UpdateLocations();
mYTextureLocation = sglWrapper.GetUniformLocation(mProgram, "uYTexture");
mCbTextureLocation = sglWrapper.GetUniformLocation(mProgram, "uCbTexture");
mCrTextureLocation = sglWrapper.GetUniformLocation(mProgram, "uCrTexture");
}
} /* layers */
} /* mozilla */

View File

@ -0,0 +1,306 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** 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) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.org>
*
* 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_LAYERMANAGEROGL_H
#define GFX_LAYERMANAGEROGL_H
#include "Layers.h"
#ifdef XP_WIN
#include <windows.h>
#endif
typedef unsigned int GLuint;
typedef int GLint;
typedef float GLfloat;
typedef char GLchar;
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
#include "gfxContext.h"
#include "nsIWidget.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);
virtual void UpdateLocations();
void Activate();
void SetMatrixUniform(GLint aLocation, const GLfloat *aValue);
void SetInt(GLint aLocation, GLint aValue);
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:
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 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.
*/
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
* to draw to the window. If this method fails the device cannot be used.
* This function is not threadsafe.
*
* \return True is initialization was succesful, false when it was not.
*/
PRBool Initialize();
/**
* Sets the clipping region for this layer manager. This is important on
* windows because using OGL we no longer have GDI's native clipping. Therefor
* widget must tell us what part of the screen is being invalidated,
* and we should clip to this.
*
* \param aClippingRegion Region to clip to. Setting an empty region
* will disable clipping.
*/
void SetClippingRegion(const nsIntRegion& aClippingRegion);
/**
* LayerManager implementation.
*/
void BeginTransaction();
void BeginTransactionWithTarget(gfxContext* aTarget);
void EndConstruction();
void EndTransaction();
void SetRoot(Layer* aLayer);
virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
virtual already_AddRefed<ImageLayer> CreateImageLayer();
virtual already_AddRefed<ImageContainer> CreateImageContainer();
/**
* Helper methods.
*/
void SetClippingEnabled(PRBool aEnabled);
void MakeCurrent();
RGBLayerProgram *GetRGBLayerProgram() { return mRGBLayerProgram; }
YCbCrLayerProgram *GetYCbCrLayerProgram() { return mYCbCrLayerProgram; }
private:
/** Widget associated with this layer manager */
nsIWidget *mWidget;
/**
* Context target, NULL when drawing directly to our swap chain.
*/
nsRefPtr<gfxContext> mTarget;
#ifdef XP_WIN
/** Windows Device Context */
HDC mDC;
/** OpenGL Context */
HGLRC mContext;
#endif
/** Backbuffer */
GLuint mBackBuffer;
/** Backbuffer size */
nsIntSize mBackBufferSize;
/** Framebuffer */
GLuint mFrameBuffer;
/** RGB Layer Program */
RGBLayerProgram *mRGBLayerProgram;
/** YUV Layer Program */
YCbCrLayerProgram *mYCbCrLayerProgram;
/** Vertex Shader */
GLuint mVertexShader;
/** RGB fragment shader */
GLuint mRGBShader;
/** YUV fragment shader */
GLuint mYUVShader;
/** Current root layer. */
LayerOGL *mRootLayer;
/** Vertex buffer */
GLuint mVBO;
/**
* Region we're clipping our current drawing to.
*/
nsIntRegion mClippingRegion;
/**
* Render the current layer tree to the active target.
*/
void Render();
/**
* Setup the pipeline.
*/
void SetupPipeline();
/**
* Setup the backbuffer.
*
* \return PR_TRUE if setup was succesful
*/
PRBool SetupBackBuffer();
/**
* Copies the content of our backbuffer to the set transaction target.
*/
void CopyToTarget();
};
/**
* General information and tree management for OGL layers.
*/
class LayerOGL
{
public:
LayerOGL();
enum LayerType { TYPE_THEBES, TYPE_CONTAINER, TYPE_IMAGE };
virtual LayerType GetType() = 0;
LayerOGL *GetNextSibling();
virtual LayerOGL *GetFirstChildOGL() { return nsnull; }
void SetNextSibling(LayerOGL *aParent);
void SetFirstChild(LayerOGL *aParent);
virtual Layer* GetLayer() = 0;
virtual void RenderLayer(int aPreviousFrameBuffer) = 0;
protected:
LayerOGL *mNextSibling;
};
} /* layers */
} /* mozilla */
#endif /* GFX_LAYERMANAGEROGL_H */

View File

@ -0,0 +1,42 @@
#define SHADER_GLOBAL_VARS "uniform mat4 uMatrixProj; \
uniform mat4 uLayerQuadTransform; \
uniform mat4 uLayerTransform; \
uniform vec4 uRenderTargetOffset; \
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 *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.0f; \
gl_FragColor = color * uLayerOpacity; \
}";

View File

@ -0,0 +1,249 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** 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) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.org>
*
* 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 ***** */
#include "ThebesLayerOGL.h"
#include "ContainerLayerOGL.h"
#include "gfxContext.h"
#include "glWrapper.h"
namespace mozilla {
namespace layers {
// Returns true if it's OK to save the contents of aLayer in an
// opaque surface (a surface without an alpha channel).
// If we can use a surface without an alpha channel, we should, because
// it will often make painting of antialiased text faster and higher
// quality.
static PRBool
UseOpaqueSurface(Layer* aLayer)
{
// If the visible content in the layer is opaque, there is no need
// for an alpha channel.
if (aLayer->IsOpaqueContent())
return PR_TRUE;
// Also, if this layer is the bottommost layer in a container which
// doesn't need an alpha channel, we can use an opaque surface for this
// layer too. Any transparent areas must be covered by something else
// in the container.
ContainerLayerOGL* parent =
static_cast<ContainerLayerOGL*>(aLayer->GetParent());
return parent && parent->GetFirstChild() == aLayer &&
UseOpaqueSurface(parent);
}
ThebesLayerOGL::ThebesLayerOGL(LayerManager *aManager)
: ThebesLayer(aManager, NULL)
, mTexture(0)
{
mImplData = static_cast<LayerOGL*>(this);
}
ThebesLayerOGL::~ThebesLayerOGL()
{
static_cast<LayerManagerOGL*>(mManager)->MakeCurrent();
if (mTexture) {
sglWrapper.DeleteTextures(1, &mTexture);
}
}
void
ThebesLayerOGL::SetVisibleRegion(const nsIntRegion &aRegion)
{
if (aRegion.GetBounds() == mVisibleRect) {
return;
}
mVisibleRect = aRegion.GetBounds();
static_cast<LayerManagerOGL*>(mManager)->MakeCurrent();
if (!mTexture) {
sglWrapper.GenTextures(1, &mTexture);
}
mInvalidatedRect = mVisibleRect;
sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
sglWrapper.TexImage2D(LOCAL_GL_TEXTURE_2D,
0,
LOCAL_GL_RGBA,
mVisibleRect.width,
mVisibleRect.height,
0,
LOCAL_GL_BGRA,
LOCAL_GL_UNSIGNED_BYTE,
NULL);
}
void
ThebesLayerOGL::InvalidateRegion(const nsIntRegion &aRegion)
{
nsIntRegion invalidatedRegion;
invalidatedRegion.Or(aRegion, mInvalidatedRect);
invalidatedRegion.And(invalidatedRegion, mVisibleRect);
mInvalidatedRect = invalidatedRegion.GetBounds();
}
gfxContext *
ThebesLayerOGL::BeginDrawing(nsIntRegion *aRegion)
{
if (mInvalidatedRect.IsEmpty()) {
aRegion->SetEmpty();
return NULL;
}
if (!mTexture) {
aRegion->SetEmpty();
return NULL;
}
*aRegion = mInvalidatedRect;
if (UseOpaqueSurface(this)) {
mSoftwareSurface = new gfxImageSurface(gfxIntSize(mInvalidatedRect.width,
mInvalidatedRect.height),
gfxASurface::ImageFormatRGB24);
} else {
mSoftwareSurface = new gfxImageSurface(gfxIntSize(mInvalidatedRect.width,
mInvalidatedRect.height),
gfxASurface::ImageFormatARGB32);
}
mContext = new gfxContext(mSoftwareSurface);
mContext->Translate(gfxPoint(-mInvalidatedRect.x, -mInvalidatedRect.y));
return mContext.get();
}
void
ThebesLayerOGL::EndDrawing()
{
static_cast<LayerManagerOGL*>(mManager)->MakeCurrent();
sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
sglWrapper.TexSubImage2D(LOCAL_GL_TEXTURE_2D,
0,
mInvalidatedRect.x - mVisibleRect.x,
mInvalidatedRect.y - mVisibleRect.y,
mInvalidatedRect.width,
mInvalidatedRect.height,
LOCAL_GL_BGRA,
LOCAL_GL_UNSIGNED_BYTE,
mSoftwareSurface->Data());
mSoftwareSurface = NULL;
mContext = NULL;
}
void
ThebesLayerOGL::CopyFrom(ThebesLayer* aSource,
const nsIntRegion& aRegion,
const nsIntPoint& aDelta)
{
// XXX - Roc says this is going away in the API. Ignore it for now.
}
LayerOGL::LayerType
ThebesLayerOGL::GetType()
{
return TYPE_THEBES;
}
const nsIntRect&
ThebesLayerOGL::GetVisibleRect()
{
return mVisibleRect;
}
void
ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer)
{
if (!mTexture) {
return;
}
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;
RGBLayerProgram *program =
static_cast<LayerManagerOGL*>(mManager)->GetRGBLayerProgram();
program->Activate();
program->SetLayerQuadTransform(&quadTransform[0][0]);
program->SetLayerOpacity(GetOpacity());
program->SetLayerTransform(&mTransform._11);
program->Apply();
sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
sglWrapper.DrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
}
const nsIntRect&
ThebesLayerOGL::GetInvalidatedRect()
{
return mInvalidatedRect;
}
Layer*
ThebesLayerOGL::GetLayer()
{
return this;
}
PRBool
ThebesLayerOGL::IsEmpty()
{
return !mTexture;
}
} /* layers */
} /* mozilla */

View File

@ -0,0 +1,110 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** 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) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.org>
*
* 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_THEBESLAYEROGL_H
#define GFX_THEBESLAYEROGL_H
#include "Layers.h"
#include "LayerManagerOGL.h"
#include "gfxImageSurface.h"
namespace mozilla {
namespace layers {
class ThebesLayerOGL : public ThebesLayer,
public LayerOGL
{
public:
ThebesLayerOGL(LayerManager *aManager);
virtual ~ThebesLayerOGL();
/** Layer implementation */
void SetVisibleRegion(const nsIntRegion& aRegion);
/** ThebesLayer implementation */
void InvalidateRegion(const nsIntRegion& aRegion);
gfxContext *BeginDrawing(nsIntRegion* aRegionToDraw);
void EndDrawing();
void CopyFrom(ThebesLayer* aSource,
const nsIntRegion& aRegion,
const nsIntPoint& aDelta);
/** LayerOGL implementation */
LayerType GetType();
Layer* GetLayer();
virtual PRBool IsEmpty();
virtual void RenderLayer(int aPreviousFrameBuffer);
/** ThebesLayerOGL */
const nsIntRect &GetVisibleRect();
const nsIntRect &GetInvalidatedRect();
private:
/**
* Visible rectangle, this is used to know the size and position of the quad
* when doing the rendering of this layer.
*/
nsIntRect mVisibleRect;
/**
* Currently invalidated rectangular area.
*/
nsIntRect mInvalidatedRect;
/**
* Software surface used for this layer's drawing operation. This is created
* on BeginDrawing() and should be removed on EndDrawing().
*/
nsRefPtr<gfxImageSurface> mSoftwareSurface;
/**
* We hold the reference to the context.
*/
nsRefPtr<gfxContext> mContext;
/**
* OpenGL Texture
*/
GLuint mTexture;
};
} /* layers */
} /* mozilla */
#endif /* GFX_THEBESLAYEROGL_H */

3028
gfx/layers/opengl/glDefs.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,215 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** 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) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.org>
*
* 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 ***** */
#include "glWrapper.h"
#include "nsDebug.h"
#ifdef XP_WIN
#define glGetProcAddress wGetProcAddress
#else
// We do not know how to glGetProcAddress on this platform.
PRFuncPtr glGetProcAddress(const char *)
{
return NULL;
}
#endif
glWrapper sglWrapper;
struct OGLFunction {
PRFuncPtr *functor;
const char *name;
};
glWrapper::glWrapper()
: mIsInitialized(PR_FALSE)
, mOGLLibrary(NULL)
{
}
#ifdef XP_WIN
HGLRC
glWrapper::wCreateContext(HDC aDC)
{
if (!wCreateContextInternal) {
if (!mOGLLibrary) {
#ifdef XP_WIN
mOGLLibrary = PR_LoadLibrary("Opengl32.dll");
#else
return NULL;
#endif
if (!mOGLLibrary) {
NS_WARNING("Couldn't load OpenGL DLL.");
return NULL;
}
}
wCreateContextInternal = (PFNWGLCREATECONTEXTPROC)
PR_FindSymbol(mOGLLibrary, "wglCreateContext");
wDeleteContext = (PFNWGLDELETECONTEXTPROC)
PR_FindSymbol(mOGLLibrary, "wglDeleteContext");
wMakeCurrent = (PFNWGLMAKECURRENTPROC)
PR_FindSymbol(mOGLLibrary, "wglMakeCurrent");
wGetProcAddress = (PFNWGLGETPROCADDRESSPROC)
PR_FindSymbol(mOGLLibrary, "wglGetProcAddress");
}
HGLRC retval = wCreateContextInternal(aDC);
if (!retval) {
return retval;
}
wMakeCurrent(aDC, retval);
if (!EnsureInitialized()) {
NS_WARNING("Failed to initialize OpenGL wrapper.");
return NULL;
}
return retval;
}
#endif
PRBool
glWrapper::LoadSymbols(OGLFunction *functions)
{
for (int i = 0; functions[i].functor; i++) {
*functions[i].functor =
PR_FindFunctionSymbol(mOGLLibrary, functions[i].name);
if (*functions[i].functor) {
continue;
}
if (!glGetProcAddress) {
return PR_FALSE;
}
*functions[i].functor = (PRFuncPtr)glGetProcAddress(functions[i].name);
if (!*functions[i].functor) {
return PR_FALSE;
}
}
return PR_TRUE;
}
PRBool
glWrapper::EnsureInitialized()
{
if (mIsInitialized) {
return PR_TRUE;
}
OGLFunction functions[] = {
{ (PRFuncPtr*) &BlendFuncSeparate, "glBlendFuncSeparate" },
{ (PRFuncPtr*) &Enable, "glEnable" },
{ (PRFuncPtr*) &EnableClientState, "glEnableClientState" },
{ (PRFuncPtr*) &EnableVertexAttribArray, "glEnableVertexAttribArray" },
{ (PRFuncPtr*) &Disable, "glDisable" },
{ (PRFuncPtr*) &DisableClientState, "glDisableClientState" },
{ (PRFuncPtr*) &DisableVertexAttribArray, "glDisableVertexAttribArray" },
{ (PRFuncPtr*) &DrawArrays, "glDrawArrays" },
{ (PRFuncPtr*) &Finish, "glFinish" },
{ (PRFuncPtr*) &Clear, "glClear" },
{ (PRFuncPtr*) &Scissor, "glScissor" },
{ (PRFuncPtr*) &Viewport, "glViewport" },
{ (PRFuncPtr*) &ClearColor, "glClearColor" },
{ (PRFuncPtr*) &ReadBuffer, "glReadBuffer" },
{ (PRFuncPtr*) &ReadPixels, "glReadPixels" },
{ (PRFuncPtr*) &TexEnvf, "glTexEnvf" },
{ (PRFuncPtr*) &TexParameteri, "glTexParameteri" },
{ (PRFuncPtr*) &ActiveTexture, "glActiveTexture" },
{ (PRFuncPtr*) &PixelStorei, "glPixelStorei" },
{ (PRFuncPtr*) &GenTextures, "glGenTextures" },
{ (PRFuncPtr*) &GenBuffers, "glGenBuffers" },
{ (PRFuncPtr*) &GenFramebuffersEXT, "glGenFramebuffersEXT" },
{ (PRFuncPtr*) &DeleteTextures, "glDeleteTextures" },
{ (PRFuncPtr*) &DeleteFramebuffersEXT, "glDeleteFramebuffersEXT" },
{ (PRFuncPtr*) &BindTexture, "glBindTexture" },
{ (PRFuncPtr*) &BindBuffer, "glBindBuffer" },
{ (PRFuncPtr*) &BindFramebufferEXT, "glBindFramebufferEXT" },
{ (PRFuncPtr*) &FramebufferTexture2DEXT, "glFramebufferTexture2DEXT" },
{ (PRFuncPtr*) &BufferData, "glBufferData" },
{ (PRFuncPtr*) &VertexPointer, "glVertexPointer" },
{ (PRFuncPtr*) &TexCoordPointer, "glTexCoordPointer" },
{ (PRFuncPtr*) &TexImage2D, "glTexImage2D" },
{ (PRFuncPtr*) &TexSubImage2D, "glTexSubImage2D" },
{ (PRFuncPtr*) &CreateShader, "glCreateShader" },
{ (PRFuncPtr*) &CreateProgram, "glCreateProgram" },
{ (PRFuncPtr*) &DeleteProgram, "glDeleteProgram" },
{ (PRFuncPtr*) &UseProgram, "glUseProgram" },
{ (PRFuncPtr*) &ShaderSource, "glShaderSource" },
{ (PRFuncPtr*) &CompileShader, "glCompileShader" },
{ (PRFuncPtr*) &AttachShader, "glAttachShader" },
{ (PRFuncPtr*) &LinkProgram, "glLinkProgram" },
{ (PRFuncPtr*) &GetProgramiv, "glGetProgramiv" },
{ (PRFuncPtr*) &GetShaderiv, "glGetShaderiv" },
{ (PRFuncPtr*) &BindAttribLocation, "glBindAttribLocation" },
{ (PRFuncPtr*) &VertexAttribPointer, "glVertexAttribPointer" },
{ (PRFuncPtr*) &Uniform1i, "glUniform1i" },
{ (PRFuncPtr*) &Uniform1f, "glUniform1f" },
{ (PRFuncPtr*) &Uniform4f, "glUniform4f" },
{ (PRFuncPtr*) &UniformMatrix4fv, "glUniformMatrix4fv" },
{ (PRFuncPtr*) &GetUniformLocation, "glGetUniformLocation" },
{ (PRFuncPtr*) &GetString, "glGetString" },
{ NULL, NULL }
};
if (!LoadSymbols(functions)) {
return PR_FALSE;
}
mIsInitialized = PR_TRUE;
return PR_TRUE;
}

View File

@ -0,0 +1,277 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** 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) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.org>
*
* 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_GLWRAPPER_H
#define GFX_GLWRAPPER_H
#ifdef XP_WIN
#include <windows.h>
#endif
#include "prlink.h"
#include "glDefs.h"
struct OGLFunction;
class glWrapper
{
public:
glWrapper();
typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEPROC) (GLenum,
GLenum,
GLenum,
GLenum);
typedef void (GLAPIENTRY * PFNGLENABLEPROC) (GLenum);
typedef void (GLAPIENTRY * PFNGLENABLECLIENTSTATEPROC) (GLenum);
typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint);
typedef void (GLAPIENTRY * PFNGLDISABLEPROC) (GLenum);
typedef void (GLAPIENTRY * PFNGLDISABLECLIENTSTATEPROC) (GLenum);
typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint);
typedef void (GLAPIENTRY * PFNGLDRAWARRAYSPROC) (GLenum, GLint, GLsizei);
typedef void (GLAPIENTRY * PFNGLFINISHPROC) (void);
typedef void (GLAPIENTRY * PFNGLCLEARPROC) (GLbitfield);
typedef void (GLAPIENTRY * PFNGLSCISSORPROC) (GLint, GLint, GLsizei, GLsizei);
typedef void (GLAPIENTRY * PFNGLVIEWPORTPROC) (GLint, GLint, GLsizei, GLsizei);
typedef void (GLAPIENTRY * PFNGLCLEARCOLORPROC) (GLclampf,
GLclampf,
GLclampf,
GLclampf);
typedef void (GLAPIENTRY * PFNGLREADBUFFERPROC) (GLenum);
typedef void (GLAPIENTRY * PFNGLREADPIXELSPROC) (GLint,
GLint,
GLsizei,
GLsizei,
GLenum,
GLenum,
GLvoid *);
typedef void (GLAPIENTRY * PFNGLTEXENVFPROC) (GLenum, GLenum, GLfloat);
typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIPROC) (GLenum, GLenum, GLint);
typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum);
typedef void (GLAPIENTRY * PFNGLPIXELSTOREIPROC) (GLenum, GLint);
typedef void (GLAPIENTRY * PFNGLGENTEXTURESPROC) (GLsizei, GLuint *);
typedef void (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei, GLuint *);
typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei, GLuint *);
typedef void (GLAPIENTRY * PFNGLDELETETEXTURESPROC) (GLsizei, const GLuint *);
typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei,
const GLuint *);
typedef void (GLAPIENTRY * PFNGLBINDTEXTUREPROC) (GLenum, GLuint);
typedef void (GLAPIENTRY * PFNGLBINDBUFFERPROC) (GLenum, GLuint);
typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum, GLuint);
typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum,
GLenum,
GLenum,
GLuint,
GLint);
typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum,
GLsizeiptr,
const GLvoid *,
GLenum);
typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERPROC) (GLint,
GLenum,
GLsizei,
const GLvoid *);
typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERPROC) (GLint,
GLenum,
GLsizei,
const GLvoid *);
typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DPROC) (GLenum,
GLint,
GLint,
GLsizei,
GLsizei,
GLint,
GLenum,
GLenum,
const GLvoid *);
typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DPROC) (GLenum,
GLint,
GLint,
GLint,
GLsizei,
GLsizei,
GLenum,
GLenum,
const GLvoid *);
typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROC) (GLenum);
typedef GLuint (GLAPIENTRY * PFNGLCREATEPROGRAMPROC) (void);
typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPROC) (GLuint);
typedef void (GLAPIENTRY * PFNGLUSEPROGRAMPROC) (GLuint);
typedef void (GLAPIENTRY * PFNGLSHADERSOURCEPROC) (GLuint,
GLsizei,
const GLchar **,
const GLint *);
typedef void (GLAPIENTRY * PFNGLCOMPILESHADERPROC) (GLuint);
typedef void (GLAPIENTRY * PFNGLATTACHSHADERPROC) (GLuint, GLuint);
typedef void (GLAPIENTRY * PFNGLLINKPROGRAMPROC) (GLuint);
typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVPROC) (GLuint, GLenum, GLint *);
typedef void (GLAPIENTRY * PFNGLGETSHADERIVPROC) (GLuint, GLenum, GLint *);
typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONPROC) (GLuint,
GLuint,
const GLchar *);
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint,
GLint,
GLenum,
GLboolean,
GLsizei,
const GLvoid *);
typedef void (GLAPIENTRY * PFNGLUNIFORM1IPROC) (GLint, GLint);
typedef void (GLAPIENTRY * PFNGLUNIFORM1FPROC) (GLint, GLfloat);
typedef void (GLAPIENTRY * PFNGLUNIFORM4FPROC) (GLint,
GLfloat,
GLfloat,
GLfloat,
GLfloat);
typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVPROC) (GLint,
GLsizei,
GLboolean,
const GLfloat *);
typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONPROC) (GLuint,
const GLchar *);
typedef GLubyte* (GLAPIENTRY * PFNGLGETSTRINGPROC) (GLenum);
#ifdef XP_WIN
typedef HGLRC (GLAPIENTRY * PFNWGLCREATECONTEXTPROC) (HDC);
typedef BOOL (GLAPIENTRY * PFNWGLDELETECONTEXTPROC) (HGLRC);
typedef BOOL (GLAPIENTRY * PFNWGLMAKECURRENTPROC) (HDC, HGLRC);
typedef PROC (GLAPIENTRY * PFNWGLGETPROCADDRESSPROC) (LPCSTR);
#endif
PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate;
PFNGLENABLEPROC Enable;
PFNGLENABLECLIENTSTATEPROC EnableClientState;
PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray;
PFNGLDISABLEPROC Disable;
PFNGLDISABLECLIENTSTATEPROC DisableClientState;
PFNGLDISABLEVERTEXATTRIBARRAYPROC DisableVertexAttribArray;
PFNGLDRAWARRAYSPROC DrawArrays;
PFNGLFINISHPROC Finish;
PFNGLCLEARPROC Clear;
PFNGLSCISSORPROC Scissor;
PFNGLVIEWPORTPROC Viewport;
PFNGLCLEARCOLORPROC ClearColor;
PFNGLREADBUFFERPROC ReadBuffer;
PFNGLREADPIXELSPROC ReadPixels;
PFNGLTEXENVFPROC TexEnvf;
PFNGLTEXPARAMETERIPROC TexParameteri;
PFNGLACTIVETEXTUREPROC ActiveTexture;
PFNGLPIXELSTOREIPROC PixelStorei;
PFNGLGENTEXTURESPROC GenTextures;
PFNGLGENBUFFERSPROC GenBuffers;
PFNGLGENFRAMEBUFFERSEXTPROC GenFramebuffersEXT;
PFNGLDELETETEXTURESPROC DeleteTextures;
PFNGLDELETEFRAMEBUFFERSEXTPROC DeleteFramebuffersEXT;
PFNGLBINDTEXTUREPROC BindTexture;
PFNGLBINDBUFFERPROC BindBuffer;
PFNGLBINDFRAMEBUFFEREXTPROC BindFramebufferEXT;
PFNGLFRAMEBUFFERTEXTURE2DEXTPROC FramebufferTexture2DEXT;
PFNGLBUFFERDATAPROC BufferData;
PFNGLVERTEXPOINTERPROC VertexPointer;
PFNGLTEXCOORDPOINTERPROC TexCoordPointer;
PFNGLTEXIMAGE2DPROC TexImage2D;
PFNGLTEXSUBIMAGE2DPROC TexSubImage2D;
PFNGLCREATESHADERPROC CreateShader;
PFNGLCREATEPROGRAMPROC CreateProgram;
PFNGLDELETEPROGRAMPROC DeleteProgram;
PFNGLUSEPROGRAMPROC UseProgram;
PFNGLSHADERSOURCEPROC ShaderSource;
PFNGLCOMPILESHADERPROC CompileShader;
PFNGLATTACHSHADERPROC AttachShader;
PFNGLLINKPROGRAMPROC LinkProgram;
PFNGLGETPROGRAMIVPROC GetProgramiv;
PFNGLGETSHADERIVPROC GetShaderiv;
PFNGLBINDATTRIBLOCATIONPROC BindAttribLocation;
PFNGLVERTEXATTRIBPOINTERPROC VertexAttribPointer;
PFNGLUNIFORM1IPROC Uniform1i;
PFNGLUNIFORM1FPROC Uniform1f;
PFNGLUNIFORM4FPROC Uniform4f;
PFNGLUNIFORMMATRIX4FVPROC UniformMatrix4fv;
PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation;
PFNGLGETSTRINGPROC GetString;
#ifdef XP_WIN
/**
* We intercept this call and do some stuff (like load the wglCreateContext
* and ensure our other function pointers are initialized.
*/
HGLRC wCreateContext(HDC aDC);
PFNWGLCREATECONTEXTPROC wCreateContextInternal;
PFNWGLDELETECONTEXTPROC wDeleteContext;
PFNWGLMAKECURRENTPROC wMakeCurrent;
PFNWGLGETPROCADDRESSPROC wGetProcAddress;
#endif
private:
PRBool EnsureInitialized();
PRBool LoadSymbols(OGLFunction *functions);
PRBool mIsInitialized;
PRLibrary *mOGLLibrary;
};
extern glWrapper sglWrapper;
#endif