зеркало из https://github.com/mozilla/gecko-dev.git
Bug 814159 - Part 4: Split TextureImageEGL into separate files - r=benwa
This commit is contained in:
Родитель
e5c293ae67
Коммит
336565d5b0
|
@ -101,6 +101,7 @@ public:
|
|||
#include "gfxPlatform.h"
|
||||
#include "GLContextProvider.h"
|
||||
#include "GLLibraryEGL.h"
|
||||
#include "TextureImageEGL.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
|
@ -968,336 +969,6 @@ GLContextEGL::ResizeOffscreen(const gfxIntSize& aNewSize)
|
|||
return ResizeScreenBuffer(aNewSize);
|
||||
}
|
||||
|
||||
static GLenum
|
||||
GLFormatForImage(gfxImageFormat aFormat)
|
||||
{
|
||||
switch (aFormat) {
|
||||
case gfxImageFormatARGB32:
|
||||
case gfxImageFormatRGB24:
|
||||
// Thebes only supports RGBX, not packed RGB.
|
||||
return LOCAL_GL_RGBA;
|
||||
case gfxImageFormatRGB16_565:
|
||||
return LOCAL_GL_RGB;
|
||||
case gfxImageFormatA8:
|
||||
return LOCAL_GL_LUMINANCE;
|
||||
default:
|
||||
NS_WARNING("Unknown GL format for Image format");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GLenum
|
||||
GLTypeForImage(gfxImageFormat aFormat)
|
||||
{
|
||||
switch (aFormat) {
|
||||
case gfxImageFormatARGB32:
|
||||
case gfxImageFormatRGB24:
|
||||
case gfxImageFormatA8:
|
||||
return LOCAL_GL_UNSIGNED_BYTE;
|
||||
case gfxImageFormatRGB16_565:
|
||||
return LOCAL_GL_UNSIGNED_SHORT_5_6_5;
|
||||
default:
|
||||
NS_WARNING("Unknown GL format for Image format");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
class TextureImageEGL
|
||||
: public TextureImage
|
||||
{
|
||||
public:
|
||||
TextureImageEGL(GLuint aTexture,
|
||||
const nsIntSize& aSize,
|
||||
GLenum aWrapMode,
|
||||
ContentType aContentType,
|
||||
GLContext* aContext,
|
||||
Flags aFlags = TextureImage::NoFlags,
|
||||
TextureState aTextureState = Created,
|
||||
TextureImage::ImageFormat aImageFormat = gfxImageFormatUnknown)
|
||||
: TextureImage(aSize, aWrapMode, aContentType, aFlags)
|
||||
, mGLContext(aContext)
|
||||
, mUpdateFormat(aImageFormat)
|
||||
, mEGLImage(nullptr)
|
||||
, mTexture(aTexture)
|
||||
, mSurface(nullptr)
|
||||
, mConfig(nullptr)
|
||||
, mTextureState(aTextureState)
|
||||
, mBound(false)
|
||||
{
|
||||
if (mUpdateFormat == gfxImageFormatUnknown) {
|
||||
mUpdateFormat = gfxPlatform::GetPlatform()->OptimalFormatForContent(GetContentType());
|
||||
}
|
||||
|
||||
if (mUpdateFormat == gfxImageFormatRGB16_565) {
|
||||
mTextureFormat = FORMAT_R8G8B8X8;
|
||||
} else if (mUpdateFormat == gfxImageFormatRGB24) {
|
||||
// RGB24 means really RGBX for Thebes, which means we have to
|
||||
// use the right shader and ignore the uninitialized alpha
|
||||
// value.
|
||||
mTextureFormat = FORMAT_B8G8R8X8;
|
||||
} else {
|
||||
mTextureFormat = FORMAT_B8G8R8A8;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~TextureImageEGL()
|
||||
{
|
||||
if (mGLContext->IsDestroyed() || !mGLContext->IsOwningThreadCurrent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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.
|
||||
mGLContext->MakeCurrent();
|
||||
mGLContext->fDeleteTextures(1, &mTexture);
|
||||
ReleaseTexImage();
|
||||
DestroyEGLSurface();
|
||||
}
|
||||
|
||||
virtual void GetUpdateRegion(nsIntRegion& aForRegion)
|
||||
{
|
||||
if (mTextureState != Valid) {
|
||||
// if the texture hasn't been initialized yet, force the
|
||||
// client to paint everything
|
||||
aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
|
||||
}
|
||||
|
||||
// We can only draw a rectangle, not subregions due to
|
||||
// the way that our texture upload functions work. If
|
||||
// needed, we /could/ do multiple texture uploads if we have
|
||||
// non-overlapping rects, but that's a tradeoff.
|
||||
aForRegion = nsIntRegion(aForRegion.GetBounds());
|
||||
}
|
||||
|
||||
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion)
|
||||
{
|
||||
NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
|
||||
|
||||
// determine the region the client will need to repaint
|
||||
GetUpdateRegion(aRegion);
|
||||
mUpdateRect = aRegion.GetBounds();
|
||||
|
||||
//printf_stderr("BeginUpdate with updateRect [%d %d %d %d]\n", mUpdateRect.x, mUpdateRect.y, mUpdateRect.width, mUpdateRect.height);
|
||||
if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(mUpdateRect)) {
|
||||
NS_ERROR("update outside of image");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//printf_stderr("creating image surface %dx%d format %d\n", mUpdateRect.width, mUpdateRect.height, mUpdateFormat);
|
||||
|
||||
mUpdateSurface =
|
||||
new gfxImageSurface(gfxIntSize(mUpdateRect.width, mUpdateRect.height),
|
||||
mUpdateFormat);
|
||||
|
||||
mUpdateSurface->SetDeviceOffset(gfxPoint(-mUpdateRect.x, -mUpdateRect.y));
|
||||
|
||||
return mUpdateSurface;
|
||||
}
|
||||
|
||||
virtual void EndUpdate()
|
||||
{
|
||||
NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
|
||||
|
||||
//printf_stderr("EndUpdate: slow path");
|
||||
|
||||
// This is the slower path -- we didn't have any way to set up
|
||||
// a fast mapping between our cairo target surface and the GL
|
||||
// texture, so we have to upload data.
|
||||
|
||||
// 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));
|
||||
|
||||
nsRefPtr<gfxImageSurface> uploadImage = nullptr;
|
||||
gfxIntSize updateSize(mUpdateRect.width, mUpdateRect.height);
|
||||
|
||||
NS_ASSERTION(mUpdateSurface->GetType() == gfxSurfaceTypeImage &&
|
||||
mUpdateSurface->GetSize() == updateSize,
|
||||
"Upload image isn't an image surface when one is expected, or is wrong size!");
|
||||
|
||||
uploadImage = static_cast<gfxImageSurface*>(mUpdateSurface.get());
|
||||
|
||||
if (!uploadImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
mGLContext->MakeCurrent();
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
if (mTextureState != Valid) {
|
||||
NS_ASSERTION(mUpdateRect.x == 0 && mUpdateRect.y == 0 &&
|
||||
mUpdateRect.Size() == mSize,
|
||||
"Bad initial update on non-created texture!");
|
||||
|
||||
mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
GLFormatForImage(mUpdateFormat),
|
||||
mUpdateRect.width,
|
||||
mUpdateRect.height,
|
||||
0,
|
||||
GLFormatForImage(uploadImage->Format()),
|
||||
GLTypeForImage(uploadImage->Format()),
|
||||
uploadImage->Data());
|
||||
} else {
|
||||
mGLContext->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
mUpdateRect.x,
|
||||
mUpdateRect.y,
|
||||
mUpdateRect.width,
|
||||
mUpdateRect.height,
|
||||
GLFormatForImage(uploadImage->Format()),
|
||||
GLTypeForImage(uploadImage->Format()),
|
||||
uploadImage->Data());
|
||||
}
|
||||
|
||||
mUpdateSurface = nullptr;
|
||||
mTextureState = Valid;
|
||||
return; // mTexture is bound
|
||||
}
|
||||
|
||||
virtual bool 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;
|
||||
}
|
||||
|
||||
mTextureFormat =
|
||||
mGLContext->UploadSurfaceToTexture(aSurf,
|
||||
region,
|
||||
mTexture,
|
||||
mTextureState == Created,
|
||||
bounds.TopLeft() + aFrom,
|
||||
false);
|
||||
|
||||
mTextureState = Valid;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void BindTexture(GLenum aTextureUnit)
|
||||
{
|
||||
// Ensure the texture is allocated before it is used.
|
||||
if (mTextureState == Created) {
|
||||
Resize(mSize);
|
||||
}
|
||||
|
||||
mGLContext->fActiveTexture(aTextureUnit);
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
}
|
||||
|
||||
virtual GLuint GetTextureID()
|
||||
{
|
||||
// Ensure the texture is allocated before it is used.
|
||||
if (mTextureState == Created) {
|
||||
Resize(mSize);
|
||||
}
|
||||
return mTexture;
|
||||
};
|
||||
|
||||
virtual bool InUpdate() const { return !!mUpdateSurface; }
|
||||
|
||||
virtual void Resize(const nsIntSize& aSize)
|
||||
{
|
||||
NS_ASSERTION(!mUpdateSurface, "Resize() while in update?");
|
||||
|
||||
if (mSize == aSize && mTextureState != Created)
|
||||
return;
|
||||
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
GLFormatForImage(mUpdateFormat),
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
0,
|
||||
GLFormatForImage(mUpdateFormat),
|
||||
GLTypeForImage(mUpdateFormat),
|
||||
nullptr);
|
||||
|
||||
mTextureState = Allocated;
|
||||
mSize = aSize;
|
||||
}
|
||||
|
||||
bool BindTexImage()
|
||||
{
|
||||
if (mBound && !ReleaseTexImage())
|
||||
return false;
|
||||
|
||||
EGLBoolean success =
|
||||
sEGLLibrary.fBindTexImage(EGL_DISPLAY(),
|
||||
(EGLSurface)mSurface,
|
||||
LOCAL_EGL_BACK_BUFFER);
|
||||
|
||||
if (success == LOCAL_EGL_FALSE)
|
||||
return false;
|
||||
|
||||
mBound = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReleaseTexImage()
|
||||
{
|
||||
if (!mBound)
|
||||
return true;
|
||||
|
||||
EGLBoolean success =
|
||||
sEGLLibrary.fReleaseTexImage(EGL_DISPLAY(),
|
||||
(EGLSurface)mSurface,
|
||||
LOCAL_EGL_BACK_BUFFER);
|
||||
|
||||
if (success == LOCAL_EGL_FALSE)
|
||||
return false;
|
||||
|
||||
mBound = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool CreateEGLSurface(gfxASurface* aSurface)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void DestroyEGLSurface(void)
|
||||
{
|
||||
if (!mSurface)
|
||||
return;
|
||||
|
||||
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), mSurface);
|
||||
mSurface = nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef gfxImageFormat ImageFormat;
|
||||
|
||||
GLContext* mGLContext;
|
||||
|
||||
nsIntRect mUpdateRect;
|
||||
ImageFormat mUpdateFormat;
|
||||
nsRefPtr<gfxASurface> mUpdateSurface;
|
||||
EGLImage mEGLImage;
|
||||
GLuint mTexture;
|
||||
EGLSurface mSurface;
|
||||
EGLConfig mConfig;
|
||||
TextureState mTextureState;
|
||||
|
||||
bool mBound;
|
||||
|
||||
virtual void ApplyFilter()
|
||||
{
|
||||
mGLContext->ApplyFilterToBoundTexture(mFilter);
|
||||
}
|
||||
};
|
||||
|
||||
already_AddRefed<TextureImage>
|
||||
GLContextEGL::CreateTextureImage(const nsIntSize& aSize,
|
||||
TextureImage::ContentType aContentType,
|
||||
|
|
|
@ -530,6 +530,9 @@ private:
|
|||
bool mIsANGLE;
|
||||
};
|
||||
|
||||
extern GLLibraryEGL sEGLLibrary;
|
||||
#define EGL_DISPLAY() sEGLLibrary.Display()
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
||||
|
|
|
@ -0,0 +1,319 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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 "TextureImageEGL.h"
|
||||
#include "GLLibraryEGL.h"
|
||||
#include "GLContext.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "mozilla/gfx/Types.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
static GLenum
|
||||
GLFormatForImage(gfxImageFormat aFormat)
|
||||
{
|
||||
switch (aFormat) {
|
||||
case gfxImageFormatARGB32:
|
||||
case gfxImageFormatRGB24:
|
||||
// Thebes only supports RGBX, not packed RGB.
|
||||
return LOCAL_GL_RGBA;
|
||||
case gfxImageFormatRGB16_565:
|
||||
return LOCAL_GL_RGB;
|
||||
case gfxImageFormatA8:
|
||||
return LOCAL_GL_LUMINANCE;
|
||||
default:
|
||||
NS_WARNING("Unknown GL format for Image format");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GLenum
|
||||
GLTypeForImage(gfxImageFormat aFormat)
|
||||
{
|
||||
switch (aFormat) {
|
||||
case gfxImageFormatARGB32:
|
||||
case gfxImageFormatRGB24:
|
||||
case gfxImageFormatA8:
|
||||
return LOCAL_GL_UNSIGNED_BYTE;
|
||||
case gfxImageFormatRGB16_565:
|
||||
return LOCAL_GL_UNSIGNED_SHORT_5_6_5;
|
||||
default:
|
||||
NS_WARNING("Unknown GL format for Image format");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
TextureImageEGL::TextureImageEGL(GLuint aTexture,
|
||||
const nsIntSize& aSize,
|
||||
GLenum aWrapMode,
|
||||
ContentType aContentType,
|
||||
GLContext* aContext,
|
||||
Flags aFlags,
|
||||
TextureState aTextureState,
|
||||
TextureImage::ImageFormat aImageFormat)
|
||||
: TextureImage(aSize, aWrapMode, aContentType, aFlags)
|
||||
, mGLContext(aContext)
|
||||
, mUpdateFormat(aImageFormat)
|
||||
, mEGLImage(nullptr)
|
||||
, mTexture(aTexture)
|
||||
, mSurface(nullptr)
|
||||
, mConfig(nullptr)
|
||||
, mTextureState(aTextureState)
|
||||
, mBound(false)
|
||||
{
|
||||
if (mUpdateFormat == gfxImageFormatUnknown) {
|
||||
mUpdateFormat = gfxPlatform::GetPlatform()->OptimalFormatForContent(GetContentType());
|
||||
}
|
||||
|
||||
if (mUpdateFormat == gfxImageFormatRGB16_565) {
|
||||
mTextureFormat = gfx::FORMAT_R8G8B8X8;
|
||||
} else if (mUpdateFormat == gfxImageFormatRGB24) {
|
||||
// RGB24 means really RGBX for Thebes, which means we have to
|
||||
// use the right shader and ignore the uninitialized alpha
|
||||
// value.
|
||||
mTextureFormat = gfx::FORMAT_B8G8R8X8;
|
||||
} else {
|
||||
mTextureFormat = gfx::FORMAT_B8G8R8A8;
|
||||
}
|
||||
}
|
||||
|
||||
TextureImageEGL::~TextureImageEGL()
|
||||
{
|
||||
if (mGLContext->IsDestroyed() || !mGLContext->IsOwningThreadCurrent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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.
|
||||
mGLContext->MakeCurrent();
|
||||
mGLContext->fDeleteTextures(1, &mTexture);
|
||||
ReleaseTexImage();
|
||||
DestroyEGLSurface();
|
||||
}
|
||||
|
||||
void
|
||||
TextureImageEGL::GetUpdateRegion(nsIntRegion& aForRegion)
|
||||
{
|
||||
if (mTextureState != Valid) {
|
||||
// if the texture hasn't been initialized yet, force the
|
||||
// client to paint everything
|
||||
aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
|
||||
}
|
||||
|
||||
// We can only draw a rectangle, not subregions due to
|
||||
// the way that our texture upload functions work. If
|
||||
// needed, we /could/ do multiple texture uploads if we have
|
||||
// non-overlapping rects, but that's a tradeoff.
|
||||
aForRegion = nsIntRegion(aForRegion.GetBounds());
|
||||
}
|
||||
|
||||
gfxASurface*
|
||||
TextureImageEGL::BeginUpdate(nsIntRegion& aRegion)
|
||||
{
|
||||
NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
|
||||
|
||||
// determine the region the client will need to repaint
|
||||
GetUpdateRegion(aRegion);
|
||||
mUpdateRect = aRegion.GetBounds();
|
||||
|
||||
//printf_stderr("BeginUpdate with updateRect [%d %d %d %d]\n", mUpdateRect.x, mUpdateRect.y, mUpdateRect.width, mUpdateRect.height);
|
||||
if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(mUpdateRect)) {
|
||||
NS_ERROR("update outside of image");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//printf_stderr("creating image surface %dx%d format %d\n", mUpdateRect.width, mUpdateRect.height, mUpdateFormat);
|
||||
|
||||
mUpdateSurface =
|
||||
new gfxImageSurface(gfxIntSize(mUpdateRect.width, mUpdateRect.height),
|
||||
mUpdateFormat);
|
||||
|
||||
mUpdateSurface->SetDeviceOffset(gfxPoint(-mUpdateRect.x, -mUpdateRect.y));
|
||||
|
||||
return mUpdateSurface;
|
||||
}
|
||||
|
||||
void
|
||||
TextureImageEGL::EndUpdate()
|
||||
{
|
||||
NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
|
||||
|
||||
//printf_stderr("EndUpdate: slow path");
|
||||
|
||||
// This is the slower path -- we didn't have any way to set up
|
||||
// a fast mapping between our cairo target surface and the GL
|
||||
// texture, so we have to upload data.
|
||||
|
||||
// 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));
|
||||
|
||||
nsRefPtr<gfxImageSurface> uploadImage = nullptr;
|
||||
gfxIntSize updateSize(mUpdateRect.width, mUpdateRect.height);
|
||||
|
||||
NS_ASSERTION(mUpdateSurface->GetType() == gfxSurfaceTypeImage &&
|
||||
mUpdateSurface->GetSize() == updateSize,
|
||||
"Upload image isn't an image surface when one is expected, or is wrong size!");
|
||||
|
||||
uploadImage = static_cast<gfxImageSurface*>(mUpdateSurface.get());
|
||||
|
||||
if (!uploadImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
mGLContext->MakeCurrent();
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
if (mTextureState != Valid) {
|
||||
NS_ASSERTION(mUpdateRect.x == 0 && mUpdateRect.y == 0 &&
|
||||
mUpdateRect.Size() == mSize,
|
||||
"Bad initial update on non-created texture!");
|
||||
|
||||
mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
GLFormatForImage(mUpdateFormat),
|
||||
mUpdateRect.width,
|
||||
mUpdateRect.height,
|
||||
0,
|
||||
GLFormatForImage(uploadImage->Format()),
|
||||
GLTypeForImage(uploadImage->Format()),
|
||||
uploadImage->Data());
|
||||
} else {
|
||||
mGLContext->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
mUpdateRect.x,
|
||||
mUpdateRect.y,
|
||||
mUpdateRect.width,
|
||||
mUpdateRect.height,
|
||||
GLFormatForImage(uploadImage->Format()),
|
||||
GLTypeForImage(uploadImage->Format()),
|
||||
uploadImage->Data());
|
||||
}
|
||||
|
||||
mUpdateSurface = nullptr;
|
||||
mTextureState = Valid;
|
||||
return; // mTexture is bound
|
||||
}
|
||||
|
||||
bool
|
||||
TextureImageEGL::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;
|
||||
}
|
||||
|
||||
mTextureFormat =
|
||||
mGLContext->UploadSurfaceToTexture(aSurf,
|
||||
region,
|
||||
mTexture,
|
||||
mTextureState == Created,
|
||||
bounds.TopLeft() + aFrom,
|
||||
false);
|
||||
|
||||
mTextureState = Valid;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TextureImageEGL::BindTexture(GLenum aTextureUnit)
|
||||
{
|
||||
// Ensure the texture is allocated before it is used.
|
||||
if (mTextureState == Created) {
|
||||
Resize(mSize);
|
||||
}
|
||||
|
||||
mGLContext->fActiveTexture(aTextureUnit);
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
}
|
||||
|
||||
void
|
||||
TextureImageEGL::Resize(const nsIntSize& aSize)
|
||||
{
|
||||
NS_ASSERTION(!mUpdateSurface, "Resize() while in update?");
|
||||
|
||||
if (mSize == aSize && mTextureState != Created)
|
||||
return;
|
||||
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
GLFormatForImage(mUpdateFormat),
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
0,
|
||||
GLFormatForImage(mUpdateFormat),
|
||||
GLTypeForImage(mUpdateFormat),
|
||||
nullptr);
|
||||
|
||||
mTextureState = Allocated;
|
||||
mSize = aSize;
|
||||
}
|
||||
|
||||
bool
|
||||
TextureImageEGL::BindTexImage()
|
||||
{
|
||||
if (mBound && !ReleaseTexImage())
|
||||
return false;
|
||||
|
||||
EGLBoolean success =
|
||||
sEGLLibrary.fBindTexImage(EGL_DISPLAY(),
|
||||
(EGLSurface)mSurface,
|
||||
LOCAL_EGL_BACK_BUFFER);
|
||||
|
||||
if (success == LOCAL_EGL_FALSE)
|
||||
return false;
|
||||
|
||||
mBound = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TextureImageEGL::ReleaseTexImage()
|
||||
{
|
||||
if (!mBound)
|
||||
return true;
|
||||
|
||||
EGLBoolean success =
|
||||
sEGLLibrary.fReleaseTexImage(EGL_DISPLAY(),
|
||||
(EGLSurface)mSurface,
|
||||
LOCAL_EGL_BACK_BUFFER);
|
||||
|
||||
if (success == LOCAL_EGL_FALSE)
|
||||
return false;
|
||||
|
||||
mBound = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TextureImageEGL::DestroyEGLSurface(void)
|
||||
{
|
||||
if (!mSurface)
|
||||
return;
|
||||
|
||||
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), mSurface);
|
||||
mSurface = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
TextureImageEGL::ApplyFilter()
|
||||
{
|
||||
mGLContext->ApplyFilterToBoundTexture(mFilter);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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 TEXTUREIMAGEEGL_H_
|
||||
#define TEXTUREIMAGEEGL_H_
|
||||
|
||||
#include "GLTextureImage.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
class TextureImageEGL
|
||||
: public TextureImage
|
||||
{
|
||||
public:
|
||||
TextureImageEGL(GLuint aTexture,
|
||||
const nsIntSize& aSize,
|
||||
GLenum aWrapMode,
|
||||
ContentType aContentType,
|
||||
GLContext* aContext,
|
||||
Flags aFlags = TextureImage::NoFlags,
|
||||
TextureState aTextureState = Created,
|
||||
TextureImage::ImageFormat aImageFormat = gfxImageFormatUnknown);
|
||||
|
||||
virtual ~TextureImageEGL();
|
||||
|
||||
virtual void GetUpdateRegion(nsIntRegion& aForRegion);
|
||||
|
||||
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
|
||||
|
||||
virtual void EndUpdate();
|
||||
|
||||
virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */);
|
||||
|
||||
virtual void BindTexture(GLenum aTextureUnit);
|
||||
|
||||
virtual GLuint GetTextureID()
|
||||
{
|
||||
// Ensure the texture is allocated before it is used.
|
||||
if (mTextureState == Created) {
|
||||
Resize(mSize);
|
||||
}
|
||||
return mTexture;
|
||||
};
|
||||
|
||||
virtual bool InUpdate() const { return !!mUpdateSurface; }
|
||||
|
||||
virtual void Resize(const nsIntSize& aSize);
|
||||
|
||||
bool BindTexImage();
|
||||
|
||||
bool ReleaseTexImage();
|
||||
|
||||
virtual bool CreateEGLSurface(gfxASurface* aSurface)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void DestroyEGLSurface(void);
|
||||
|
||||
protected:
|
||||
typedef gfxImageFormat ImageFormat;
|
||||
|
||||
GLContext* mGLContext;
|
||||
|
||||
nsIntRect mUpdateRect;
|
||||
ImageFormat mUpdateFormat;
|
||||
nsRefPtr<gfxASurface> mUpdateSurface;
|
||||
EGLImage mEGLImage;
|
||||
GLuint mTexture;
|
||||
EGLSurface mSurface;
|
||||
EGLConfig mConfig;
|
||||
TextureState mTextureState;
|
||||
|
||||
bool mBound;
|
||||
|
||||
virtual void ApplyFilter();
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TEXTUREIMAGEEGL_H_
|
|
@ -102,6 +102,7 @@ CPP_SOURCES += [
|
|||
'SharedSurface.cpp',
|
||||
'GLLibraryEGL.cpp',
|
||||
'SharedSurfaceEGL.cpp',
|
||||
'TextureImageEGL.cpp',
|
||||
'SharedSurfaceGL.cpp',
|
||||
'SurfaceFactory.cpp',
|
||||
'SurfaceStream.cpp',
|
||||
|
|
Загрузка…
Ссылка в новой задаче