зеркало из https://github.com/mozilla/gecko-dev.git
Backed out csets 807f2c3df974, 1637c39b4ed6, ec29e09a270e (bug 811958) for burning android
This commit is contained in:
Родитель
d90aa800b3
Коммит
1039582660
|
@ -129,10 +129,7 @@ public:
|
|||
if (mTextureInfo.mWidth == 0 || mTextureInfo.mHeight == 0)
|
||||
return 0;
|
||||
|
||||
SharedTextureHandle handle =
|
||||
sPluginContext->CreateSharedHandle(GLContext::SameProcess,
|
||||
(void*)mTextureInfo.mTexture,
|
||||
GLContext::TextureID);
|
||||
SharedTextureHandle handle = sPluginContext->CreateSharedHandle(TextureImage::ThreadShared, (void*)mTextureInfo.mTexture, GLContext::TextureID);
|
||||
|
||||
// We want forget about this now, so delete the texture. Assigning it to zero
|
||||
// ensures that we create a new one in Lock()
|
||||
|
@ -1003,9 +1000,7 @@ SharedTextureHandle nsNPAPIPluginInstance::CreateSharedHandle()
|
|||
return mContentTexture->CreateSharedHandle();
|
||||
} else if (mContentSurface) {
|
||||
EnsureGLContext();
|
||||
return sPluginContext->CreateSharedHandle(GLContext::SameProcess,
|
||||
mContentSurface,
|
||||
GLContext::SurfaceTexture);
|
||||
return sPluginContext->CreateSharedHandle(TextureImage::ThreadShared, mContentSurface, GLContext::SurfaceTexture);
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ nsPluginInstanceOwner::GetImageContainer()
|
|||
|
||||
SharedTextureImage::Data data;
|
||||
data.mHandle = mInstance->CreateSharedHandle();
|
||||
data.mShareType = mozilla::gl::GLContext::SameProcess;
|
||||
data.mShareType = mozilla::gl::TextureImage::ThreadShared;
|
||||
data.mInverted = mInstance->Inverted();
|
||||
|
||||
gfxRect r = GetPluginRect();
|
||||
|
@ -1723,10 +1723,8 @@ already_AddRefed<ImageContainer> nsPluginInstanceOwner::GetImageContainerForVide
|
|||
|
||||
SharedTextureImage::Data data;
|
||||
|
||||
data.mShareType = gl::GLContext::SameProcess;
|
||||
data.mHandle = mInstance->GLContext()->CreateSharedHandle(data.mShareType,
|
||||
aVideoInfo->mSurfaceTexture,
|
||||
gl::GLContext::SurfaceTexture);
|
||||
data.mHandle = mInstance->GLContext()->CreateSharedHandle(gl::TextureImage::ThreadShared, aVideoInfo->mSurfaceTexture, gl::GLContext::SurfaceTexture);
|
||||
data.mShareType = mozilla::gl::TextureImage::ThreadShared;
|
||||
|
||||
// The logic below for Honeycomb is just a guess, but seems to work. We don't have a separate
|
||||
// inverted flag for video.
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Util.h" // for DebugOnly
|
||||
|
||||
#include "GLTextureImage.h"
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -740,19 +738,6 @@ GLContext::CreateTextureImage(const nsIntSize& aSize,
|
|||
return CreateBasicTextureImage(texture, aSize, aWrapMode, aContentType, this, aFlags);
|
||||
}
|
||||
|
||||
already_AddRefed<TextureImage>
|
||||
GLContext::CreateBasicTextureImage(GLuint aTexture,
|
||||
const nsIntSize& aSize,
|
||||
GLenum aWrapMode,
|
||||
TextureImage::ContentType aContentType,
|
||||
GLContext* aContext,
|
||||
TextureImage::Flags aFlags)
|
||||
{
|
||||
nsRefPtr<BasicTextureImage> teximage(
|
||||
new BasicTextureImage(aTexture, aSize, aWrapMode, aContentType, aContext, aFlags));
|
||||
return teximage.forget();
|
||||
}
|
||||
|
||||
void GLContext::ApplyFilterToBoundTexture(gfxPattern::GraphicsFilter aFilter)
|
||||
{
|
||||
ApplyFilterToBoundTexture(LOCAL_GL_TEXTURE_2D, aFilter);
|
||||
|
@ -770,6 +755,546 @@ void GLContext::ApplyFilterToBoundTexture(GLuint aTarget,
|
|||
}
|
||||
}
|
||||
|
||||
BasicTextureImage::~BasicTextureImage()
|
||||
{
|
||||
GLContext *ctx = mGLContext;
|
||||
if (ctx->IsDestroyed() || !ctx->IsOwningThreadCurrent()) {
|
||||
ctx = ctx->GetSharedContext();
|
||||
}
|
||||
|
||||
// If we have a context, then we need to delete the texture;
|
||||
// if we don't have a context (either real or shared),
|
||||
// then they went away when the contex was deleted, because it
|
||||
// was the only one that had access to it.
|
||||
if (ctx && !ctx->IsDestroyed()) {
|
||||
mGLContext->MakeCurrent();
|
||||
mGLContext->fDeleteTextures(1, &mTexture);
|
||||
}
|
||||
}
|
||||
|
||||
gfxASurface*
|
||||
BasicTextureImage::BeginUpdate(nsIntRegion& aRegion)
|
||||
{
|
||||
NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
|
||||
|
||||
// determine the region the client will need to repaint
|
||||
if (mGLContext->CanUploadSubTextures()) {
|
||||
GetUpdateRegion(aRegion);
|
||||
} else {
|
||||
aRegion = nsIntRect(nsIntPoint(0, 0), mSize);
|
||||
}
|
||||
|
||||
mUpdateRegion = aRegion;
|
||||
|
||||
nsIntRect rgnSize = mUpdateRegion.GetBounds();
|
||||
if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(rgnSize)) {
|
||||
NS_ERROR("update outside of image");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ImageFormat format =
|
||||
(GetContentType() == gfxASurface::CONTENT_COLOR) ?
|
||||
gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32;
|
||||
mUpdateSurface =
|
||||
GetSurfaceForUpdate(gfxIntSize(rgnSize.width, rgnSize.height), format);
|
||||
|
||||
if (!mUpdateSurface || mUpdateSurface->CairoStatus()) {
|
||||
mUpdateSurface = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mUpdateSurface->SetDeviceOffset(gfxPoint(-rgnSize.x, -rgnSize.y));
|
||||
|
||||
return mUpdateSurface;
|
||||
}
|
||||
|
||||
void
|
||||
BasicTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
|
||||
{
|
||||
// if the texture hasn't been initialized yet, or something important
|
||||
// changed, we need to recreate our backing surface and force the
|
||||
// client to paint everything
|
||||
if (mTextureState != Valid)
|
||||
aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
|
||||
}
|
||||
|
||||
void
|
||||
BasicTextureImage::EndUpdate()
|
||||
{
|
||||
NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
|
||||
|
||||
// FIXME: this is the slow boat. Make me fast (with GLXPixmap?).
|
||||
|
||||
// Undo the device offset that BeginUpdate set; doesn't much matter for us here,
|
||||
// but important if we ever do anything directly with the surface.
|
||||
mUpdateSurface->SetDeviceOffset(gfxPoint(0, 0));
|
||||
|
||||
bool relative = FinishedSurfaceUpdate();
|
||||
|
||||
mShaderType =
|
||||
mGLContext->UploadSurfaceToTexture(mUpdateSurface,
|
||||
mUpdateRegion,
|
||||
mTexture,
|
||||
mTextureState == Created,
|
||||
mUpdateOffset,
|
||||
relative);
|
||||
FinishedSurfaceUpload();
|
||||
|
||||
mUpdateSurface = nullptr;
|
||||
mTextureState = Valid;
|
||||
}
|
||||
|
||||
void
|
||||
BasicTextureImage::BindTexture(GLenum aTextureUnit)
|
||||
{
|
||||
mGLContext->fActiveTexture(aTextureUnit);
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
}
|
||||
|
||||
void
|
||||
BasicTextureImage::ApplyFilter()
|
||||
{
|
||||
mGLContext->ApplyFilterToBoundTexture(mFilter);
|
||||
}
|
||||
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
BasicTextureImage::GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt)
|
||||
{
|
||||
return gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenSurface(aSize, gfxASurface::ContentFromFormat(aFmt));
|
||||
}
|
||||
|
||||
bool
|
||||
BasicTextureImage::FinishedSurfaceUpdate()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
BasicTextureImage::FinishedSurfaceUpload()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
BasicTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
|
||||
{
|
||||
nsIntRect bounds = aRegion.GetBounds();
|
||||
nsIntRegion region;
|
||||
if (mTextureState != Valid) {
|
||||
bounds = nsIntRect(0, 0, mSize.width, mSize.height);
|
||||
region = nsIntRegion(bounds);
|
||||
} else {
|
||||
region = aRegion;
|
||||
}
|
||||
|
||||
mShaderType =
|
||||
mGLContext->UploadSurfaceToTexture(aSurf,
|
||||
region,
|
||||
mTexture,
|
||||
mTextureState == Created,
|
||||
bounds.TopLeft() + aFrom,
|
||||
false);
|
||||
mTextureState = Valid;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
BasicTextureImage::Resize(const nsIntSize& aSize)
|
||||
{
|
||||
NS_ASSERTION(!mUpdateSurface, "Resize() while in update?");
|
||||
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
NULL);
|
||||
|
||||
mTextureState = Allocated;
|
||||
mSize = aSize;
|
||||
}
|
||||
|
||||
TiledTextureImage::TiledTextureImage(GLContext* aGL,
|
||||
nsIntSize aSize,
|
||||
TextureImage::ContentType aContentType,
|
||||
TextureImage::Flags aFlags)
|
||||
: TextureImage(aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, aFlags)
|
||||
, mCurrentImage(0)
|
||||
, mIterationCallback(nullptr)
|
||||
, mInUpdate(false)
|
||||
, mRows(0)
|
||||
, mColumns(0)
|
||||
, mGL(aGL)
|
||||
, mTextureState(Created)
|
||||
{
|
||||
mTileSize = (!(aFlags & TextureImage::ForceSingleTile) && mGL->WantsSmallTiles())
|
||||
? 256 : mGL->GetMaxTextureSize();
|
||||
if (aSize != nsIntSize(0,0)) {
|
||||
Resize(aSize);
|
||||
}
|
||||
}
|
||||
|
||||
TiledTextureImage::~TiledTextureImage()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
TiledTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
|
||||
{
|
||||
nsIntRegion region;
|
||||
|
||||
if (mTextureState != Valid) {
|
||||
nsIntRect bounds = nsIntRect(0, 0, mSize.width, mSize.height);
|
||||
region = nsIntRegion(bounds);
|
||||
} else {
|
||||
region = aRegion;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
int oldCurrentImage = mCurrentImage;
|
||||
BeginTileIteration();
|
||||
do {
|
||||
nsIntRect tileRect = GetSrcTileRect();
|
||||
int xPos = tileRect.x;
|
||||
int yPos = tileRect.y;
|
||||
|
||||
nsIntRegion tileRegion;
|
||||
tileRegion.And(region, tileRect); // intersect with tile
|
||||
|
||||
if (tileRegion.IsEmpty())
|
||||
continue;
|
||||
|
||||
if (mGL->CanUploadSubTextures()) {
|
||||
tileRegion.MoveBy(-xPos, -yPos); // translate into tile local space
|
||||
} else {
|
||||
// If sub-textures are unsupported, expand to tile boundaries
|
||||
tileRect.x = tileRect.y = 0;
|
||||
tileRegion = nsIntRegion(tileRect);
|
||||
}
|
||||
|
||||
result &= mImages[mCurrentImage]->
|
||||
DirectUpdate(aSurf, tileRegion, aFrom + nsIntPoint(xPos, yPos));
|
||||
|
||||
if (mCurrentImage == mImages.Length() - 1) {
|
||||
// We know we're done, but we still need to ensure that the callback
|
||||
// gets called (e.g. to update the uploaded region).
|
||||
NextTile();
|
||||
break;
|
||||
}
|
||||
// Override a callback cancelling iteration if the texture wasn't valid.
|
||||
// We need to force the update in that situation, or we may end up
|
||||
// showing invalid/out-of-date texture data.
|
||||
} while (NextTile() || (mTextureState != Valid));
|
||||
mCurrentImage = oldCurrentImage;
|
||||
|
||||
mShaderType = mImages[0]->GetShaderProgramType();
|
||||
mTextureState = Valid;
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
TiledTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
|
||||
{
|
||||
if (mTextureState != Valid) {
|
||||
// if the texture hasn't been initialized yet, or something important
|
||||
// changed, we need to recreate our backing surface and force the
|
||||
// client to paint everything
|
||||
aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRegion newRegion;
|
||||
|
||||
// We need to query each texture with the region it will be drawing and
|
||||
// set aForRegion to be the combination of all of these regions
|
||||
for (unsigned i = 0; i < mImages.Length(); i++) {
|
||||
int xPos = (i % mColumns) * mTileSize;
|
||||
int yPos = (i / mColumns) * mTileSize;
|
||||
nsIntRect imageRect = nsIntRect(nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize()));
|
||||
|
||||
if (aForRegion.Intersects(imageRect)) {
|
||||
// Make a copy of the region
|
||||
nsIntRegion subRegion;
|
||||
subRegion.And(aForRegion, imageRect);
|
||||
// Translate it into tile-space
|
||||
subRegion.MoveBy(-xPos, -yPos);
|
||||
// Query region
|
||||
mImages[i]->GetUpdateRegion(subRegion);
|
||||
// Translate back
|
||||
subRegion.MoveBy(xPos, yPos);
|
||||
// Add to the accumulated region
|
||||
newRegion.Or(newRegion, subRegion);
|
||||
}
|
||||
}
|
||||
|
||||
aForRegion = newRegion;
|
||||
}
|
||||
|
||||
gfxASurface*
|
||||
TiledTextureImage::BeginUpdate(nsIntRegion& aRegion)
|
||||
{
|
||||
NS_ASSERTION(!mInUpdate, "nested update");
|
||||
mInUpdate = true;
|
||||
|
||||
// Note, we don't call GetUpdateRegion here as if the updated region is
|
||||
// fully contained in a single tile, we get to avoid iterating through
|
||||
// the tiles again (and a little copying).
|
||||
if (mTextureState != Valid)
|
||||
{
|
||||
// if the texture hasn't been initialized yet, or something important
|
||||
// changed, we need to recreate our backing surface and force the
|
||||
// client to paint everything
|
||||
aRegion = nsIntRect(nsIntPoint(0, 0), mSize);
|
||||
}
|
||||
|
||||
nsIntRect bounds = aRegion.GetBounds();
|
||||
|
||||
for (unsigned i = 0; i < mImages.Length(); i++) {
|
||||
int xPos = (i % mColumns) * mTileSize;
|
||||
int yPos = (i / mColumns) * mTileSize;
|
||||
nsIntRegion imageRegion = nsIntRegion(nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize()));
|
||||
|
||||
// a single Image can handle this update request
|
||||
if (imageRegion.Contains(aRegion)) {
|
||||
// adjust for tile offset
|
||||
aRegion.MoveBy(-xPos, -yPos);
|
||||
// forward the actual call
|
||||
nsRefPtr<gfxASurface> surface = mImages[i]->BeginUpdate(aRegion);
|
||||
// caller expects container space
|
||||
aRegion.MoveBy(xPos, yPos);
|
||||
// Correct the device offset
|
||||
gfxPoint offset = surface->GetDeviceOffset();
|
||||
surface->SetDeviceOffset(gfxPoint(offset.x - xPos,
|
||||
offset.y - yPos));
|
||||
// we don't have a temp surface
|
||||
mUpdateSurface = nullptr;
|
||||
// remember which image to EndUpdate
|
||||
mCurrentImage = i;
|
||||
return surface.get();
|
||||
}
|
||||
}
|
||||
|
||||
// Get the real updated region, taking into account the capabilities of
|
||||
// each TextureImage tile
|
||||
GetUpdateRegion(aRegion);
|
||||
mUpdateRegion = aRegion;
|
||||
bounds = aRegion.GetBounds();
|
||||
|
||||
// update covers multiple Images - create a temp surface to paint in
|
||||
gfxASurface::gfxImageFormat format =
|
||||
(GetContentType() == gfxASurface::CONTENT_COLOR) ?
|
||||
gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32;
|
||||
mUpdateSurface = gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenSurface(gfxIntSize(bounds.width, bounds.height), gfxASurface::ContentFromFormat(format));
|
||||
mUpdateSurface->SetDeviceOffset(gfxPoint(-bounds.x, -bounds.y));
|
||||
|
||||
return mUpdateSurface;
|
||||
}
|
||||
|
||||
void
|
||||
TiledTextureImage::EndUpdate()
|
||||
{
|
||||
NS_ASSERTION(mInUpdate, "EndUpdate not in update");
|
||||
if (!mUpdateSurface) { // update was to a single TextureImage
|
||||
mImages[mCurrentImage]->EndUpdate();
|
||||
mInUpdate = false;
|
||||
mTextureState = Valid;
|
||||
mShaderType = mImages[mCurrentImage]->GetShaderProgramType();
|
||||
return;
|
||||
}
|
||||
|
||||
// upload tiles from temp surface
|
||||
for (unsigned i = 0; i < mImages.Length(); i++) {
|
||||
int xPos = (i % mColumns) * mTileSize;
|
||||
int yPos = (i / mColumns) * mTileSize;
|
||||
nsIntRect imageRect = nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize());
|
||||
|
||||
nsIntRegion subregion;
|
||||
subregion.And(mUpdateRegion, imageRect);
|
||||
if (subregion.IsEmpty())
|
||||
continue;
|
||||
subregion.MoveBy(-xPos, -yPos); // Tile-local space
|
||||
// copy tile from temp surface
|
||||
gfxASurface* surf = mImages[i]->BeginUpdate(subregion);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
|
||||
gfxUtils::ClipToRegion(ctx, subregion);
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetSource(mUpdateSurface, gfxPoint(-xPos, -yPos));
|
||||
ctx->Paint();
|
||||
mImages[i]->EndUpdate();
|
||||
}
|
||||
|
||||
mUpdateSurface = nullptr;
|
||||
mInUpdate = false;
|
||||
mShaderType = mImages[0]->GetShaderProgramType();
|
||||
mTextureState = Valid;
|
||||
}
|
||||
|
||||
void TiledTextureImage::BeginTileIteration()
|
||||
{
|
||||
mCurrentImage = 0;
|
||||
}
|
||||
|
||||
bool TiledTextureImage::NextTile()
|
||||
{
|
||||
bool continueIteration = true;
|
||||
|
||||
if (mIterationCallback)
|
||||
continueIteration = mIterationCallback(this, mCurrentImage,
|
||||
mIterationCallbackData);
|
||||
|
||||
if (mCurrentImage + 1 < mImages.Length()) {
|
||||
mCurrentImage++;
|
||||
return continueIteration;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TiledTextureImage::SetIterationCallback(TileIterationCallback aCallback,
|
||||
void* aCallbackData)
|
||||
{
|
||||
mIterationCallback = aCallback;
|
||||
mIterationCallbackData = aCallbackData;
|
||||
}
|
||||
|
||||
nsIntRect TiledTextureImage::GetTileRect()
|
||||
{
|
||||
nsIntRect rect = mImages[mCurrentImage]->GetTileRect();
|
||||
unsigned int xPos = (mCurrentImage % mColumns) * mTileSize;
|
||||
unsigned int yPos = (mCurrentImage / mColumns) * mTileSize;
|
||||
rect.MoveBy(xPos, yPos);
|
||||
return rect;
|
||||
}
|
||||
|
||||
nsIntRect TiledTextureImage::GetSrcTileRect()
|
||||
{
|
||||
nsIntRect rect = GetTileRect();
|
||||
unsigned int srcY = mFlags & NeedsYFlip
|
||||
? mSize.height - rect.height - rect.y
|
||||
: rect.y;
|
||||
return nsIntRect(rect.x, srcY, rect.width, rect.height);
|
||||
}
|
||||
|
||||
void
|
||||
TiledTextureImage::BindTexture(GLenum aTextureUnit)
|
||||
{
|
||||
mImages[mCurrentImage]->BindTexture(aTextureUnit);
|
||||
}
|
||||
|
||||
void
|
||||
TiledTextureImage::ApplyFilter()
|
||||
{
|
||||
mGL->ApplyFilterToBoundTexture(mFilter);
|
||||
}
|
||||
|
||||
/*
|
||||
* Resize, trying to reuse tiles. The reuse strategy is to decide on reuse per
|
||||
* column. A tile on a column is reused if it hasn't changed size, otherwise it
|
||||
* is discarded/replaced. Extra tiles on a column are pruned after iterating
|
||||
* each column, and extra rows are pruned after iteration over the entire image
|
||||
* finishes.
|
||||
*/
|
||||
void TiledTextureImage::Resize(const nsIntSize& aSize)
|
||||
{
|
||||
if (mSize == aSize && mTextureState != Created) {
|
||||
return;
|
||||
}
|
||||
|
||||
// calculate rows and columns, rounding up
|
||||
unsigned int columns = (aSize.width + mTileSize - 1) / mTileSize;
|
||||
unsigned int rows = (aSize.height + mTileSize - 1) / mTileSize;
|
||||
|
||||
// Iterate over old tile-store and insert/remove tiles as necessary
|
||||
int row;
|
||||
unsigned int i = 0;
|
||||
for (row = 0; row < (int)rows; row++) {
|
||||
// If we've gone beyond how many rows there were before, set mColumns to
|
||||
// zero so that we only create new tiles.
|
||||
if (row >= (int)mRows)
|
||||
mColumns = 0;
|
||||
|
||||
// Similarly, if we're on the last row of old tiles and the height has
|
||||
// changed, discard all tiles in that row.
|
||||
// This will cause the pruning of columns not to work, but we don't need
|
||||
// to worry about that, as no more tiles will be reused past this point
|
||||
// anyway.
|
||||
if ((row == (int)mRows - 1) && (aSize.height != mSize.height))
|
||||
mColumns = 0;
|
||||
|
||||
int col;
|
||||
for (col = 0; col < (int)columns; col++) {
|
||||
nsIntSize size( // use tilesize first, then the remainder
|
||||
(col+1) * mTileSize > (unsigned int)aSize.width ? aSize.width % mTileSize : mTileSize,
|
||||
(row+1) * mTileSize > (unsigned int)aSize.height ? aSize.height % mTileSize : mTileSize);
|
||||
|
||||
bool replace = false;
|
||||
|
||||
// Check if we can re-use old tiles.
|
||||
if (col < (int)mColumns) {
|
||||
// Reuse an existing tile. If the tile is an end-tile and the
|
||||
// width differs, replace it instead.
|
||||
if (mSize.width != aSize.width) {
|
||||
if (col == (int)mColumns - 1) {
|
||||
// Tile at the end of the old column, replace it with
|
||||
// a new one.
|
||||
replace = true;
|
||||
} else if (col == (int)columns - 1) {
|
||||
// Tile at the end of the new column, create a new one.
|
||||
} else {
|
||||
// Before the last column on both the old and new sizes,
|
||||
// reuse existing tile.
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Width hasn't changed, reuse existing tile.
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new tile.
|
||||
nsRefPtr<TextureImage> teximg =
|
||||
mGL->TileGenFunc(size, mContentType, mFlags);
|
||||
if (replace)
|
||||
mImages.ReplaceElementAt(i, teximg.forget());
|
||||
else
|
||||
mImages.InsertElementAt(i, teximg.forget());
|
||||
i++;
|
||||
}
|
||||
|
||||
// Prune any unused tiles on the end of the column.
|
||||
if (row < (int)mRows) {
|
||||
for (col = (int)mColumns - col; col > 0; col--) {
|
||||
mImages.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prune any unused tiles at the end of the store.
|
||||
unsigned int length = mImages.Length();
|
||||
for (; i < length; i++)
|
||||
mImages.RemoveElementAt(mImages.Length()-1);
|
||||
|
||||
// Reset tile-store properties.
|
||||
mRows = rows;
|
||||
mColumns = columns;
|
||||
mSize = aSize;
|
||||
mTextureState = Allocated;
|
||||
mCurrentImage = 0;
|
||||
}
|
||||
|
||||
uint32_t TiledTextureImage::GetTileCount()
|
||||
{
|
||||
return mImages.Length();
|
||||
}
|
||||
|
||||
GLContext::GLFormats
|
||||
GLContext::ChooseGLFormats(ContextFormat& aCF, ColorByteOrder aByteOrder)
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
#include "nsRegion.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "GLContextTypes.h"
|
||||
#include "GLTextureImage.h"
|
||||
|
||||
typedef char realGLboolean;
|
||||
|
||||
|
@ -57,6 +55,391 @@ class GLContext;
|
|||
|
||||
typedef uintptr_t SharedTextureHandle;
|
||||
|
||||
enum ShaderProgramType {
|
||||
RGBALayerProgramType,
|
||||
RGBALayerExternalProgramType,
|
||||
BGRALayerProgramType,
|
||||
RGBXLayerProgramType,
|
||||
BGRXLayerProgramType,
|
||||
RGBARectLayerProgramType,
|
||||
RGBAExternalLayerProgramType,
|
||||
ColorLayerProgramType,
|
||||
YCbCrLayerProgramType,
|
||||
ComponentAlphaPass1ProgramType,
|
||||
ComponentAlphaPass2ProgramType,
|
||||
Copy2DProgramType,
|
||||
Copy2DRectProgramType,
|
||||
NumProgramTypes
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A TextureImage encapsulates a surface that can be drawn to by a
|
||||
* Thebes gfxContext and (hopefully efficiently!) synchronized to a
|
||||
* texture in the server. TextureImages are associated with one and
|
||||
* only one GLContext.
|
||||
*
|
||||
* Implementation note: TextureImages attempt to unify two categories
|
||||
* of backends
|
||||
*
|
||||
* (1) proxy to server-side object that can be bound to a texture;
|
||||
* e.g. Pixmap on X11.
|
||||
*
|
||||
* (2) efficient manager of texture memory; e.g. by having clients draw
|
||||
* into a scratch buffer which is then uploaded with
|
||||
* glTexSubImage2D().
|
||||
*/
|
||||
class TextureImage
|
||||
{
|
||||
NS_INLINE_DECL_REFCOUNTING(TextureImage)
|
||||
public:
|
||||
enum TextureState
|
||||
{
|
||||
Created, // Texture created, but has not had glTexImage called to initialize it.
|
||||
Allocated, // Texture memory exists, but contents are invalid.
|
||||
Valid // Texture fully ready to use.
|
||||
};
|
||||
|
||||
enum Flags {
|
||||
NoFlags = 0x0,
|
||||
UseNearestFilter = 0x1,
|
||||
NeedsYFlip = 0x2,
|
||||
ForceSingleTile = 0x4
|
||||
};
|
||||
|
||||
enum TextureShareType {
|
||||
ThreadShared = 0x0,
|
||||
ProcessShared = 0x1
|
||||
};
|
||||
|
||||
typedef gfxASurface::gfxContentType ContentType;
|
||||
|
||||
virtual ~TextureImage() {}
|
||||
|
||||
/**
|
||||
* Returns a gfxASurface for updating |aRegion| of the client's
|
||||
* image if successul, NULL if not. |aRegion|'s bounds must fit
|
||||
* within Size(); its coordinate space (if any) is ignored. If
|
||||
* the update begins successfully, the returned gfxASurface is
|
||||
* owned by this. Otherwise, NULL is returned.
|
||||
*
|
||||
* |aRegion| is an inout param: the returned region is what the
|
||||
* client must repaint. Category (1) regions above can
|
||||
* efficiently handle repaints to "scattered" regions, while (2)
|
||||
* can only efficiently handle repaints to rects.
|
||||
*
|
||||
* Painting the returned surface outside of |aRegion| results
|
||||
* in undefined behavior.
|
||||
*
|
||||
* BeginUpdate() calls cannot be "nested", and each successful
|
||||
* BeginUpdate() must be followed by exactly one EndUpdate() (see
|
||||
* below). Failure to do so can leave this in a possibly
|
||||
* inconsistent state. Unsuccessful BeginUpdate()s must not be
|
||||
* followed by EndUpdate().
|
||||
*/
|
||||
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion) = 0;
|
||||
/**
|
||||
* Retrieves the region that will require updating, given a
|
||||
* region that needs to be updated. This can be used for
|
||||
* making decisions about updating before calling BeginUpdate().
|
||||
*
|
||||
* |aRegion| is an inout param.
|
||||
*/
|
||||
virtual void GetUpdateRegion(nsIntRegion& aForRegion) {
|
||||
}
|
||||
/**
|
||||
* Finish the active update and synchronize with the server, if
|
||||
* necessary.
|
||||
*
|
||||
* BeginUpdate() must have been called exactly once before
|
||||
* EndUpdate().
|
||||
*/
|
||||
virtual void EndUpdate() = 0;
|
||||
|
||||
/**
|
||||
* The Image may contain several textures for different regions (tiles).
|
||||
* These functions iterate over each sub texture image tile.
|
||||
*/
|
||||
virtual void BeginTileIteration() {
|
||||
}
|
||||
|
||||
virtual bool NextTile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Function prototype for a tile iteration callback. Returning false will
|
||||
// cause iteration to be interrupted (i.e. the corresponding NextTile call
|
||||
// will return false).
|
||||
typedef bool (* TileIterationCallback)(TextureImage* aImage,
|
||||
int aTileNumber,
|
||||
void* aCallbackData);
|
||||
|
||||
// Sets a callback to be called every time NextTile is called.
|
||||
virtual void SetIterationCallback(TileIterationCallback aCallback,
|
||||
void* aCallbackData) {
|
||||
}
|
||||
|
||||
virtual nsIntRect GetTileRect() {
|
||||
return nsIntRect(nsIntPoint(0,0), mSize);
|
||||
}
|
||||
|
||||
virtual GLuint GetTextureID() = 0;
|
||||
|
||||
virtual uint32_t GetTileCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this TextureImage's size, and ensure a texture has been
|
||||
* allocated. Must not be called between BeginUpdate and EndUpdate.
|
||||
* After a resize, the contents are undefined.
|
||||
*
|
||||
* If this isn't implemented by a subclass, it will just perform
|
||||
* a dummy BeginUpdate/EndUpdate pair.
|
||||
*/
|
||||
virtual void Resize(const nsIntSize& aSize) {
|
||||
mSize = aSize;
|
||||
nsIntRegion r(nsIntRect(0, 0, aSize.width, aSize.height));
|
||||
BeginUpdate(r);
|
||||
EndUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark this texture as having valid contents. Call this after modifying
|
||||
* the texture contents externally.
|
||||
*/
|
||||
virtual void MarkValid() {}
|
||||
|
||||
/**
|
||||
* aSurf - the source surface to update from
|
||||
* aRegion - the region in this image to update
|
||||
* aFrom - offset in the source to update from
|
||||
*/
|
||||
virtual bool DirectUpdate(gfxASurface *aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0)) = 0;
|
||||
|
||||
virtual void BindTexture(GLenum aTextureUnit) = 0;
|
||||
virtual void ReleaseTexture() {}
|
||||
|
||||
void BindTextureAndApplyFilter(GLenum aTextureUnit) {
|
||||
BindTexture(aTextureUnit);
|
||||
ApplyFilter();
|
||||
}
|
||||
|
||||
class ScopedBindTexture
|
||||
{
|
||||
public:
|
||||
ScopedBindTexture(TextureImage *aTexture, GLenum aTextureUnit) :
|
||||
mTexture(aTexture)
|
||||
{
|
||||
if (mTexture) {
|
||||
mTexture->BindTexture(aTextureUnit);
|
||||
}
|
||||
}
|
||||
|
||||
~ScopedBindTexture()
|
||||
{
|
||||
if (mTexture) {
|
||||
mTexture->ReleaseTexture();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
TextureImage *mTexture;
|
||||
};
|
||||
|
||||
class ScopedBindTextureAndApplyFilter
|
||||
: public ScopedBindTexture
|
||||
{
|
||||
public:
|
||||
ScopedBindTextureAndApplyFilter(TextureImage *aTexture, GLenum aTextureUnit) :
|
||||
ScopedBindTexture(aTexture, aTextureUnit)
|
||||
{
|
||||
if (mTexture) {
|
||||
mTexture->ApplyFilter();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the shader program type that should be used to render
|
||||
* this texture. Only valid after a matching BeginUpdate/EndUpdate
|
||||
* pair have been called.
|
||||
*/
|
||||
virtual ShaderProgramType GetShaderProgramType()
|
||||
{
|
||||
return mShaderType;
|
||||
}
|
||||
|
||||
/** Can be called safely at any time. */
|
||||
|
||||
/**
|
||||
* If this TextureImage has a permanent gfxASurface backing,
|
||||
* return it. Otherwise return NULL.
|
||||
*/
|
||||
virtual already_AddRefed<gfxASurface> GetBackingSurface()
|
||||
{ return NULL; }
|
||||
|
||||
const nsIntSize& GetSize() const { return mSize; }
|
||||
ContentType GetContentType() const { return mContentType; }
|
||||
virtual bool InUpdate() const = 0;
|
||||
GLenum GetWrapMode() const { return mWrapMode; }
|
||||
|
||||
void SetFilter(gfxPattern::GraphicsFilter aFilter) { mFilter = aFilter; }
|
||||
|
||||
/**
|
||||
* Applies this TextureImage's filter, assuming that its texture is
|
||||
* the currently bound texture.
|
||||
*/
|
||||
virtual void ApplyFilter() = 0;
|
||||
|
||||
protected:
|
||||
friend class GLContext;
|
||||
|
||||
/**
|
||||
* After the ctor, the TextureImage is invalid. Implementations
|
||||
* must allocate resources successfully before returning the new
|
||||
* TextureImage from GLContext::CreateTextureImage(). That is,
|
||||
* clients must not be given partially-constructed TextureImages.
|
||||
*/
|
||||
TextureImage(const nsIntSize& aSize,
|
||||
GLenum aWrapMode, ContentType aContentType,
|
||||
Flags aFlags = NoFlags)
|
||||
: mSize(aSize)
|
||||
, mWrapMode(aWrapMode)
|
||||
, mContentType(aContentType)
|
||||
, mFilter(gfxPattern::FILTER_GOOD)
|
||||
, mFlags(aFlags)
|
||||
{}
|
||||
|
||||
virtual nsIntRect GetSrcTileRect() {
|
||||
return nsIntRect(nsIntPoint(0,0), mSize);
|
||||
}
|
||||
|
||||
nsIntSize mSize;
|
||||
GLenum mWrapMode;
|
||||
ContentType mContentType;
|
||||
ShaderProgramType mShaderType;
|
||||
gfxPattern::GraphicsFilter mFilter;
|
||||
Flags mFlags;
|
||||
};
|
||||
|
||||
/**
|
||||
* BasicTextureImage is the baseline TextureImage implementation ---
|
||||
* it updates its texture by allocating a scratch buffer for the
|
||||
* client to draw into, then using glTexSubImage2D() to upload the new
|
||||
* pixels. Platforms must provide the code to create a new surface
|
||||
* into which the updated pixels will be drawn, and the code to
|
||||
* convert the update surface's pixels into an image on which we can
|
||||
* glTexSubImage2D().
|
||||
*/
|
||||
class BasicTextureImage
|
||||
: public TextureImage
|
||||
{
|
||||
public:
|
||||
typedef gfxASurface::gfxImageFormat ImageFormat;
|
||||
virtual ~BasicTextureImage();
|
||||
|
||||
BasicTextureImage(GLuint aTexture,
|
||||
const nsIntSize& aSize,
|
||||
GLenum aWrapMode,
|
||||
ContentType aContentType,
|
||||
GLContext* aContext,
|
||||
TextureImage::Flags aFlags = TextureImage::NoFlags)
|
||||
: TextureImage(aSize, aWrapMode, aContentType, aFlags)
|
||||
, mTexture(aTexture)
|
||||
, mTextureState(Created)
|
||||
, mGLContext(aContext)
|
||||
, mUpdateOffset(0, 0)
|
||||
{}
|
||||
|
||||
virtual void BindTexture(GLenum aTextureUnit);
|
||||
|
||||
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
|
||||
virtual void GetUpdateRegion(nsIntRegion& aForRegion);
|
||||
virtual void EndUpdate();
|
||||
virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0));
|
||||
virtual GLuint GetTextureID() { return mTexture; }
|
||||
// Returns a surface to draw into
|
||||
virtual already_AddRefed<gfxASurface>
|
||||
GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt);
|
||||
|
||||
virtual void MarkValid() { mTextureState = Valid; }
|
||||
|
||||
// Call when drawing into the update surface is complete.
|
||||
// Returns true if textures should be upload with a relative
|
||||
// offset - See UploadSurfaceToTexture.
|
||||
virtual bool FinishedSurfaceUpdate();
|
||||
|
||||
// Call after surface data has been uploaded to a texture.
|
||||
virtual void FinishedSurfaceUpload();
|
||||
|
||||
virtual bool InUpdate() const { return !!mUpdateSurface; }
|
||||
|
||||
virtual void Resize(const nsIntSize& aSize);
|
||||
|
||||
virtual void ApplyFilter();
|
||||
protected:
|
||||
|
||||
GLuint mTexture;
|
||||
TextureState mTextureState;
|
||||
GLContext* mGLContext;
|
||||
nsRefPtr<gfxASurface> mUpdateSurface;
|
||||
nsIntRegion mUpdateRegion;
|
||||
|
||||
// The offset into the update surface at which the update rect is located.
|
||||
nsIntPoint mUpdateOffset;
|
||||
};
|
||||
|
||||
/**
|
||||
* A container class that complements many sub TextureImages into a big TextureImage.
|
||||
* Aims to behave just like the real thing.
|
||||
*/
|
||||
|
||||
class TiledTextureImage
|
||||
: public TextureImage
|
||||
{
|
||||
public:
|
||||
TiledTextureImage(GLContext* aGL, nsIntSize aSize,
|
||||
TextureImage::ContentType, TextureImage::Flags aFlags = TextureImage::NoFlags);
|
||||
~TiledTextureImage();
|
||||
void DumpDiv();
|
||||
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
|
||||
virtual void GetUpdateRegion(nsIntRegion& aForRegion);
|
||||
virtual void EndUpdate();
|
||||
virtual void Resize(const nsIntSize& aSize);
|
||||
virtual uint32_t GetTileCount();
|
||||
virtual void BeginTileIteration();
|
||||
virtual bool NextTile();
|
||||
virtual void SetIterationCallback(TileIterationCallback aCallback,
|
||||
void* aCallbackData);
|
||||
virtual nsIntRect GetTileRect();
|
||||
virtual GLuint GetTextureID() {
|
||||
return mImages[mCurrentImage]->GetTextureID();
|
||||
}
|
||||
virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0));
|
||||
virtual bool InUpdate() const { return mInUpdate; }
|
||||
virtual void BindTexture(GLenum);
|
||||
virtual void ApplyFilter();
|
||||
|
||||
protected:
|
||||
virtual nsIntRect GetSrcTileRect();
|
||||
|
||||
unsigned int mCurrentImage;
|
||||
TileIterationCallback mIterationCallback;
|
||||
void* mIterationCallbackData;
|
||||
nsTArray< nsRefPtr<TextureImage> > mImages;
|
||||
bool mInUpdate;
|
||||
nsIntSize mSize;
|
||||
unsigned int mTileSize;
|
||||
unsigned int mRows, mColumns;
|
||||
GLContext* mGL;
|
||||
// A temporary surface to faciliate cross-tile updates.
|
||||
nsRefPtr<gfxASurface> mUpdateSurface;
|
||||
// The region of update requested
|
||||
nsIntRegion mUpdateRegion;
|
||||
TextureState mTextureState;
|
||||
};
|
||||
|
||||
struct THEBES_API ContextFormat
|
||||
{
|
||||
static const ContextFormat BasicRGBA32Format;
|
||||
|
@ -546,12 +929,6 @@ public:
|
|||
return IsExtensionSupported(EXT_framebuffer_blit) || IsExtensionSupported(ANGLE_framebuffer_blit);
|
||||
}
|
||||
|
||||
|
||||
enum SharedTextureShareType {
|
||||
SameProcess = 0,
|
||||
CrossProcess
|
||||
};
|
||||
|
||||
enum SharedTextureBufferType {
|
||||
TextureID
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
@ -562,26 +939,23 @@ public:
|
|||
/**
|
||||
* Create new shared GLContext content handle, must be released by ReleaseSharedHandle.
|
||||
*/
|
||||
virtual SharedTextureHandle CreateSharedHandle(SharedTextureShareType shareType)
|
||||
{ return 0; }
|
||||
virtual SharedTextureHandle CreateSharedHandle(TextureImage::TextureShareType aType) { return 0; }
|
||||
/*
|
||||
* Create a new shared GLContext content handle, using the passed buffer as a source.
|
||||
* Must be released by ReleaseSharedHandle. UpdateSharedHandle will have no effect
|
||||
* on handles created with this method, as the caller owns the source (the passed buffer)
|
||||
* and is responsible for updating it accordingly.
|
||||
*/
|
||||
virtual SharedTextureHandle CreateSharedHandle(SharedTextureShareType shareType,
|
||||
void* buffer,
|
||||
SharedTextureBufferType bufferType)
|
||||
{ return 0; }
|
||||
virtual SharedTextureHandle CreateSharedHandle(TextureImage::TextureShareType aType,
|
||||
void* aBuffer,
|
||||
SharedTextureBufferType aBufferType) { return 0; }
|
||||
/**
|
||||
* Publish GLContext content to intermediate buffer attached to shared handle.
|
||||
* Shared handle content is ready to be used after call returns, and no need extra Flush/Finish are required.
|
||||
* GLContext must be current before this call
|
||||
*/
|
||||
virtual void UpdateSharedHandle(SharedTextureShareType shareType,
|
||||
SharedTextureHandle sharedHandle)
|
||||
{ }
|
||||
virtual void UpdateSharedHandle(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle) { }
|
||||
/**
|
||||
* - It is better to call ReleaseSharedHandle before original GLContext destroyed,
|
||||
* otherwise warning will be thrown on attempt to destroy Texture associated with SharedHandle, depends on backend implementation.
|
||||
|
@ -595,9 +969,8 @@ public:
|
|||
* SharedHandle (currently EGLImage) does not require GLContext because it is EGL call, and can be destroyed
|
||||
* at any time, unless EGLImage have siblings (which are not expected with current API).
|
||||
*/
|
||||
virtual void ReleaseSharedHandle(SharedTextureShareType shareType,
|
||||
SharedTextureHandle sharedHandle)
|
||||
{ }
|
||||
virtual void ReleaseSharedHandle(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle) { }
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
@ -610,24 +983,21 @@ public:
|
|||
* Returns information necessary for rendering a shared handle.
|
||||
* These values change depending on what sharing mechanism is in use
|
||||
*/
|
||||
virtual bool GetSharedHandleDetails(SharedTextureShareType shareType,
|
||||
SharedTextureHandle sharedHandle,
|
||||
SharedHandleDetails& details)
|
||||
{ return false; }
|
||||
virtual bool GetSharedHandleDetails(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle,
|
||||
SharedHandleDetails& aDetails) { return false; }
|
||||
/**
|
||||
* Attach Shared GL Handle to GL_TEXTURE_2D target
|
||||
* GLContext must be current before this call
|
||||
*/
|
||||
virtual bool AttachSharedHandle(SharedTextureShareType shareType,
|
||||
SharedTextureHandle sharedHandle)
|
||||
{ return false; }
|
||||
virtual bool AttachSharedHandle(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle) { return false; }
|
||||
|
||||
/**
|
||||
* Detach Shared GL Handle from GL_TEXTURE_2D target
|
||||
*/
|
||||
virtual void DetachSharedHandle(SharedTextureShareType shareType,
|
||||
SharedTextureHandle sharedHandle)
|
||||
{ }
|
||||
virtual void DetachSharedHandle(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle) { return; }
|
||||
|
||||
private:
|
||||
GLuint mUserBoundDrawFBO;
|
||||
|
@ -1566,7 +1936,12 @@ protected:
|
|||
GLenum aWrapMode,
|
||||
TextureImage::ContentType aContentType,
|
||||
GLContext* aContext,
|
||||
TextureImage::Flags aFlags = TextureImage::NoFlags);
|
||||
TextureImage::Flags aFlags = TextureImage::NoFlags)
|
||||
{
|
||||
nsRefPtr<BasicTextureImage> teximage(
|
||||
new BasicTextureImage(aTexture, aSize, aWrapMode, aContentType, aContext, aFlags));
|
||||
return teximage.forget();
|
||||
}
|
||||
|
||||
bool IsOffscreenSizeAllowed(const gfxIntSize& aSize) const {
|
||||
int32_t biggerDimension = NS_MAX(aSize.width, aSize.height);
|
||||
|
|
|
@ -646,19 +646,19 @@ public:
|
|||
return sEGLLibrary.HasKHRLockSurface();
|
||||
}
|
||||
|
||||
virtual SharedTextureHandle CreateSharedHandle(SharedTextureShareType shareType);
|
||||
virtual SharedTextureHandle CreateSharedHandle(SharedTextureShareType shareType,
|
||||
void* buffer,
|
||||
SharedTextureBufferType bufferType);
|
||||
virtual void UpdateSharedHandle(SharedTextureShareType shareType,
|
||||
SharedTextureHandle sharedHandle);
|
||||
virtual void ReleaseSharedHandle(SharedTextureShareType shareType,
|
||||
SharedTextureHandle sharedHandle);
|
||||
virtual bool GetSharedHandleDetails(SharedTextureShareType shareType,
|
||||
SharedTextureHandle sharedHandle,
|
||||
SharedHandleDetails& details);
|
||||
virtual bool AttachSharedHandle(SharedTextureShareType shareType,
|
||||
SharedTextureHandle sharedHandle);
|
||||
virtual SharedTextureHandle CreateSharedHandle(TextureImage::TextureShareType aType);
|
||||
virtual SharedTextureHandle CreateSharedHandle(TextureImage::TextureShareType aType,
|
||||
void* aBuffer,
|
||||
SharedTextureBufferType aBufferType);
|
||||
virtual void UpdateSharedHandle(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle);
|
||||
virtual void ReleaseSharedHandle(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle);
|
||||
virtual bool GetSharedHandleDetails(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle,
|
||||
SharedHandleDetails& aDetails);
|
||||
virtual bool AttachSharedHandle(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle);
|
||||
protected:
|
||||
friend class GLContextProviderEGL;
|
||||
|
||||
|
@ -854,15 +854,15 @@ private:
|
|||
};
|
||||
|
||||
void
|
||||
GLContextEGL::UpdateSharedHandle(SharedTextureShareType shareType,
|
||||
SharedTextureHandle sharedHandle)
|
||||
GLContextEGL::UpdateSharedHandle(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle)
|
||||
{
|
||||
if (shareType != SameProcess) {
|
||||
if (aType != TextureImage::ThreadShared) {
|
||||
NS_ERROR("Implementation not available for this sharing type");
|
||||
return;
|
||||
}
|
||||
|
||||
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(sharedHandle);
|
||||
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(aSharedHandle);
|
||||
|
||||
NS_ASSERTION(wrapper->Type() == SharedHandleType::Image, "Expected EGLImage shared handle");
|
||||
NS_ASSERTION(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
|
||||
|
@ -895,9 +895,9 @@ GLContextEGL::UpdateSharedHandle(SharedTextureShareType shareType,
|
|||
}
|
||||
|
||||
SharedTextureHandle
|
||||
GLContextEGL::CreateSharedHandle(SharedTextureShareType shareType)
|
||||
GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType)
|
||||
{
|
||||
if (shareType != SameProcess)
|
||||
if (aType != TextureImage::ThreadShared)
|
||||
return 0;
|
||||
|
||||
if (!mShareWithEGLImage)
|
||||
|
@ -914,7 +914,7 @@ GLContextEGL::CreateSharedHandle(SharedTextureShareType shareType)
|
|||
|
||||
if (!ok) {
|
||||
NS_ERROR("EGLImage creation for EGLTextureWrapper failed");
|
||||
ReleaseSharedHandle(shareType, (SharedTextureHandle)tex);
|
||||
ReleaseSharedHandle(aType, (SharedTextureHandle)tex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -923,16 +923,16 @@ GLContextEGL::CreateSharedHandle(SharedTextureShareType shareType)
|
|||
}
|
||||
|
||||
SharedTextureHandle
|
||||
GLContextEGL::CreateSharedHandle(SharedTextureShareType shareType,
|
||||
void* buffer,
|
||||
SharedTextureBufferType bufferType)
|
||||
GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType,
|
||||
void* aBuffer,
|
||||
SharedTextureBufferType aBufferType)
|
||||
{
|
||||
// Both EGLImage and SurfaceTexture only support ThreadShared currently, but
|
||||
// it's possible to make SurfaceTexture work across processes. We should do that.
|
||||
if (shareType != SameProcess)
|
||||
if (aType != TextureImage::ThreadShared)
|
||||
return 0;
|
||||
|
||||
switch (bufferType) {
|
||||
switch (aBufferType) {
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
case SharedTextureBufferType::SurfaceTexture:
|
||||
if (!IsExtensionSupported(GLContext::OES_EGL_image_external)) {
|
||||
|
@ -940,13 +940,13 @@ GLContextEGL::CreateSharedHandle(SharedTextureShareType shareType,
|
|||
return 0;
|
||||
}
|
||||
|
||||
return (SharedTextureHandle) new SurfaceTextureWrapper(reinterpret_cast<nsSurfaceTexture*>(buffer));
|
||||
return (SharedTextureHandle) new SurfaceTextureWrapper(reinterpret_cast<nsSurfaceTexture*>(aBuffer));
|
||||
#endif
|
||||
case SharedTextureBufferType::TextureID: {
|
||||
if (!mShareWithEGLImage)
|
||||
return 0;
|
||||
|
||||
GLuint texture = (uintptr_t)buffer;
|
||||
GLuint texture = (uintptr_t)aBuffer;
|
||||
EGLTextureWrapper* tex = new EGLTextureWrapper();
|
||||
if (!tex->CreateEGLImage(this, texture)) {
|
||||
NS_ERROR("EGLImage creation for EGLTextureWrapper failed");
|
||||
|
@ -962,15 +962,15 @@ GLContextEGL::CreateSharedHandle(SharedTextureShareType shareType,
|
|||
}
|
||||
}
|
||||
|
||||
void GLContextEGL::ReleaseSharedHandle(SharedTextureShareType shareType,
|
||||
SharedTextureHandle sharedHandle)
|
||||
void GLContextEGL::ReleaseSharedHandle(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle)
|
||||
{
|
||||
if (shareType != SameProcess) {
|
||||
if (aType != TextureImage::ThreadShared) {
|
||||
NS_ERROR("Implementation not available for this sharing type");
|
||||
return;
|
||||
}
|
||||
|
||||
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(sharedHandle);
|
||||
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(aSharedHandle);
|
||||
|
||||
switch (wrapper->Type()) {
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
@ -982,25 +982,24 @@ void GLContextEGL::ReleaseSharedHandle(SharedTextureShareType shareType,
|
|||
case SharedHandleType::Image: {
|
||||
NS_ASSERTION(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
|
||||
|
||||
EGLTextureWrapper* wrap = (EGLTextureWrapper*)sharedHandle;
|
||||
EGLTextureWrapper* wrap = (EGLTextureWrapper*)aSharedHandle;
|
||||
delete wrap;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
NS_ERROR("Unknown shared handle type");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool GLContextEGL::GetSharedHandleDetails(SharedTextureShareType shareType,
|
||||
SharedTextureHandle sharedHandle,
|
||||
SharedHandleDetails& details)
|
||||
bool GLContextEGL::GetSharedHandleDetails(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle,
|
||||
SharedHandleDetails& aDetails)
|
||||
{
|
||||
if (shareType != SameProcess)
|
||||
if (aType != TextureImage::ThreadShared)
|
||||
return false;
|
||||
|
||||
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(sharedHandle);
|
||||
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(aSharedHandle);
|
||||
|
||||
switch (wrapper->Type()) {
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
@ -1015,8 +1014,8 @@ bool GLContextEGL::GetSharedHandleDetails(SharedTextureShareType shareType,
|
|||
#endif
|
||||
|
||||
case SharedHandleType::Image:
|
||||
details.mTarget = LOCAL_GL_TEXTURE_2D;
|
||||
details.mProgramType = RGBALayerProgramType;
|
||||
aDetails.mTarget = LOCAL_GL_TEXTURE_2D;
|
||||
aDetails.mProgramType = RGBALayerProgramType;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1027,13 +1026,13 @@ bool GLContextEGL::GetSharedHandleDetails(SharedTextureShareType shareType,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GLContextEGL::AttachSharedHandle(SharedTextureShareType shareType,
|
||||
SharedTextureHandle sharedHandle)
|
||||
bool GLContextEGL::AttachSharedHandle(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle)
|
||||
{
|
||||
if (shareType != SameProcess)
|
||||
if (aType != TextureImage::ThreadShared)
|
||||
return false;
|
||||
|
||||
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(sharedHandle);
|
||||
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(aSharedHandle);
|
||||
|
||||
switch (wrapper->Type()) {
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
@ -1058,7 +1057,7 @@ bool GLContextEGL::AttachSharedHandle(SharedTextureShareType shareType,
|
|||
case SharedHandleType::Image: {
|
||||
NS_ASSERTION(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
|
||||
|
||||
EGLTextureWrapper* wrap = (EGLTextureWrapper*)sharedHandle;
|
||||
EGLTextureWrapper* wrap = (EGLTextureWrapper*)aSharedHandle;
|
||||
wrap->WaitSync();
|
||||
fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, wrap->GetEGLImage());
|
||||
break;
|
||||
|
@ -1072,7 +1071,6 @@ bool GLContextEGL::AttachSharedHandle(SharedTextureShareType shareType,
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
GLContextEGL::BindTex2DOffscreen(GLContext *aOffscreen)
|
||||
{
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* GLContextStuff.h
|
||||
*
|
||||
* Created on: Nov 13, 2012
|
||||
* Author: jgilbert
|
||||
*/
|
||||
|
||||
#ifndef GLCONTEXTSTUFF_H_
|
||||
#define GLCONTEXTSTUFF_H_
|
||||
|
||||
/**
|
||||
* We don't include GLDefs.h here since we don't want to drag in all defines
|
||||
* in for all our users.
|
||||
*/
|
||||
typedef unsigned int GLenum;
|
||||
typedef unsigned int GLbitfield;
|
||||
typedef unsigned int GLuint;
|
||||
typedef int GLint;
|
||||
typedef int GLsizei;
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
enum ShaderProgramType {
|
||||
RGBALayerProgramType,
|
||||
RGBALayerExternalProgramType,
|
||||
BGRALayerProgramType,
|
||||
RGBXLayerProgramType,
|
||||
BGRXLayerProgramType,
|
||||
RGBARectLayerProgramType,
|
||||
RGBAExternalLayerProgramType,
|
||||
ColorLayerProgramType,
|
||||
YCbCrLayerProgramType,
|
||||
ComponentAlphaPass1ProgramType,
|
||||
ComponentAlphaPass2ProgramType,
|
||||
Copy2DProgramType,
|
||||
Copy2DRectProgramType,
|
||||
NumProgramTypes
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* GLCONTEXTSTUFF_H_ */
|
|
@ -1,573 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "GLTextureImage.h"
|
||||
#include "GLContext.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxUtils.h"
|
||||
|
||||
using namespace mozilla::gl;
|
||||
|
||||
already_AddRefed<TextureImage>
|
||||
TextureImage::Create(GLContext* gl,
|
||||
const nsIntSize& size,
|
||||
TextureImage::ContentType contentType,
|
||||
GLenum wrapMode,
|
||||
TextureImage::Flags flags)
|
||||
{
|
||||
return gl->CreateTextureImage(size, contentType, wrapMode, flags);
|
||||
}
|
||||
|
||||
BasicTextureImage::~BasicTextureImage()
|
||||
{
|
||||
GLContext *ctx = mGLContext;
|
||||
if (ctx->IsDestroyed() || !ctx->IsOwningThreadCurrent()) {
|
||||
ctx = ctx->GetSharedContext();
|
||||
}
|
||||
|
||||
// If we have a context, then we need to delete the texture;
|
||||
// if we don't have a context (either real or shared),
|
||||
// then they went away when the contex was deleted, because it
|
||||
// was the only one that had access to it.
|
||||
if (ctx && !ctx->IsDestroyed()) {
|
||||
mGLContext->MakeCurrent();
|
||||
mGLContext->fDeleteTextures(1, &mTexture);
|
||||
}
|
||||
}
|
||||
|
||||
gfxASurface*
|
||||
BasicTextureImage::BeginUpdate(nsIntRegion& aRegion)
|
||||
{
|
||||
NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
|
||||
|
||||
// determine the region the client will need to repaint
|
||||
if (mGLContext->CanUploadSubTextures()) {
|
||||
GetUpdateRegion(aRegion);
|
||||
} else {
|
||||
aRegion = nsIntRect(nsIntPoint(0, 0), mSize);
|
||||
}
|
||||
|
||||
mUpdateRegion = aRegion;
|
||||
|
||||
nsIntRect rgnSize = mUpdateRegion.GetBounds();
|
||||
if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(rgnSize)) {
|
||||
NS_ERROR("update outside of image");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ImageFormat format =
|
||||
(GetContentType() == gfxASurface::CONTENT_COLOR) ?
|
||||
gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32;
|
||||
mUpdateSurface =
|
||||
GetSurfaceForUpdate(gfxIntSize(rgnSize.width, rgnSize.height), format);
|
||||
|
||||
if (!mUpdateSurface || mUpdateSurface->CairoStatus()) {
|
||||
mUpdateSurface = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mUpdateSurface->SetDeviceOffset(gfxPoint(-rgnSize.x, -rgnSize.y));
|
||||
|
||||
return mUpdateSurface;
|
||||
}
|
||||
|
||||
void
|
||||
BasicTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
|
||||
{
|
||||
// if the texture hasn't been initialized yet, or something important
|
||||
// changed, we need to recreate our backing surface and force the
|
||||
// client to paint everything
|
||||
if (mTextureState != Valid)
|
||||
aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
|
||||
}
|
||||
|
||||
void
|
||||
BasicTextureImage::EndUpdate()
|
||||
{
|
||||
NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
|
||||
|
||||
// FIXME: this is the slow boat. Make me fast (with GLXPixmap?).
|
||||
|
||||
// Undo the device offset that BeginUpdate set; doesn't much matter for us here,
|
||||
// but important if we ever do anything directly with the surface.
|
||||
mUpdateSurface->SetDeviceOffset(gfxPoint(0, 0));
|
||||
|
||||
bool relative = FinishedSurfaceUpdate();
|
||||
|
||||
mShaderType =
|
||||
mGLContext->UploadSurfaceToTexture(mUpdateSurface,
|
||||
mUpdateRegion,
|
||||
mTexture,
|
||||
mTextureState == Created,
|
||||
mUpdateOffset,
|
||||
relative);
|
||||
FinishedSurfaceUpload();
|
||||
|
||||
mUpdateSurface = nullptr;
|
||||
mTextureState = Valid;
|
||||
}
|
||||
|
||||
void
|
||||
BasicTextureImage::BindTexture(GLenum aTextureUnit)
|
||||
{
|
||||
mGLContext->fActiveTexture(aTextureUnit);
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
}
|
||||
|
||||
void
|
||||
BasicTextureImage::ApplyFilter()
|
||||
{
|
||||
mGLContext->ApplyFilterToBoundTexture(mFilter);
|
||||
}
|
||||
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
BasicTextureImage::GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt)
|
||||
{
|
||||
return gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenSurface(aSize, gfxASurface::ContentFromFormat(aFmt));
|
||||
}
|
||||
|
||||
bool
|
||||
BasicTextureImage::FinishedSurfaceUpdate()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
BasicTextureImage::FinishedSurfaceUpload()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
BasicTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
|
||||
{
|
||||
nsIntRect bounds = aRegion.GetBounds();
|
||||
nsIntRegion region;
|
||||
if (mTextureState != Valid) {
|
||||
bounds = nsIntRect(0, 0, mSize.width, mSize.height);
|
||||
region = nsIntRegion(bounds);
|
||||
} else {
|
||||
region = aRegion;
|
||||
}
|
||||
|
||||
mShaderType =
|
||||
mGLContext->UploadSurfaceToTexture(aSurf,
|
||||
region,
|
||||
mTexture,
|
||||
mTextureState == Created,
|
||||
bounds.TopLeft() + aFrom,
|
||||
false);
|
||||
mTextureState = Valid;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
BasicTextureImage::Resize(const nsIntSize& aSize)
|
||||
{
|
||||
NS_ASSERTION(!mUpdateSurface, "Resize() while in update?");
|
||||
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
NULL);
|
||||
|
||||
mTextureState = Allocated;
|
||||
mSize = aSize;
|
||||
}
|
||||
|
||||
TiledTextureImage::TiledTextureImage(GLContext* aGL,
|
||||
nsIntSize aSize,
|
||||
TextureImage::ContentType aContentType,
|
||||
TextureImage::Flags aFlags)
|
||||
: TextureImage(aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, aFlags)
|
||||
, mCurrentImage(0)
|
||||
, mIterationCallback(nullptr)
|
||||
, mInUpdate(false)
|
||||
, mRows(0)
|
||||
, mColumns(0)
|
||||
, mGL(aGL)
|
||||
, mTextureState(Created)
|
||||
{
|
||||
mTileSize = (!(aFlags & TextureImage::ForceSingleTile) && mGL->WantsSmallTiles())
|
||||
? 256 : mGL->GetMaxTextureSize();
|
||||
if (aSize != nsIntSize(0,0)) {
|
||||
Resize(aSize);
|
||||
}
|
||||
}
|
||||
|
||||
TiledTextureImage::~TiledTextureImage()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
TiledTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
|
||||
{
|
||||
nsIntRegion region;
|
||||
|
||||
if (mTextureState != Valid) {
|
||||
nsIntRect bounds = nsIntRect(0, 0, mSize.width, mSize.height);
|
||||
region = nsIntRegion(bounds);
|
||||
} else {
|
||||
region = aRegion;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
int oldCurrentImage = mCurrentImage;
|
||||
BeginTileIteration();
|
||||
do {
|
||||
nsIntRect tileRect = GetSrcTileRect();
|
||||
int xPos = tileRect.x;
|
||||
int yPos = tileRect.y;
|
||||
|
||||
nsIntRegion tileRegion;
|
||||
tileRegion.And(region, tileRect); // intersect with tile
|
||||
|
||||
if (tileRegion.IsEmpty())
|
||||
continue;
|
||||
|
||||
if (mGL->CanUploadSubTextures()) {
|
||||
tileRegion.MoveBy(-xPos, -yPos); // translate into tile local space
|
||||
} else {
|
||||
// If sub-textures are unsupported, expand to tile boundaries
|
||||
tileRect.x = tileRect.y = 0;
|
||||
tileRegion = nsIntRegion(tileRect);
|
||||
}
|
||||
|
||||
result &= mImages[mCurrentImage]->
|
||||
DirectUpdate(aSurf, tileRegion, aFrom + nsIntPoint(xPos, yPos));
|
||||
|
||||
if (mCurrentImage == mImages.Length() - 1) {
|
||||
// We know we're done, but we still need to ensure that the callback
|
||||
// gets called (e.g. to update the uploaded region).
|
||||
NextTile();
|
||||
break;
|
||||
}
|
||||
// Override a callback cancelling iteration if the texture wasn't valid.
|
||||
// We need to force the update in that situation, or we may end up
|
||||
// showing invalid/out-of-date texture data.
|
||||
} while (NextTile() || (mTextureState != Valid));
|
||||
mCurrentImage = oldCurrentImage;
|
||||
|
||||
mShaderType = mImages[0]->GetShaderProgramType();
|
||||
mTextureState = Valid;
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
TiledTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
|
||||
{
|
||||
if (mTextureState != Valid) {
|
||||
// if the texture hasn't been initialized yet, or something important
|
||||
// changed, we need to recreate our backing surface and force the
|
||||
// client to paint everything
|
||||
aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRegion newRegion;
|
||||
|
||||
// We need to query each texture with the region it will be drawing and
|
||||
// set aForRegion to be the combination of all of these regions
|
||||
for (unsigned i = 0; i < mImages.Length(); i++) {
|
||||
int xPos = (i % mColumns) * mTileSize;
|
||||
int yPos = (i / mColumns) * mTileSize;
|
||||
nsIntRect imageRect = nsIntRect(nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize()));
|
||||
|
||||
if (aForRegion.Intersects(imageRect)) {
|
||||
// Make a copy of the region
|
||||
nsIntRegion subRegion;
|
||||
subRegion.And(aForRegion, imageRect);
|
||||
// Translate it into tile-space
|
||||
subRegion.MoveBy(-xPos, -yPos);
|
||||
// Query region
|
||||
mImages[i]->GetUpdateRegion(subRegion);
|
||||
// Translate back
|
||||
subRegion.MoveBy(xPos, yPos);
|
||||
// Add to the accumulated region
|
||||
newRegion.Or(newRegion, subRegion);
|
||||
}
|
||||
}
|
||||
|
||||
aForRegion = newRegion;
|
||||
}
|
||||
|
||||
gfxASurface*
|
||||
TiledTextureImage::BeginUpdate(nsIntRegion& aRegion)
|
||||
{
|
||||
NS_ASSERTION(!mInUpdate, "nested update");
|
||||
mInUpdate = true;
|
||||
|
||||
// Note, we don't call GetUpdateRegion here as if the updated region is
|
||||
// fully contained in a single tile, we get to avoid iterating through
|
||||
// the tiles again (and a little copying).
|
||||
if (mTextureState != Valid)
|
||||
{
|
||||
// if the texture hasn't been initialized yet, or something important
|
||||
// changed, we need to recreate our backing surface and force the
|
||||
// client to paint everything
|
||||
aRegion = nsIntRect(nsIntPoint(0, 0), mSize);
|
||||
}
|
||||
|
||||
nsIntRect bounds = aRegion.GetBounds();
|
||||
|
||||
for (unsigned i = 0; i < mImages.Length(); i++) {
|
||||
int xPos = (i % mColumns) * mTileSize;
|
||||
int yPos = (i / mColumns) * mTileSize;
|
||||
nsIntRegion imageRegion = nsIntRegion(nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize()));
|
||||
|
||||
// a single Image can handle this update request
|
||||
if (imageRegion.Contains(aRegion)) {
|
||||
// adjust for tile offset
|
||||
aRegion.MoveBy(-xPos, -yPos);
|
||||
// forward the actual call
|
||||
nsRefPtr<gfxASurface> surface = mImages[i]->BeginUpdate(aRegion);
|
||||
// caller expects container space
|
||||
aRegion.MoveBy(xPos, yPos);
|
||||
// Correct the device offset
|
||||
gfxPoint offset = surface->GetDeviceOffset();
|
||||
surface->SetDeviceOffset(gfxPoint(offset.x - xPos,
|
||||
offset.y - yPos));
|
||||
// we don't have a temp surface
|
||||
mUpdateSurface = nullptr;
|
||||
// remember which image to EndUpdate
|
||||
mCurrentImage = i;
|
||||
return surface.get();
|
||||
}
|
||||
}
|
||||
|
||||
// Get the real updated region, taking into account the capabilities of
|
||||
// each TextureImage tile
|
||||
GetUpdateRegion(aRegion);
|
||||
mUpdateRegion = aRegion;
|
||||
bounds = aRegion.GetBounds();
|
||||
|
||||
// update covers multiple Images - create a temp surface to paint in
|
||||
gfxASurface::gfxImageFormat format =
|
||||
(GetContentType() == gfxASurface::CONTENT_COLOR) ?
|
||||
gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32;
|
||||
mUpdateSurface = gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenSurface(gfxIntSize(bounds.width, bounds.height), gfxASurface::ContentFromFormat(format));
|
||||
mUpdateSurface->SetDeviceOffset(gfxPoint(-bounds.x, -bounds.y));
|
||||
|
||||
return mUpdateSurface;
|
||||
}
|
||||
|
||||
void
|
||||
TiledTextureImage::EndUpdate()
|
||||
{
|
||||
NS_ASSERTION(mInUpdate, "EndUpdate not in update");
|
||||
if (!mUpdateSurface) { // update was to a single TextureImage
|
||||
mImages[mCurrentImage]->EndUpdate();
|
||||
mInUpdate = false;
|
||||
mTextureState = Valid;
|
||||
mShaderType = mImages[mCurrentImage]->GetShaderProgramType();
|
||||
return;
|
||||
}
|
||||
|
||||
// upload tiles from temp surface
|
||||
for (unsigned i = 0; i < mImages.Length(); i++) {
|
||||
int xPos = (i % mColumns) * mTileSize;
|
||||
int yPos = (i / mColumns) * mTileSize;
|
||||
nsIntRect imageRect = nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize());
|
||||
|
||||
nsIntRegion subregion;
|
||||
subregion.And(mUpdateRegion, imageRect);
|
||||
if (subregion.IsEmpty())
|
||||
continue;
|
||||
subregion.MoveBy(-xPos, -yPos); // Tile-local space
|
||||
// copy tile from temp surface
|
||||
gfxASurface* surf = mImages[i]->BeginUpdate(subregion);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
|
||||
gfxUtils::ClipToRegion(ctx, subregion);
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetSource(mUpdateSurface, gfxPoint(-xPos, -yPos));
|
||||
ctx->Paint();
|
||||
mImages[i]->EndUpdate();
|
||||
}
|
||||
|
||||
mUpdateSurface = nullptr;
|
||||
mInUpdate = false;
|
||||
mShaderType = mImages[0]->GetShaderProgramType();
|
||||
mTextureState = Valid;
|
||||
}
|
||||
|
||||
void TiledTextureImage::BeginTileIteration()
|
||||
{
|
||||
mCurrentImage = 0;
|
||||
}
|
||||
|
||||
bool TiledTextureImage::NextTile()
|
||||
{
|
||||
bool continueIteration = true;
|
||||
|
||||
if (mIterationCallback)
|
||||
continueIteration = mIterationCallback(this, mCurrentImage,
|
||||
mIterationCallbackData);
|
||||
|
||||
if (mCurrentImage + 1 < mImages.Length()) {
|
||||
mCurrentImage++;
|
||||
return continueIteration;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TiledTextureImage::SetIterationCallback(TileIterationCallback aCallback,
|
||||
void* aCallbackData)
|
||||
{
|
||||
mIterationCallback = aCallback;
|
||||
mIterationCallbackData = aCallbackData;
|
||||
}
|
||||
|
||||
nsIntRect TiledTextureImage::GetTileRect()
|
||||
{
|
||||
nsIntRect rect = mImages[mCurrentImage]->GetTileRect();
|
||||
unsigned int xPos = (mCurrentImage % mColumns) * mTileSize;
|
||||
unsigned int yPos = (mCurrentImage / mColumns) * mTileSize;
|
||||
rect.MoveBy(xPos, yPos);
|
||||
return rect;
|
||||
}
|
||||
|
||||
nsIntRect TiledTextureImage::GetSrcTileRect()
|
||||
{
|
||||
nsIntRect rect = GetTileRect();
|
||||
unsigned int srcY = mFlags & NeedsYFlip
|
||||
? mSize.height - rect.height - rect.y
|
||||
: rect.y;
|
||||
return nsIntRect(rect.x, srcY, rect.width, rect.height);
|
||||
}
|
||||
|
||||
void
|
||||
TiledTextureImage::BindTexture(GLenum aTextureUnit)
|
||||
{
|
||||
mImages[mCurrentImage]->BindTexture(aTextureUnit);
|
||||
}
|
||||
|
||||
void
|
||||
TiledTextureImage::ApplyFilter()
|
||||
{
|
||||
mGL->ApplyFilterToBoundTexture(mFilter);
|
||||
}
|
||||
|
||||
/*
|
||||
* Resize, trying to reuse tiles. The reuse strategy is to decide on reuse per
|
||||
* column. A tile on a column is reused if it hasn't changed size, otherwise it
|
||||
* is discarded/replaced. Extra tiles on a column are pruned after iterating
|
||||
* each column, and extra rows are pruned after iteration over the entire image
|
||||
* finishes.
|
||||
*/
|
||||
void TiledTextureImage::Resize(const nsIntSize& aSize)
|
||||
{
|
||||
if (mSize == aSize && mTextureState != Created) {
|
||||
return;
|
||||
}
|
||||
|
||||
// calculate rows and columns, rounding up
|
||||
unsigned int columns = (aSize.width + mTileSize - 1) / mTileSize;
|
||||
unsigned int rows = (aSize.height + mTileSize - 1) / mTileSize;
|
||||
|
||||
// Iterate over old tile-store and insert/remove tiles as necessary
|
||||
int row;
|
||||
unsigned int i = 0;
|
||||
for (row = 0; row < (int)rows; row++) {
|
||||
// If we've gone beyond how many rows there were before, set mColumns to
|
||||
// zero so that we only create new tiles.
|
||||
if (row >= (int)mRows)
|
||||
mColumns = 0;
|
||||
|
||||
// Similarly, if we're on the last row of old tiles and the height has
|
||||
// changed, discard all tiles in that row.
|
||||
// This will cause the pruning of columns not to work, but we don't need
|
||||
// to worry about that, as no more tiles will be reused past this point
|
||||
// anyway.
|
||||
if ((row == (int)mRows - 1) && (aSize.height != mSize.height))
|
||||
mColumns = 0;
|
||||
|
||||
int col;
|
||||
for (col = 0; col < (int)columns; col++) {
|
||||
nsIntSize size( // use tilesize first, then the remainder
|
||||
(col+1) * mTileSize > (unsigned int)aSize.width ? aSize.width % mTileSize : mTileSize,
|
||||
(row+1) * mTileSize > (unsigned int)aSize.height ? aSize.height % mTileSize : mTileSize);
|
||||
|
||||
bool replace = false;
|
||||
|
||||
// Check if we can re-use old tiles.
|
||||
if (col < (int)mColumns) {
|
||||
// Reuse an existing tile. If the tile is an end-tile and the
|
||||
// width differs, replace it instead.
|
||||
if (mSize.width != aSize.width) {
|
||||
if (col == (int)mColumns - 1) {
|
||||
// Tile at the end of the old column, replace it with
|
||||
// a new one.
|
||||
replace = true;
|
||||
} else if (col == (int)columns - 1) {
|
||||
// Tile at the end of the new column, create a new one.
|
||||
} else {
|
||||
// Before the last column on both the old and new sizes,
|
||||
// reuse existing tile.
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Width hasn't changed, reuse existing tile.
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new tile.
|
||||
nsRefPtr<TextureImage> teximg =
|
||||
mGL->TileGenFunc(size, mContentType, mFlags);
|
||||
if (replace)
|
||||
mImages.ReplaceElementAt(i, teximg.forget());
|
||||
else
|
||||
mImages.InsertElementAt(i, teximg.forget());
|
||||
i++;
|
||||
}
|
||||
|
||||
// Prune any unused tiles on the end of the column.
|
||||
if (row < (int)mRows) {
|
||||
for (col = (int)mColumns - col; col > 0; col--) {
|
||||
mImages.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prune any unused tiles at the end of the store.
|
||||
unsigned int length = mImages.Length();
|
||||
for (; i < length; i++)
|
||||
mImages.RemoveElementAt(mImages.Length()-1);
|
||||
|
||||
// Reset tile-store properties.
|
||||
mRows = rows;
|
||||
mColumns = columns;
|
||||
mSize = aSize;
|
||||
mTextureState = Allocated;
|
||||
mCurrentImage = 0;
|
||||
}
|
||||
|
||||
uint32_t TiledTextureImage::GetTileCount()
|
||||
{
|
||||
return mImages.Length();
|
||||
}
|
||||
|
||||
TextureImage::ScopedBindTexture::ScopedBindTexture(TextureImage* aTexture,
|
||||
GLenum aTextureUnit)
|
||||
: mTexture(aTexture)
|
||||
{
|
||||
if (mTexture) {
|
||||
MOZ_ASSERT(aTextureUnit >= LOCAL_GL_TEXTURE0);
|
||||
mTexture->BindTexture(aTextureUnit);
|
||||
}
|
||||
}
|
|
@ -1,385 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GLTEXTUREIMAGE_H_
|
||||
#define GLTEXTUREIMAGE_H_
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsRegion.h"
|
||||
#include "gfxASurface.h"
|
||||
#include "GLContextTypes.h"
|
||||
#include "gfxPattern.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
class GLContext;
|
||||
|
||||
/**
|
||||
* A TextureImage encapsulates a surface that can be drawn to by a
|
||||
* Thebes gfxContext and (hopefully efficiently!) synchronized to a
|
||||
* texture in the server. TextureImages are associated with one and
|
||||
* only one GLContext.
|
||||
*
|
||||
* Implementation note: TextureImages attempt to unify two categories
|
||||
* of backends
|
||||
*
|
||||
* (1) proxy to server-side object that can be bound to a texture;
|
||||
* e.g. Pixmap on X11.
|
||||
*
|
||||
* (2) efficient manager of texture memory; e.g. by having clients draw
|
||||
* into a scratch buffer which is then uploaded with
|
||||
* glTexSubImage2D().
|
||||
*/
|
||||
class TextureImage
|
||||
{
|
||||
NS_INLINE_DECL_REFCOUNTING(TextureImage)
|
||||
public:
|
||||
enum TextureState
|
||||
{
|
||||
Created, // Texture created, but has not had glTexImage called to initialize it.
|
||||
Allocated, // Texture memory exists, but contents are invalid.
|
||||
Valid // Texture fully ready to use.
|
||||
};
|
||||
|
||||
enum Flags {
|
||||
NoFlags = 0x0,
|
||||
UseNearestFilter = 0x1,
|
||||
NeedsYFlip = 0x2,
|
||||
ForceSingleTile = 0x4
|
||||
};
|
||||
|
||||
typedef gfxASurface::gfxContentType ContentType;
|
||||
|
||||
static already_AddRefed<TextureImage> Create(
|
||||
GLContext* gl,
|
||||
const nsIntSize& aSize,
|
||||
TextureImage::ContentType aContentType,
|
||||
GLenum aWrapMode,
|
||||
TextureImage::Flags aFlags = TextureImage::NoFlags);
|
||||
|
||||
virtual ~TextureImage() {}
|
||||
|
||||
/**
|
||||
* Returns a gfxASurface for updating |aRegion| of the client's
|
||||
* image if successul, NULL if not. |aRegion|'s bounds must fit
|
||||
* within Size(); its coordinate space (if any) is ignored. If
|
||||
* the update begins successfully, the returned gfxASurface is
|
||||
* owned by this. Otherwise, NULL is returned.
|
||||
*
|
||||
* |aRegion| is an inout param: the returned region is what the
|
||||
* client must repaint. Category (1) regions above can
|
||||
* efficiently handle repaints to "scattered" regions, while (2)
|
||||
* can only efficiently handle repaints to rects.
|
||||
*
|
||||
* Painting the returned surface outside of |aRegion| results
|
||||
* in undefined behavior.
|
||||
*
|
||||
* BeginUpdate() calls cannot be "nested", and each successful
|
||||
* BeginUpdate() must be followed by exactly one EndUpdate() (see
|
||||
* below). Failure to do so can leave this in a possibly
|
||||
* inconsistent state. Unsuccessful BeginUpdate()s must not be
|
||||
* followed by EndUpdate().
|
||||
*/
|
||||
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion) = 0;
|
||||
/**
|
||||
* Retrieves the region that will require updating, given a
|
||||
* region that needs to be updated. This can be used for
|
||||
* making decisions about updating before calling BeginUpdate().
|
||||
*
|
||||
* |aRegion| is an inout param.
|
||||
*/
|
||||
virtual void GetUpdateRegion(nsIntRegion& aForRegion) {
|
||||
}
|
||||
/**
|
||||
* Finish the active update and synchronize with the server, if
|
||||
* necessary.
|
||||
*
|
||||
* BeginUpdate() must have been called exactly once before
|
||||
* EndUpdate().
|
||||
*/
|
||||
virtual void EndUpdate() = 0;
|
||||
|
||||
/**
|
||||
* The Image may contain several textures for different regions (tiles).
|
||||
* These functions iterate over each sub texture image tile.
|
||||
*/
|
||||
virtual void BeginTileIteration() {
|
||||
}
|
||||
|
||||
virtual bool NextTile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Function prototype for a tile iteration callback. Returning false will
|
||||
// cause iteration to be interrupted (i.e. the corresponding NextTile call
|
||||
// will return false).
|
||||
typedef bool (* TileIterationCallback)(TextureImage* aImage,
|
||||
int aTileNumber,
|
||||
void* aCallbackData);
|
||||
|
||||
// Sets a callback to be called every time NextTile is called.
|
||||
virtual void SetIterationCallback(TileIterationCallback aCallback,
|
||||
void* aCallbackData) {
|
||||
}
|
||||
|
||||
virtual nsIntRect GetTileRect() {
|
||||
return nsIntRect(nsIntPoint(0,0), mSize);
|
||||
}
|
||||
|
||||
virtual GLuint GetTextureID() = 0;
|
||||
|
||||
virtual uint32_t GetTileCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this TextureImage's size, and ensure a texture has been
|
||||
* allocated. Must not be called between BeginUpdate and EndUpdate.
|
||||
* After a resize, the contents are undefined.
|
||||
*
|
||||
* If this isn't implemented by a subclass, it will just perform
|
||||
* a dummy BeginUpdate/EndUpdate pair.
|
||||
*/
|
||||
virtual void Resize(const nsIntSize& aSize) {
|
||||
mSize = aSize;
|
||||
nsIntRegion r(nsIntRect(0, 0, aSize.width, aSize.height));
|
||||
BeginUpdate(r);
|
||||
EndUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark this texture as having valid contents. Call this after modifying
|
||||
* the texture contents externally.
|
||||
*/
|
||||
virtual void MarkValid() {}
|
||||
|
||||
/**
|
||||
* aSurf - the source surface to update from
|
||||
* aRegion - the region in this image to update
|
||||
* aFrom - offset in the source to update from
|
||||
*/
|
||||
virtual bool DirectUpdate(gfxASurface *aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0)) = 0;
|
||||
|
||||
virtual void BindTexture(GLenum aTextureUnit) = 0;
|
||||
virtual void ReleaseTexture() {}
|
||||
|
||||
void BindTextureAndApplyFilter(GLenum aTextureUnit) {
|
||||
BindTexture(aTextureUnit);
|
||||
ApplyFilter();
|
||||
}
|
||||
|
||||
class ScopedBindTexture
|
||||
{
|
||||
public:
|
||||
ScopedBindTexture(TextureImage *aTexture, GLenum aTextureUnit);
|
||||
|
||||
~ScopedBindTexture()
|
||||
{
|
||||
if (mTexture) {
|
||||
mTexture->ReleaseTexture();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
TextureImage *mTexture;
|
||||
};
|
||||
|
||||
class ScopedBindTextureAndApplyFilter
|
||||
: public ScopedBindTexture
|
||||
{
|
||||
public:
|
||||
ScopedBindTextureAndApplyFilter(TextureImage *aTexture, GLenum aTextureUnit) :
|
||||
ScopedBindTexture(aTexture, aTextureUnit)
|
||||
{
|
||||
if (mTexture) {
|
||||
mTexture->ApplyFilter();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the shader program type that should be used to render
|
||||
* this texture. Only valid after a matching BeginUpdate/EndUpdate
|
||||
* pair have been called.
|
||||
*/
|
||||
virtual ShaderProgramType GetShaderProgramType()
|
||||
{
|
||||
return mShaderType;
|
||||
}
|
||||
|
||||
/** Can be called safely at any time. */
|
||||
|
||||
/**
|
||||
* If this TextureImage has a permanent gfxASurface backing,
|
||||
* return it. Otherwise return NULL.
|
||||
*/
|
||||
virtual already_AddRefed<gfxASurface> GetBackingSurface()
|
||||
{ return NULL; }
|
||||
|
||||
const nsIntSize& GetSize() const { return mSize; }
|
||||
ContentType GetContentType() const { return mContentType; }
|
||||
virtual bool InUpdate() const = 0;
|
||||
GLenum GetWrapMode() const { return mWrapMode; }
|
||||
|
||||
void SetFilter(gfxPattern::GraphicsFilter aFilter) { mFilter = aFilter; }
|
||||
|
||||
/**
|
||||
* Applies this TextureImage's filter, assuming that its texture is
|
||||
* the currently bound texture.
|
||||
*/
|
||||
virtual void ApplyFilter() = 0;
|
||||
|
||||
protected:
|
||||
friend class GLContext;
|
||||
|
||||
/**
|
||||
* After the ctor, the TextureImage is invalid. Implementations
|
||||
* must allocate resources successfully before returning the new
|
||||
* TextureImage from GLContext::CreateTextureImage(). That is,
|
||||
* clients must not be given partially-constructed TextureImages.
|
||||
*/
|
||||
TextureImage(const nsIntSize& aSize,
|
||||
GLenum aWrapMode, ContentType aContentType,
|
||||
Flags aFlags = NoFlags)
|
||||
: mSize(aSize)
|
||||
, mWrapMode(aWrapMode)
|
||||
, mContentType(aContentType)
|
||||
, mFilter(gfxPattern::FILTER_GOOD)
|
||||
, mFlags(aFlags)
|
||||
{}
|
||||
|
||||
virtual nsIntRect GetSrcTileRect() {
|
||||
return nsIntRect(nsIntPoint(0,0), mSize);
|
||||
}
|
||||
|
||||
nsIntSize mSize;
|
||||
GLenum mWrapMode;
|
||||
ContentType mContentType;
|
||||
ShaderProgramType mShaderType;
|
||||
gfxPattern::GraphicsFilter mFilter;
|
||||
Flags mFlags;
|
||||
};
|
||||
|
||||
/**
|
||||
* BasicTextureImage is the baseline TextureImage implementation ---
|
||||
* it updates its texture by allocating a scratch buffer for the
|
||||
* client to draw into, then using glTexSubImage2D() to upload the new
|
||||
* pixels. Platforms must provide the code to create a new surface
|
||||
* into which the updated pixels will be drawn, and the code to
|
||||
* convert the update surface's pixels into an image on which we can
|
||||
* glTexSubImage2D().
|
||||
*/
|
||||
class BasicTextureImage
|
||||
: public TextureImage
|
||||
{
|
||||
public:
|
||||
typedef gfxASurface::gfxImageFormat ImageFormat;
|
||||
virtual ~BasicTextureImage();
|
||||
|
||||
BasicTextureImage(GLuint aTexture,
|
||||
const nsIntSize& aSize,
|
||||
GLenum aWrapMode,
|
||||
ContentType aContentType,
|
||||
GLContext* aContext,
|
||||
TextureImage::Flags aFlags = TextureImage::NoFlags)
|
||||
: TextureImage(aSize, aWrapMode, aContentType, aFlags)
|
||||
, mTexture(aTexture)
|
||||
, mTextureState(Created)
|
||||
, mGLContext(aContext)
|
||||
, mUpdateOffset(0, 0)
|
||||
{}
|
||||
|
||||
virtual void BindTexture(GLenum aTextureUnit);
|
||||
|
||||
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
|
||||
virtual void GetUpdateRegion(nsIntRegion& aForRegion);
|
||||
virtual void EndUpdate();
|
||||
virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0));
|
||||
virtual GLuint GetTextureID() { return mTexture; }
|
||||
// Returns a surface to draw into
|
||||
virtual already_AddRefed<gfxASurface>
|
||||
GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt);
|
||||
|
||||
virtual void MarkValid() { mTextureState = Valid; }
|
||||
|
||||
// Call when drawing into the update surface is complete.
|
||||
// Returns true if textures should be upload with a relative
|
||||
// offset - See UploadSurfaceToTexture.
|
||||
virtual bool FinishedSurfaceUpdate();
|
||||
|
||||
// Call after surface data has been uploaded to a texture.
|
||||
virtual void FinishedSurfaceUpload();
|
||||
|
||||
virtual bool InUpdate() const { return !!mUpdateSurface; }
|
||||
|
||||
virtual void Resize(const nsIntSize& aSize);
|
||||
|
||||
virtual void ApplyFilter();
|
||||
protected:
|
||||
|
||||
GLuint mTexture;
|
||||
TextureState mTextureState;
|
||||
GLContext* mGLContext;
|
||||
nsRefPtr<gfxASurface> mUpdateSurface;
|
||||
nsIntRegion mUpdateRegion;
|
||||
|
||||
// The offset into the update surface at which the update rect is located.
|
||||
nsIntPoint mUpdateOffset;
|
||||
};
|
||||
|
||||
/**
|
||||
* A container class that complements many sub TextureImages into a big TextureImage.
|
||||
* Aims to behave just like the real thing.
|
||||
*/
|
||||
|
||||
class TiledTextureImage
|
||||
: public TextureImage
|
||||
{
|
||||
public:
|
||||
TiledTextureImage(GLContext* aGL, nsIntSize aSize,
|
||||
TextureImage::ContentType, TextureImage::Flags aFlags = TextureImage::NoFlags);
|
||||
~TiledTextureImage();
|
||||
void DumpDiv();
|
||||
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
|
||||
virtual void GetUpdateRegion(nsIntRegion& aForRegion);
|
||||
virtual void EndUpdate();
|
||||
virtual void Resize(const nsIntSize& aSize);
|
||||
virtual uint32_t GetTileCount();
|
||||
virtual void BeginTileIteration();
|
||||
virtual bool NextTile();
|
||||
virtual void SetIterationCallback(TileIterationCallback aCallback,
|
||||
void* aCallbackData);
|
||||
virtual nsIntRect GetTileRect();
|
||||
virtual GLuint GetTextureID() {
|
||||
return mImages[mCurrentImage]->GetTextureID();
|
||||
}
|
||||
virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0));
|
||||
virtual bool InUpdate() const { return mInUpdate; }
|
||||
virtual void BindTexture(GLenum);
|
||||
virtual void ApplyFilter();
|
||||
|
||||
protected:
|
||||
virtual nsIntRect GetSrcTileRect();
|
||||
|
||||
unsigned int mCurrentImage;
|
||||
TileIterationCallback mIterationCallback;
|
||||
void* mIterationCallbackData;
|
||||
nsTArray< nsRefPtr<TextureImage> > mImages;
|
||||
bool mInUpdate;
|
||||
nsIntSize mSize;
|
||||
unsigned int mTileSize;
|
||||
unsigned int mRows, mColumns;
|
||||
GLContext* mGL;
|
||||
// A temporary surface to faciliate cross-tile updates.
|
||||
nsRefPtr<gfxASurface> mUpdateSurface;
|
||||
// The region of update requested
|
||||
nsIntRegion mUpdateRegion;
|
||||
TextureState mTextureState;
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* GLTEXTUREIMAGE_H_ */
|
|
@ -18,13 +18,11 @@ FAIL_ON_WARNINGS = 1
|
|||
EXPORTS = \
|
||||
GLDefs.h \
|
||||
GLContext.h \
|
||||
GLContextTypes.h \
|
||||
GLContextSymbols.h \
|
||||
GLContextProvider.h \
|
||||
GLContextProviderImpl.h \
|
||||
GLLibraryLoader.h \
|
||||
ForceDiscreteGPUHelperCGL.h \
|
||||
GLTextureImage.h \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_X11
|
||||
|
@ -49,7 +47,6 @@ CPPSRCS = \
|
|||
GLContext.cpp \
|
||||
GLContextUtils.cpp \
|
||||
GLLibraryLoader.cpp \
|
||||
GLTextureImage.cpp \
|
||||
$(NULL)
|
||||
|
||||
GL_PROVIDER = Null
|
||||
|
|
|
@ -20,7 +20,7 @@ class THEBES_API SharedTextureImage : public Image {
|
|||
public:
|
||||
struct Data {
|
||||
gl::SharedTextureHandle mHandle;
|
||||
gl::GLContext::SharedTextureShareType mShareType;
|
||||
gl::TextureImage::TextureShareType mShareType;
|
||||
gfxIntSize mSize;
|
||||
bool mInverted;
|
||||
};
|
||||
|
@ -41,4 +41,4 @@ private:
|
|||
} // layers
|
||||
} // mozilla
|
||||
|
||||
#endif // GFX_SHAREDTEXTUREIMAGE_H
|
||||
#endif // GFX_SHAREDTEXTUREIMAGE_H
|
|
@ -387,25 +387,24 @@ BasicShadowableCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
|
|||
|
||||
if (mGLContext &&
|
||||
!mForceReadback &&
|
||||
BasicManager()->GetParentBackendType() == mozilla::layers::LAYERS_OPENGL)
|
||||
{
|
||||
GLContext::SharedTextureShareType shareType;
|
||||
BasicManager()->GetParentBackendType() == mozilla::layers::LAYERS_OPENGL) {
|
||||
TextureImage::TextureShareType flags;
|
||||
// if process type is default, then it is single-process (non-e10s)
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default)
|
||||
shareType = GLContext::SameProcess;
|
||||
flags = TextureImage::ThreadShared;
|
||||
else
|
||||
shareType = GLContext::CrossProcess;
|
||||
flags = TextureImage::ProcessShared;
|
||||
|
||||
SharedTextureHandle handle = GetSharedBackBufferHandle();
|
||||
if (!handle) {
|
||||
handle = mGLContext->CreateSharedHandle(shareType);
|
||||
handle = mGLContext->CreateSharedHandle(flags);
|
||||
if (handle) {
|
||||
mBackBuffer = SharedTextureDescriptor(shareType, handle, mBounds.Size(), false);
|
||||
mBackBuffer = SharedTextureDescriptor(flags, handle, mBounds.Size(), false);
|
||||
}
|
||||
}
|
||||
if (handle) {
|
||||
mGLContext->MakeCurrent();
|
||||
mGLContext->UpdateSharedHandle(shareType, handle);
|
||||
mGLContext->UpdateSharedHandle(flags, handle);
|
||||
// call Painted() to reset our dirty 'bit'
|
||||
Painted();
|
||||
FireDidTransactionCallback();
|
||||
|
|
|
@ -22,7 +22,7 @@ using mozilla::layers::SurfaceDescriptorX11;
|
|||
using mozilla::null_t;
|
||||
using mozilla::WindowsHandle;
|
||||
using mozilla::gl::SharedTextureHandle;
|
||||
using mozilla::gl::GLContext::SharedTextureShareType;
|
||||
using mozilla::gl::TextureImage::TextureShareType;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
@ -37,7 +37,7 @@ struct SurfaceDescriptorD3D10 {
|
|||
};
|
||||
|
||||
struct SharedTextureDescriptor {
|
||||
SharedTextureShareType shareType;
|
||||
TextureShareType shareType;
|
||||
SharedTextureHandle handle;
|
||||
nsIntSize size;
|
||||
bool inverted;
|
||||
|
|
|
@ -52,9 +52,9 @@ struct ParamTraits<mozilla::layers::SurfaceDescriptorX11> {
|
|||
#endif // !defined(MOZ_HAVE_XSURFACEDESCRIPTORX11)
|
||||
|
||||
template<>
|
||||
struct ParamTraits<mozilla::gl::GLContext::SharedTextureShareType>
|
||||
struct ParamTraits<mozilla::gl::TextureImage::TextureShareType>
|
||||
{
|
||||
typedef mozilla::gl::GLContext::SharedTextureShareType paramType;
|
||||
typedef mozilla::gl::TextureImage::TextureShareType paramType;
|
||||
|
||||
static void Write(Message* msg, const paramType& param)
|
||||
{
|
||||
|
|
|
@ -420,10 +420,7 @@ ShadowCanvasLayerOGL::Swap(const CanvasSurface& aNewFront,
|
|||
} else if (IsValidSharedTexDescriptor(aNewFront)) {
|
||||
MakeTextureIfNeeded(gl(), mTexture);
|
||||
if (!IsValidSharedTexDescriptor(mFrontBufferDescriptor)) {
|
||||
mFrontBufferDescriptor = SharedTextureDescriptor(GLContext::SameProcess,
|
||||
0,
|
||||
nsIntSize(0, 0),
|
||||
false);
|
||||
mFrontBufferDescriptor = SharedTextureDescriptor(TextureImage::ThreadShared, 0, nsIntSize(0, 0), false);
|
||||
}
|
||||
*aNewBack = mFrontBufferDescriptor;
|
||||
mFrontBufferDescriptor = aNewFront;
|
||||
|
|
|
@ -194,7 +194,7 @@ private:
|
|||
|
||||
// For SharedTextureHandle
|
||||
gl::SharedTextureHandle mSharedHandle;
|
||||
gl::GLContext::SharedTextureShareType mShareType;
|
||||
gl::TextureImage::TextureShareType mShareType;
|
||||
bool mInverted;
|
||||
GLuint mTexture;
|
||||
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "LayerManagerOGL.h"
|
||||
|
||||
#include "mozilla/layers/PLayers.h"
|
||||
|
||||
/* This must occur *after* layers/PLayers.h to avoid typedefs conflicts. */
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "Composer2D.h"
|
||||
#include "LayerManagerOGL.h"
|
||||
#include "ThebesLayerOGL.h"
|
||||
#include "ContainerLayerOGL.h"
|
||||
#include "ImageLayerOGL.h"
|
||||
|
@ -52,91 +52,6 @@ using namespace mozilla::gl;
|
|||
int ShaderProgramOGL::sCurrentProgramKey = 0;
|
||||
#endif
|
||||
|
||||
bool
|
||||
LayerManagerOGL::Initialize(bool force)
|
||||
{
|
||||
return Initialize(CreateContext(), force);
|
||||
}
|
||||
|
||||
int32_t
|
||||
LayerManagerOGL::GetMaxTextureSize() const
|
||||
{
|
||||
return mGLContext->GetMaxTextureSize();
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerOGL::MakeCurrent(bool aForce)
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return;
|
||||
}
|
||||
mGLContext->MakeCurrent(aForce);
|
||||
}
|
||||
|
||||
void*
|
||||
LayerManagerOGL::GetNSOpenGLContext() const
|
||||
{
|
||||
return gl()->GetNativeData(GLContext::NativeGLContext);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LayerManagerOGL::BindQuadVBO() {
|
||||
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO);
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerOGL::QuadVBOVerticesAttrib(GLuint aAttribIndex) {
|
||||
mGLContext->fVertexAttribPointer(aAttribIndex, 2,
|
||||
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
|
||||
(GLvoid*) QuadVBOVertexOffset());
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerOGL::QuadVBOTexCoordsAttrib(GLuint aAttribIndex) {
|
||||
mGLContext->fVertexAttribPointer(aAttribIndex, 2,
|
||||
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
|
||||
(GLvoid*) QuadVBOTexCoordOffset());
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerOGL::QuadVBOFlippedTexCoordsAttrib(GLuint aAttribIndex) {
|
||||
mGLContext->fVertexAttribPointer(aAttribIndex, 2,
|
||||
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
|
||||
(GLvoid*) QuadVBOFlippedTexCoordOffset());
|
||||
}
|
||||
|
||||
// Super common
|
||||
|
||||
void
|
||||
LayerManagerOGL::BindAndDrawQuad(GLuint aVertAttribIndex,
|
||||
GLuint aTexCoordAttribIndex,
|
||||
bool aFlipped)
|
||||
{
|
||||
BindQuadVBO();
|
||||
QuadVBOVerticesAttrib(aVertAttribIndex);
|
||||
|
||||
if (aTexCoordAttribIndex != GLuint(-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 != GLuint(-1)) {
|
||||
mGLContext->fDisableVertexAttribArray(aTexCoordAttribIndex);
|
||||
}
|
||||
}
|
||||
|
||||
static const double kFpsWindowMs = 250.0;
|
||||
static const size_t kNumFrameTimeStamps = 16;
|
||||
struct FPSCounter {
|
||||
|
|
|
@ -9,23 +9,31 @@
|
|||
#include "LayerManagerOGLProgram.h"
|
||||
|
||||
#include "mozilla/layers/ShadowLayers.h"
|
||||
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* We don't include GLDefs.h here since we don't want to drag in all defines
|
||||
* in for all our users.
|
||||
*/
|
||||
typedef unsigned int GLenum;
|
||||
typedef unsigned int GLbitfield;
|
||||
typedef unsigned int GLuint;
|
||||
typedef int GLint;
|
||||
typedef int GLsizei;
|
||||
|
||||
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
||||
|
||||
#include "gfxContext.h"
|
||||
#include "gfx3DMatrix.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "GLContextTypes.h"
|
||||
#include "GLContext.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
class GLContext;
|
||||
}
|
||||
namespace layers {
|
||||
|
||||
class Composer2D;
|
||||
|
@ -63,7 +71,9 @@ public:
|
|||
*
|
||||
* \return True is initialization was succesful, false when it was not.
|
||||
*/
|
||||
bool Initialize(bool force = false);
|
||||
bool Initialize(bool force = false) {
|
||||
return Initialize(CreateContext(), force);
|
||||
}
|
||||
|
||||
bool Initialize(nsRefPtr<GLContext> aContext, bool force = false);
|
||||
|
||||
|
@ -100,14 +110,18 @@ public:
|
|||
|
||||
virtual void SetRoot(Layer* aLayer) { mRoot = aLayer; }
|
||||
|
||||
virtual bool CanUseCanvasLayerForSize(const gfxIntSize &aSize) {
|
||||
if (!mGLContext)
|
||||
return false;
|
||||
int32_t maxSize = GetMaxTextureSize();
|
||||
return aSize <= gfxIntSize(maxSize, maxSize);
|
||||
virtual bool CanUseCanvasLayerForSize(const gfxIntSize &aSize)
|
||||
{
|
||||
if (!mGLContext)
|
||||
return false;
|
||||
int32_t maxSize = mGLContext->GetMaxTextureSize();
|
||||
return aSize <= gfxIntSize(maxSize, maxSize);
|
||||
}
|
||||
|
||||
virtual int32_t GetMaxTextureSize() const;
|
||||
virtual int32_t GetMaxTextureSize() const
|
||||
{
|
||||
return mGLContext->GetMaxTextureSize();
|
||||
}
|
||||
|
||||
virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
|
||||
|
||||
|
@ -137,7 +151,13 @@ public:
|
|||
/**
|
||||
* Helper methods.
|
||||
*/
|
||||
void MakeCurrent(bool aForce = false);
|
||||
void MakeCurrent(bool aForce = false) {
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return;
|
||||
}
|
||||
mGLContext->MakeCurrent(aForce);
|
||||
}
|
||||
|
||||
ShaderProgramOGL* GetBasicLayerProgram(bool aOpaque, bool aIsRGB,
|
||||
MaskType aMask = MaskNone)
|
||||
|
@ -183,9 +203,6 @@ public:
|
|||
|
||||
GLContext* gl() const { return mGLContext; }
|
||||
|
||||
// |NSOpenGLContext*|:
|
||||
void* GetNSOpenGLContext() const;
|
||||
|
||||
DrawThebesLayerCallback GetThebesLayerCallback() const
|
||||
{ return mThebesLayerCallback; }
|
||||
|
||||
|
@ -237,15 +254,56 @@ public:
|
|||
GLintptr QuadVBOTexCoordOffset() { return sizeof(float)*4*2; }
|
||||
GLintptr QuadVBOFlippedTexCoordOffset() { return sizeof(float)*8*2; }
|
||||
|
||||
void BindQuadVBO();
|
||||
void QuadVBOVerticesAttrib(GLuint aAttribIndex);
|
||||
void QuadVBOTexCoordsAttrib(GLuint aAttribIndex);
|
||||
void QuadVBOFlippedTexCoordsAttrib(GLuint aAttribIndex);
|
||||
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);
|
||||
bool aFlipped = false)
|
||||
{
|
||||
BindQuadVBO();
|
||||
QuadVBOVerticesAttrib(aVertAttribIndex);
|
||||
|
||||
if (aTexCoordAttribIndex != GLuint(-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 != GLuint(-1)) {
|
||||
mGLContext->fDisableVertexAttribArray(aTexCoordAttribIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void BindAndDrawQuad(ShaderProgramOGL *aProg,
|
||||
bool aFlipped = false)
|
||||
|
|
|
@ -3,16 +3,9 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "LayerManagerOGLProgram.h"
|
||||
|
||||
#ifdef GLCONTEXT_H_
|
||||
#error GLContext.h should not have been included here.
|
||||
#endif
|
||||
|
||||
#include "LayerManagerOGLShaders.h"
|
||||
#include "LayerManagerOGL.h"
|
||||
|
||||
#include "GLContext.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
|
@ -234,28 +227,6 @@ ProgramProfileOGL::GetProfileFor(gl::ShaderProgramType aType,
|
|||
const char* const ShaderProgramOGL::VertexCoordAttrib = "aVertexCoord";
|
||||
const char* const ShaderProgramOGL::TexCoordAttrib = "aTexCoord";
|
||||
|
||||
ShaderProgramOGL::ShaderProgramOGL(GLContext* aGL, const ProgramProfileOGL& aProfile)
|
||||
: mIsProjectionMatrixStale(false)
|
||||
, mGL(aGL)
|
||||
, mProgram(0)
|
||||
, mProfile(aProfile)
|
||||
, mProgramState(STATE_NEW)
|
||||
{}
|
||||
|
||||
ShaderProgramOGL::~ShaderProgramOGL()
|
||||
{
|
||||
if (mProgram <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContext> ctx = mGL->GetSharedContext();
|
||||
if (!ctx) {
|
||||
ctx = mGL;
|
||||
}
|
||||
ctx->MakeCurrent();
|
||||
ctx->fDeleteProgram(mProgram);
|
||||
}
|
||||
|
||||
bool
|
||||
ShaderProgramOGL::Initialize()
|
||||
{
|
||||
|
@ -423,87 +394,5 @@ ShaderProgramOGL::LoadMask(Layer* aMaskLayer)
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ShaderProgramOGL::Activate()
|
||||
{
|
||||
if (mProgramState == STATE_NEW) {
|
||||
if (!Initialize()) {
|
||||
NS_WARNING("Shader could not be initialised");
|
||||
return;
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(HasInitialized(), "Attempting to activate a program that's not in use!");
|
||||
mGL->fUseProgram(mProgram);
|
||||
#if CHECK_CURRENT_PROGRAM
|
||||
mGL->SetUserData(&sCurrentProgramKey, this);
|
||||
#endif
|
||||
// check and set the projection matrix
|
||||
if (mIsProjectionMatrixStale) {
|
||||
SetProjectionMatrix(mProjectionMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ShaderProgramOGL::SetUniform(GLint aLocation, float aFloatValue)
|
||||
{
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aLocation >= 0, "Invalid location");
|
||||
|
||||
mGL->fUniform1f(aLocation, aFloatValue);
|
||||
}
|
||||
|
||||
void
|
||||
ShaderProgramOGL::SetUniform(GLint aLocation, const gfxRGBA& aColor)
|
||||
{
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aLocation >= 0, "Invalid location");
|
||||
|
||||
mGL->fUniform4f(aLocation, float(aColor.r), float(aColor.g), float(aColor.b), float(aColor.a));
|
||||
}
|
||||
|
||||
void
|
||||
ShaderProgramOGL::SetUniform(GLint aLocation, int aLength, float *aFloatValues)
|
||||
{
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aLocation >= 0, "Invalid location");
|
||||
|
||||
if (aLength == 1) {
|
||||
mGL->fUniform1fv(aLocation, 1, aFloatValues);
|
||||
} else if (aLength == 2) {
|
||||
mGL->fUniform2fv(aLocation, 1, aFloatValues);
|
||||
} else if (aLength == 3) {
|
||||
mGL->fUniform3fv(aLocation, 1, aFloatValues);
|
||||
} else if (aLength == 4) {
|
||||
mGL->fUniform4fv(aLocation, 1, aFloatValues);
|
||||
} else {
|
||||
NS_NOTREACHED("Bogus aLength param");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ShaderProgramOGL::SetUniform(GLint aLocation, GLint aIntValue)
|
||||
{
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aLocation >= 0, "Invalid location");
|
||||
|
||||
mGL->fUniform1i(aLocation, aIntValue);
|
||||
}
|
||||
|
||||
void
|
||||
ShaderProgramOGL::SetMatrixUniform(GLint aLocation, const gfx3DMatrix& aMatrix)
|
||||
{
|
||||
SetMatrixUniform(aLocation, &aMatrix._11);
|
||||
}
|
||||
|
||||
void
|
||||
ShaderProgramOGL::SetMatrixUniform(GLint aLocation, const float *aFloatValues)
|
||||
{
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aLocation >= 0, "Invalid location");
|
||||
|
||||
mGL->fUniformMatrix4fv(aLocation, 1, false, aFloatValues);
|
||||
}
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
|
|
|
@ -10,16 +10,11 @@
|
|||
|
||||
#include "prenv.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "GLContextTypes.h"
|
||||
#include "GLContext.h"
|
||||
#include "gfx3DMatrix.h"
|
||||
#include "gfxColor.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
class GLContext;
|
||||
}
|
||||
namespace layers {
|
||||
|
||||
class Layer;
|
||||
|
@ -145,16 +140,45 @@ class ShaderProgramOGL
|
|||
public:
|
||||
typedef mozilla::gl::GLContext GLContext;
|
||||
|
||||
ShaderProgramOGL(GLContext* aGL, const ProgramProfileOGL& aProfile);
|
||||
ShaderProgramOGL(GLContext* aGL, const ProgramProfileOGL& aProfile) :
|
||||
mIsProjectionMatrixStale(false), mGL(aGL), mProgram(0),
|
||||
mProfile(aProfile), mProgramState(STATE_NEW) { }
|
||||
|
||||
~ShaderProgramOGL();
|
||||
~ShaderProgramOGL() {
|
||||
if (mProgram <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContext> ctx = mGL->GetSharedContext();
|
||||
if (!ctx) {
|
||||
ctx = mGL;
|
||||
}
|
||||
ctx->MakeCurrent();
|
||||
ctx->fDeleteProgram(mProgram);
|
||||
}
|
||||
|
||||
bool HasInitialized() {
|
||||
NS_ASSERTION(mProgramState != STATE_OK || mProgram > 0, "Inconsistent program state");
|
||||
return mProgramState == STATE_OK;
|
||||
}
|
||||
|
||||
void Activate();
|
||||
void Activate() {
|
||||
if (mProgramState == STATE_NEW) {
|
||||
if (!Initialize()) {
|
||||
NS_WARNING("Shader could not be initialised");
|
||||
return;
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(HasInitialized(), "Attempting to activate a program that's not in use!");
|
||||
mGL->fUseProgram(mProgram);
|
||||
#if CHECK_CURRENT_PROGRAM
|
||||
mGL->SetUserData(&sCurrentProgramKey, this);
|
||||
#endif
|
||||
// check and set the projection matrix
|
||||
if (mIsProjectionMatrixStale) {
|
||||
SetProjectionMatrix(mProjectionMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
bool Initialize();
|
||||
|
||||
|
@ -305,12 +329,54 @@ protected:
|
|||
static int sCurrentProgramKey;
|
||||
#endif
|
||||
|
||||
void SetUniform(GLint aLocation, float aFloatValue);
|
||||
void SetUniform(GLint aLocation, const gfxRGBA& aColor);
|
||||
void SetUniform(GLint aLocation, int aLength, float *aFloatValues);
|
||||
void SetUniform(GLint aLocation, GLint aIntValue);
|
||||
void SetMatrixUniform(GLint aLocation, const gfx3DMatrix& aMatrix);
|
||||
void SetMatrixUniform(GLint aLocation, const float *aFloatValues);
|
||||
void SetUniform(GLint aLocation, float aFloatValue) {
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aLocation >= 0, "Invalid location");
|
||||
|
||||
mGL->fUniform1f(aLocation, aFloatValue);
|
||||
}
|
||||
|
||||
void SetUniform(GLint aLocation, const gfxRGBA& aColor) {
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aLocation >= 0, "Invalid location");
|
||||
|
||||
mGL->fUniform4f(aLocation, float(aColor.r), float(aColor.g), float(aColor.b), float(aColor.a));
|
||||
}
|
||||
|
||||
void SetUniform(GLint aLocation, int aLength, float *aFloatValues) {
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aLocation >= 0, "Invalid location");
|
||||
|
||||
if (aLength == 1) {
|
||||
mGL->fUniform1fv(aLocation, 1, aFloatValues);
|
||||
} else if (aLength == 2) {
|
||||
mGL->fUniform2fv(aLocation, 1, aFloatValues);
|
||||
} else if (aLength == 3) {
|
||||
mGL->fUniform3fv(aLocation, 1, aFloatValues);
|
||||
} else if (aLength == 4) {
|
||||
mGL->fUniform4fv(aLocation, 1, aFloatValues);
|
||||
} else {
|
||||
NS_NOTREACHED("Bogus aLength param");
|
||||
}
|
||||
}
|
||||
|
||||
void SetUniform(GLint aLocation, GLint aIntValue) {
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aLocation >= 0, "Invalid location");
|
||||
|
||||
mGL->fUniform1i(aLocation, aIntValue);
|
||||
}
|
||||
|
||||
void SetMatrixUniform(GLint aLocation, const gfx3DMatrix& aMatrix) {
|
||||
SetMatrixUniform(aLocation, &aMatrix._11);
|
||||
}
|
||||
|
||||
void SetMatrixUniform(GLint aLocation, const float *aFloatValues) {
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aLocation >= 0, "Invalid location");
|
||||
|
||||
mGL->fUniformMatrix4fv(aLocation, 1, false, aFloatValues);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
#include "ReusableTileStoreOGL.h"
|
||||
|
||||
#include "GLContext.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
#include "nsRegion.h"
|
||||
#include "Layers.h"
|
||||
#include "LayerManagerOGL.h"
|
||||
#include "GLTextureImage.h"
|
||||
#include "GLContext.h"
|
||||
#include "mozilla/layers/CompositorCocoaWidgetHelper.h"
|
||||
#ifdef ACCESSIBILITY
|
||||
#include "nsAccessibilityService.h"
|
||||
|
@ -67,10 +67,6 @@
|
|||
|
||||
#include "nsIDOMWheelEvent.h"
|
||||
|
||||
#ifdef GLCONTEXT_H_
|
||||
#error GLContext.h should not have been included here.
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::gl;
|
||||
|
@ -1696,7 +1692,8 @@ nsChildView::CreateCompositor()
|
|||
LayerManagerOGL *manager =
|
||||
static_cast<LayerManagerOGL*>(compositor::GetLayerManager(mCompositorParent));
|
||||
|
||||
NSOpenGLContext *glContext = (NSOpenGLContext *)manager->GetNSOpenGLContext();
|
||||
NSOpenGLContext *glContext =
|
||||
(NSOpenGLContext *) manager->gl()->GetNativeData(GLContext::NativeGLContext);
|
||||
|
||||
[(ChildView *)mView setGLContext:glContext];
|
||||
[(ChildView *)mView setUsingOMTCompositor:true];
|
||||
|
@ -1759,11 +1756,10 @@ nsChildView::DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect)
|
|||
}
|
||||
|
||||
if (!mResizerImage) {
|
||||
mResizerImage = TextureImage::Create(manager->gl(),
|
||||
nsIntSize(15, 15),
|
||||
gfxASurface::CONTENT_COLOR_ALPHA,
|
||||
LOCAL_GL_CLAMP_TO_EDGE,
|
||||
TextureImage::UseNearestFilter);
|
||||
mResizerImage = manager->gl()->CreateTextureImage(nsIntSize(15, 15),
|
||||
gfxASurface::CONTENT_COLOR_ALPHA,
|
||||
LOCAL_GL_CLAMP_TO_EDGE,
|
||||
TextureImage::UseNearestFilter);
|
||||
|
||||
// Creation of texture images can fail.
|
||||
if (!mResizerImage)
|
||||
|
@ -2461,7 +2457,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||
|
||||
LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(layerManager);
|
||||
manager->SetClippingRegion(region);
|
||||
glContext = (NSOpenGLContext *)manager->GetNSOpenGLContext();
|
||||
glContext = (NSOpenGLContext *)manager->gl()->GetNativeData(mozilla::gl::GLContext::NativeGLContext);
|
||||
|
||||
if (!mGLContext) {
|
||||
[self setGLContext:glContext];
|
||||
|
|
Загрузка…
Ссылка в новой задаче