mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 942509 - Move Upload* functions to new GLUploadHelpers files - r=gal,jgilbert
This commit is contained in:
parent
988099a6e9
commit
884f878ce5
@ -2517,247 +2517,6 @@ GLContext::ReadPixelsIntoImageSurface(gfxImageSurface* dest)
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
DataOffset(const nsIntPoint &aPoint, int32_t aStride, gfxImageFormat aFormat)
|
||||
{
|
||||
unsigned int data = aPoint.y * aStride;
|
||||
data += aPoint.x * gfxASurface::BytePerPixelFromFormat(aFormat);
|
||||
return data;
|
||||
}
|
||||
|
||||
GLContext::SurfaceFormat
|
||||
GLContext::UploadImageDataToTexture(unsigned char* aData,
|
||||
int32_t aStride,
|
||||
gfxImageFormat aFormat,
|
||||
const nsIntRegion& aDstRegion,
|
||||
GLuint& aTexture,
|
||||
bool aOverwrite,
|
||||
bool aPixelBuffer,
|
||||
GLenum aTextureUnit,
|
||||
GLenum aTextureTarget)
|
||||
{
|
||||
bool textureInited = aOverwrite ? false : true;
|
||||
MakeCurrent();
|
||||
fActiveTexture(aTextureUnit);
|
||||
|
||||
if (!aTexture) {
|
||||
fGenTextures(1, &aTexture);
|
||||
fBindTexture(aTextureTarget, aTexture);
|
||||
fTexParameteri(aTextureTarget,
|
||||
LOCAL_GL_TEXTURE_MIN_FILTER,
|
||||
LOCAL_GL_LINEAR);
|
||||
fTexParameteri(aTextureTarget,
|
||||
LOCAL_GL_TEXTURE_MAG_FILTER,
|
||||
LOCAL_GL_LINEAR);
|
||||
fTexParameteri(aTextureTarget,
|
||||
LOCAL_GL_TEXTURE_WRAP_S,
|
||||
LOCAL_GL_CLAMP_TO_EDGE);
|
||||
fTexParameteri(aTextureTarget,
|
||||
LOCAL_GL_TEXTURE_WRAP_T,
|
||||
LOCAL_GL_CLAMP_TO_EDGE);
|
||||
textureInited = false;
|
||||
} else {
|
||||
fBindTexture(aTextureTarget, aTexture);
|
||||
}
|
||||
|
||||
nsIntRegion paintRegion;
|
||||
if (!textureInited) {
|
||||
paintRegion = nsIntRegion(aDstRegion.GetBounds());
|
||||
} else {
|
||||
paintRegion = aDstRegion;
|
||||
}
|
||||
|
||||
GLenum format;
|
||||
GLenum internalFormat;
|
||||
GLenum type;
|
||||
int32_t pixelSize = gfxASurface::BytePerPixelFromFormat(aFormat);
|
||||
SurfaceFormat surfaceFormat;
|
||||
|
||||
MOZ_ASSERT(GetPreferredARGB32Format() == LOCAL_GL_BGRA ||
|
||||
GetPreferredARGB32Format() == LOCAL_GL_RGBA);
|
||||
switch (aFormat) {
|
||||
case gfxImageFormatARGB32:
|
||||
if (GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
|
||||
format = LOCAL_GL_BGRA;
|
||||
surfaceFormat = FORMAT_R8G8B8A8;
|
||||
type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
} else {
|
||||
format = LOCAL_GL_RGBA;
|
||||
surfaceFormat = FORMAT_B8G8R8A8;
|
||||
type = LOCAL_GL_UNSIGNED_BYTE;
|
||||
}
|
||||
internalFormat = LOCAL_GL_RGBA;
|
||||
break;
|
||||
case gfxImageFormatRGB24:
|
||||
// Treat RGB24 surfaces as RGBA32 except for the surface
|
||||
// format used.
|
||||
if (GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
|
||||
format = LOCAL_GL_BGRA;
|
||||
surfaceFormat = FORMAT_R8G8B8X8;
|
||||
type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
} else {
|
||||
format = LOCAL_GL_RGBA;
|
||||
surfaceFormat = FORMAT_B8G8R8X8;
|
||||
type = LOCAL_GL_UNSIGNED_BYTE;
|
||||
}
|
||||
internalFormat = LOCAL_GL_RGBA;
|
||||
break;
|
||||
case gfxImageFormatRGB16_565:
|
||||
internalFormat = format = LOCAL_GL_RGB;
|
||||
type = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
|
||||
surfaceFormat = FORMAT_R5G6B5;
|
||||
break;
|
||||
case gfxImageFormatA8:
|
||||
internalFormat = format = LOCAL_GL_LUMINANCE;
|
||||
type = LOCAL_GL_UNSIGNED_BYTE;
|
||||
// We don't have a specific luminance shader
|
||||
surfaceFormat = FORMAT_A8;
|
||||
break;
|
||||
default:
|
||||
NS_ASSERTION(false, "Unhandled image surface format!");
|
||||
format = 0;
|
||||
type = 0;
|
||||
surfaceFormat = FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
nsIntRegionRectIterator iter(paintRegion);
|
||||
const nsIntRect *iterRect;
|
||||
|
||||
// Top left point of the region's bounding rectangle.
|
||||
nsIntPoint topLeft = paintRegion.GetBounds().TopLeft();
|
||||
|
||||
while ((iterRect = iter.Next())) {
|
||||
// The inital data pointer is at the top left point of the region's
|
||||
// bounding rectangle. We need to find the offset of this rect
|
||||
// within the region and adjust the data pointer accordingly.
|
||||
unsigned char *rectData =
|
||||
aData + DataOffset(iterRect->TopLeft() - topLeft, aStride, aFormat);
|
||||
|
||||
NS_ASSERTION(textureInited || (iterRect->x == 0 && iterRect->y == 0),
|
||||
"Must be uploading to the origin when we don't have an existing texture");
|
||||
|
||||
if (textureInited && CanUploadSubTextures()) {
|
||||
TexSubImage2D(aTextureTarget,
|
||||
0,
|
||||
iterRect->x,
|
||||
iterRect->y,
|
||||
iterRect->width,
|
||||
iterRect->height,
|
||||
aStride,
|
||||
pixelSize,
|
||||
format,
|
||||
type,
|
||||
rectData);
|
||||
} else {
|
||||
TexImage2D(aTextureTarget,
|
||||
0,
|
||||
internalFormat,
|
||||
iterRect->width,
|
||||
iterRect->height,
|
||||
aStride,
|
||||
pixelSize,
|
||||
0,
|
||||
format,
|
||||
type,
|
||||
rectData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return surfaceFormat;
|
||||
}
|
||||
|
||||
GLContext::SurfaceFormat
|
||||
GLContext::UploadSurfaceToTexture(gfxASurface *aSurface,
|
||||
const nsIntRegion& aDstRegion,
|
||||
GLuint& aTexture,
|
||||
bool aOverwrite,
|
||||
const nsIntPoint& aSrcPoint,
|
||||
bool aPixelBuffer,
|
||||
GLenum aTextureUnit,
|
||||
GLenum aTextureTarget)
|
||||
{
|
||||
|
||||
nsRefPtr<gfxImageSurface> imageSurface = aSurface->GetAsImageSurface();
|
||||
unsigned char* data = nullptr;
|
||||
|
||||
if (!imageSurface ||
|
||||
(imageSurface->Format() != gfxImageFormatARGB32 &&
|
||||
imageSurface->Format() != gfxImageFormatRGB24 &&
|
||||
imageSurface->Format() != gfxImageFormatRGB16_565 &&
|
||||
imageSurface->Format() != gfxImageFormatA8)) {
|
||||
// We can't get suitable pixel data for the surface, make a copy
|
||||
nsIntRect bounds = aDstRegion.GetBounds();
|
||||
imageSurface =
|
||||
new gfxImageSurface(gfxIntSize(bounds.width, bounds.height),
|
||||
gfxImageFormatARGB32);
|
||||
|
||||
nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
|
||||
|
||||
context->Translate(-gfxPoint(aSrcPoint.x, aSrcPoint.y));
|
||||
context->SetSource(aSurface);
|
||||
context->Paint();
|
||||
data = imageSurface->Data();
|
||||
NS_ASSERTION(!aPixelBuffer,
|
||||
"Must be using an image compatible surface with pixel buffers!");
|
||||
} else {
|
||||
// If a pixel buffer is bound the data pointer parameter is relative
|
||||
// to the start of the data block.
|
||||
if (!aPixelBuffer) {
|
||||
data = imageSurface->Data();
|
||||
}
|
||||
data += DataOffset(aSrcPoint, imageSurface->Stride(),
|
||||
imageSurface->Format());
|
||||
}
|
||||
|
||||
MOZ_ASSERT(imageSurface);
|
||||
imageSurface->Flush();
|
||||
|
||||
return UploadImageDataToTexture(data,
|
||||
imageSurface->Stride(),
|
||||
imageSurface->Format(),
|
||||
aDstRegion, aTexture, aOverwrite,
|
||||
aPixelBuffer, aTextureUnit, aTextureTarget);
|
||||
}
|
||||
|
||||
static gfxImageFormat
|
||||
ImageFormatForSurfaceFormat(gfx::SurfaceFormat aFormat)
|
||||
{
|
||||
switch (aFormat) {
|
||||
case gfx::FORMAT_B8G8R8A8:
|
||||
return gfxImageFormatARGB32;
|
||||
case gfx::FORMAT_B8G8R8X8:
|
||||
return gfxImageFormatRGB24;
|
||||
case gfx::FORMAT_R5G6B5:
|
||||
return gfxImageFormatRGB16_565;
|
||||
case gfx::FORMAT_A8:
|
||||
return gfxImageFormatA8;
|
||||
default:
|
||||
return gfxImageFormatUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
GLContext::SurfaceFormat
|
||||
GLContext::UploadSurfaceToTexture(gfx::DataSourceSurface *aSurface,
|
||||
const nsIntRegion& aDstRegion,
|
||||
GLuint& aTexture,
|
||||
bool aOverwrite,
|
||||
const nsIntPoint& aSrcPoint,
|
||||
bool aPixelBuffer,
|
||||
GLenum aTextureUnit,
|
||||
GLenum aTextureTarget)
|
||||
{
|
||||
unsigned char* data = aPixelBuffer ? nullptr : aSurface->GetData();
|
||||
int32_t stride = aSurface->Stride();
|
||||
gfxImageFormat format =
|
||||
ImageFormatForSurfaceFormat(aSurface->GetFormat());
|
||||
data += DataOffset(aSrcPoint, stride, format);
|
||||
return UploadImageDataToTexture(data, stride, format,
|
||||
aDstRegion, aTexture, aOverwrite,
|
||||
aPixelBuffer, aTextureUnit,
|
||||
aTextureTarget);
|
||||
}
|
||||
|
||||
static GLint GetAddressAlignment(ptrdiff_t aAddress)
|
||||
{
|
||||
if (!(aAddress & 0x7)) {
|
||||
|
@ -2673,71 +2673,6 @@ public:
|
||||
|
||||
TemporaryRef<gfx::SourceSurface> ReadPixelsToSourceSurface(const gfx::IntSize &aSize);
|
||||
|
||||
/**
|
||||
* Creates a RGB/RGBA texture (or uses one provided) and uploads the surface
|
||||
* contents to it within aSrcRect.
|
||||
*
|
||||
* aSrcRect.x/y will be uploaded to 0/0 in the texture, and the size
|
||||
* of the texture with be aSrcRect.width/height.
|
||||
*
|
||||
* If an existing texture is passed through aTexture, it is assumed it
|
||||
* has already been initialised with glTexImage2D (or this function),
|
||||
* and that its size is equal to or greater than aSrcRect + aDstPoint.
|
||||
* You can alternatively set the overwrite flag to true and have a new
|
||||
* texture memory block allocated.
|
||||
*
|
||||
* The aDstPoint parameter is ignored if no texture was provided
|
||||
* or aOverwrite is true.
|
||||
*
|
||||
* \param aData Image data to upload.
|
||||
* \param aDstRegion Region of texture to upload to.
|
||||
* \param aTexture Texture to use, or 0 to have one created for you.
|
||||
* \param aOverwrite Over an existing texture with a new one.
|
||||
* \param aSrcPoint Offset into aSrc where the region's bound's
|
||||
* TopLeft() sits.
|
||||
* \param aPixelBuffer Pass true to upload texture data with an
|
||||
* offset from the base data (generally for pixel buffer objects),
|
||||
* otherwise textures are upload with an absolute pointer to the data.
|
||||
* \param aTextureUnit, the texture unit used temporarily to upload the
|
||||
* surface. This testure may be overridden, clients should not rely on
|
||||
* the contents of this texture after this call or even on this
|
||||
* texture unit being active.
|
||||
* \return Surface format of this texture.
|
||||
*/
|
||||
SurfaceFormat UploadImageDataToTexture(unsigned char* aData,
|
||||
int32_t aStride,
|
||||
gfxImageFormat aFormat,
|
||||
const nsIntRegion& aDstRegion,
|
||||
GLuint& aTexture,
|
||||
bool aOverwrite = false,
|
||||
bool aPixelBuffer = false,
|
||||
GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
|
||||
GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D);
|
||||
|
||||
/**
|
||||
* Convenience wrapper around UploadImageDataToTexture for gfxASurfaces.
|
||||
*/
|
||||
SurfaceFormat UploadSurfaceToTexture(gfxASurface *aSurface,
|
||||
const nsIntRegion& aDstRegion,
|
||||
GLuint& aTexture,
|
||||
bool aOverwrite = false,
|
||||
const nsIntPoint& aSrcPoint = nsIntPoint(0, 0),
|
||||
bool aPixelBuffer = false,
|
||||
GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
|
||||
GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D);
|
||||
|
||||
/**
|
||||
* Same as above, for DataSourceSurfaces.
|
||||
*/
|
||||
SurfaceFormat UploadSurfaceToTexture(gfx::DataSourceSurface *aSurface,
|
||||
const nsIntRegion& aDstRegion,
|
||||
GLuint& aTexture,
|
||||
bool aOverwrite = false,
|
||||
const nsIntPoint& aSrcPoint = nsIntPoint(0, 0),
|
||||
bool aPixelBuffer = false,
|
||||
GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
|
||||
GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D);
|
||||
|
||||
void TexImage2D(GLenum target, GLint level, GLint internalformat,
|
||||
GLsizei width, GLsizei height, GLsizei stride,
|
||||
GLint pixelsize, GLint border, GLenum format,
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "gfxUtils.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "ScopedGLHelpers.h"
|
||||
#include "GLUploadHelpers.h"
|
||||
|
||||
#include "TextureImageEGL.h"
|
||||
#ifdef XP_MACOSX
|
||||
@ -183,12 +184,13 @@ BasicTextureImage::EndUpdate()
|
||||
bool relative = FinishedSurfaceUpdate();
|
||||
|
||||
mTextureFormat =
|
||||
mGLContext->UploadSurfaceToTexture(mUpdateSurface,
|
||||
mUpdateRegion,
|
||||
mTexture,
|
||||
mTextureState == Created,
|
||||
mUpdateOffset,
|
||||
relative);
|
||||
UploadSurfaceToTexture(mGLContext,
|
||||
mUpdateSurface,
|
||||
mUpdateRegion,
|
||||
mTexture,
|
||||
mTextureState == Created,
|
||||
mUpdateOffset,
|
||||
relative);
|
||||
FinishedSurfaceUpload();
|
||||
|
||||
mUpdateSurface = nullptr;
|
||||
@ -241,12 +243,13 @@ BasicTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion,
|
||||
}
|
||||
|
||||
mTextureFormat =
|
||||
mGLContext->UploadSurfaceToTexture(aSurf,
|
||||
region,
|
||||
mTexture,
|
||||
mTextureState == Created,
|
||||
bounds.TopLeft() + aFrom,
|
||||
false);
|
||||
UploadSurfaceToTexture(mGLContext,
|
||||
aSurf,
|
||||
region,
|
||||
mTexture,
|
||||
mTextureState == Created,
|
||||
bounds.TopLeft() + aFrom,
|
||||
false);
|
||||
mTextureState = Valid;
|
||||
return true;
|
||||
}
|
||||
|
267
gfx/gl/GLUploadHelpers.cpp
Normal file
267
gfx/gl/GLUploadHelpers.cpp
Normal file
@ -0,0 +1,267 @@
|
||||
/* -*- 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 "GLUploadHelpers.h"
|
||||
|
||||
#include "GLContext.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "gfxASurface.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "gfxContext.h"
|
||||
#include "nsRegion.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using gfx::SurfaceFormat;
|
||||
|
||||
namespace gl {
|
||||
|
||||
static unsigned int
|
||||
DataOffset(const nsIntPoint &aPoint, int32_t aStride, gfxImageFormat aFormat)
|
||||
{
|
||||
unsigned int data = aPoint.y * aStride;
|
||||
data += aPoint.x * gfxASurface::BytePerPixelFromFormat(aFormat);
|
||||
return data;
|
||||
}
|
||||
|
||||
static gfxImageFormat
|
||||
ImageFormatForSurfaceFormat(gfx::SurfaceFormat aFormat)
|
||||
{
|
||||
switch (aFormat) {
|
||||
case gfx::FORMAT_B8G8R8A8:
|
||||
return gfxImageFormatARGB32;
|
||||
case gfx::FORMAT_B8G8R8X8:
|
||||
return gfxImageFormatRGB24;
|
||||
case gfx::FORMAT_R5G6B5:
|
||||
return gfxImageFormatRGB16_565;
|
||||
case gfx::FORMAT_A8:
|
||||
return gfxImageFormatA8;
|
||||
default:
|
||||
return gfxImageFormatUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
SurfaceFormat
|
||||
UploadImageDataToTexture(GLContext* gl,
|
||||
unsigned char* aData,
|
||||
int32_t aStride,
|
||||
gfxImageFormat aFormat,
|
||||
const nsIntRegion& aDstRegion,
|
||||
GLuint& aTexture,
|
||||
bool aOverwrite,
|
||||
bool aPixelBuffer,
|
||||
GLenum aTextureUnit,
|
||||
GLenum aTextureTarget)
|
||||
{
|
||||
bool textureInited = aOverwrite ? false : true;
|
||||
gl->MakeCurrent();
|
||||
gl->fActiveTexture(aTextureUnit);
|
||||
|
||||
if (!aTexture) {
|
||||
gl->fGenTextures(1, &aTexture);
|
||||
gl->fBindTexture(aTextureTarget, aTexture);
|
||||
gl->fTexParameteri(aTextureTarget,
|
||||
LOCAL_GL_TEXTURE_MIN_FILTER,
|
||||
LOCAL_GL_LINEAR);
|
||||
gl->fTexParameteri(aTextureTarget,
|
||||
LOCAL_GL_TEXTURE_MAG_FILTER,
|
||||
LOCAL_GL_LINEAR);
|
||||
gl->fTexParameteri(aTextureTarget,
|
||||
LOCAL_GL_TEXTURE_WRAP_S,
|
||||
LOCAL_GL_CLAMP_TO_EDGE);
|
||||
gl->fTexParameteri(aTextureTarget,
|
||||
LOCAL_GL_TEXTURE_WRAP_T,
|
||||
LOCAL_GL_CLAMP_TO_EDGE);
|
||||
textureInited = false;
|
||||
} else {
|
||||
gl->fBindTexture(aTextureTarget, aTexture);
|
||||
}
|
||||
|
||||
nsIntRegion paintRegion;
|
||||
if (!textureInited) {
|
||||
paintRegion = nsIntRegion(aDstRegion.GetBounds());
|
||||
} else {
|
||||
paintRegion = aDstRegion;
|
||||
}
|
||||
|
||||
GLenum format;
|
||||
GLenum internalFormat;
|
||||
GLenum type;
|
||||
int32_t pixelSize = gfxASurface::BytePerPixelFromFormat(aFormat);
|
||||
SurfaceFormat surfaceFormat;
|
||||
|
||||
MOZ_ASSERT(gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA ||
|
||||
gl->GetPreferredARGB32Format() == LOCAL_GL_RGBA);
|
||||
switch (aFormat) {
|
||||
case gfxImageFormatARGB32:
|
||||
if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
|
||||
format = LOCAL_GL_BGRA;
|
||||
surfaceFormat = gfx::FORMAT_R8G8B8A8;
|
||||
type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
} else {
|
||||
format = LOCAL_GL_RGBA;
|
||||
surfaceFormat = gfx::FORMAT_B8G8R8A8;
|
||||
type = LOCAL_GL_UNSIGNED_BYTE;
|
||||
}
|
||||
internalFormat = LOCAL_GL_RGBA;
|
||||
break;
|
||||
case gfxImageFormatRGB24:
|
||||
// Treat RGB24 surfaces as RGBA32 except for the surface
|
||||
// format used.
|
||||
if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
|
||||
format = LOCAL_GL_BGRA;
|
||||
surfaceFormat = gfx::FORMAT_R8G8B8X8;
|
||||
type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
} else {
|
||||
format = LOCAL_GL_RGBA;
|
||||
surfaceFormat = gfx::FORMAT_B8G8R8X8;
|
||||
type = LOCAL_GL_UNSIGNED_BYTE;
|
||||
}
|
||||
internalFormat = LOCAL_GL_RGBA;
|
||||
break;
|
||||
case gfxImageFormatRGB16_565:
|
||||
internalFormat = format = LOCAL_GL_RGB;
|
||||
type = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
|
||||
surfaceFormat = gfx::FORMAT_R5G6B5;
|
||||
break;
|
||||
case gfxImageFormatA8:
|
||||
internalFormat = format = LOCAL_GL_LUMINANCE;
|
||||
type = LOCAL_GL_UNSIGNED_BYTE;
|
||||
// We don't have a specific luminance shader
|
||||
surfaceFormat = gfx::FORMAT_A8;
|
||||
break;
|
||||
default:
|
||||
NS_ASSERTION(false, "Unhandled image surface format!");
|
||||
format = 0;
|
||||
type = 0;
|
||||
surfaceFormat = gfx::FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
nsIntRegionRectIterator iter(paintRegion);
|
||||
const nsIntRect *iterRect;
|
||||
|
||||
// Top left point of the region's bounding rectangle.
|
||||
nsIntPoint topLeft = paintRegion.GetBounds().TopLeft();
|
||||
|
||||
while ((iterRect = iter.Next())) {
|
||||
// The inital data pointer is at the top left point of the region's
|
||||
// bounding rectangle. We need to find the offset of this rect
|
||||
// within the region and adjust the data pointer accordingly.
|
||||
unsigned char *rectData =
|
||||
aData + DataOffset(iterRect->TopLeft() - topLeft, aStride, aFormat);
|
||||
|
||||
NS_ASSERTION(textureInited || (iterRect->x == 0 && iterRect->y == 0),
|
||||
"Must be uploading to the origin when we don't have an existing texture");
|
||||
|
||||
if (textureInited && gl->CanUploadSubTextures()) {
|
||||
gl->TexSubImage2D(aTextureTarget,
|
||||
0,
|
||||
iterRect->x,
|
||||
iterRect->y,
|
||||
iterRect->width,
|
||||
iterRect->height,
|
||||
aStride,
|
||||
pixelSize,
|
||||
format,
|
||||
type,
|
||||
rectData);
|
||||
} else {
|
||||
gl->TexImage2D(aTextureTarget,
|
||||
0,
|
||||
internalFormat,
|
||||
iterRect->width,
|
||||
iterRect->height,
|
||||
aStride,
|
||||
pixelSize,
|
||||
0,
|
||||
format,
|
||||
type,
|
||||
rectData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return surfaceFormat;
|
||||
}
|
||||
|
||||
SurfaceFormat
|
||||
UploadSurfaceToTexture(GLContext* gl,
|
||||
gfxASurface *aSurface,
|
||||
const nsIntRegion& aDstRegion,
|
||||
GLuint& aTexture,
|
||||
bool aOverwrite,
|
||||
const nsIntPoint& aSrcPoint,
|
||||
bool aPixelBuffer,
|
||||
GLenum aTextureUnit,
|
||||
GLenum aTextureTarget)
|
||||
{
|
||||
|
||||
nsRefPtr<gfxImageSurface> imageSurface = aSurface->GetAsImageSurface();
|
||||
unsigned char* data = nullptr;
|
||||
|
||||
if (!imageSurface ||
|
||||
(imageSurface->Format() != gfxImageFormatARGB32 &&
|
||||
imageSurface->Format() != gfxImageFormatRGB24 &&
|
||||
imageSurface->Format() != gfxImageFormatRGB16_565 &&
|
||||
imageSurface->Format() != gfxImageFormatA8)) {
|
||||
// We can't get suitable pixel data for the surface, make a copy
|
||||
nsIntRect bounds = aDstRegion.GetBounds();
|
||||
imageSurface =
|
||||
new gfxImageSurface(gfxIntSize(bounds.width, bounds.height),
|
||||
gfxImageFormatARGB32);
|
||||
|
||||
nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
|
||||
|
||||
context->Translate(-gfxPoint(aSrcPoint.x, aSrcPoint.y));
|
||||
context->SetSource(aSurface);
|
||||
context->Paint();
|
||||
data = imageSurface->Data();
|
||||
NS_ASSERTION(!aPixelBuffer,
|
||||
"Must be using an image compatible surface with pixel buffers!");
|
||||
} else {
|
||||
// If a pixel buffer is bound the data pointer parameter is relative
|
||||
// to the start of the data block.
|
||||
if (!aPixelBuffer) {
|
||||
data = imageSurface->Data();
|
||||
}
|
||||
data += DataOffset(aSrcPoint, imageSurface->Stride(),
|
||||
imageSurface->Format());
|
||||
}
|
||||
|
||||
MOZ_ASSERT(imageSurface);
|
||||
imageSurface->Flush();
|
||||
|
||||
return UploadImageDataToTexture(gl,
|
||||
data,
|
||||
imageSurface->Stride(),
|
||||
imageSurface->Format(),
|
||||
aDstRegion, aTexture, aOverwrite,
|
||||
aPixelBuffer, aTextureUnit, aTextureTarget);
|
||||
}
|
||||
|
||||
SurfaceFormat
|
||||
UploadSurfaceToTexture(GLContext* gl,
|
||||
gfx::DataSourceSurface *aSurface,
|
||||
const nsIntRegion& aDstRegion,
|
||||
GLuint& aTexture,
|
||||
bool aOverwrite,
|
||||
const nsIntPoint& aSrcPoint,
|
||||
bool aPixelBuffer,
|
||||
GLenum aTextureUnit,
|
||||
GLenum aTextureTarget)
|
||||
{
|
||||
unsigned char* data = aPixelBuffer ? nullptr : aSurface->GetData();
|
||||
int32_t stride = aSurface->Stride();
|
||||
gfxImageFormat format =
|
||||
ImageFormatForSurfaceFormat(aSurface->GetFormat());
|
||||
data += DataOffset(aSrcPoint, stride, format);
|
||||
return UploadImageDataToTexture(gl, data, stride, format,
|
||||
aDstRegion, aTexture, aOverwrite,
|
||||
aPixelBuffer, aTextureUnit,
|
||||
aTextureTarget);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
101
gfx/gl/GLUploadHelpers.h
Normal file
101
gfx/gl/GLUploadHelpers.h
Normal file
@ -0,0 +1,101 @@
|
||||
/* -*- 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 GLUploadHelpers_h_
|
||||
#define GLUploadHelpers_h_
|
||||
|
||||
#include "GLDefs.h"
|
||||
#include "gfxTypes.h"
|
||||
#include "mozilla/gfx/Types.h"
|
||||
#include "nsPoint.h"
|
||||
|
||||
class gfxASurface;
|
||||
class nsIntRegion;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace gfx {
|
||||
class DataSourceSurface;
|
||||
}
|
||||
|
||||
namespace gl {
|
||||
|
||||
class GLContext;
|
||||
|
||||
/**
|
||||
* Creates a RGB/RGBA texture (or uses one provided) and uploads the surface
|
||||
* contents to it within aSrcRect.
|
||||
*
|
||||
* aSrcRect.x/y will be uploaded to 0/0 in the texture, and the size
|
||||
* of the texture with be aSrcRect.width/height.
|
||||
*
|
||||
* If an existing texture is passed through aTexture, it is assumed it
|
||||
* has already been initialised with glTexImage2D (or this function),
|
||||
* and that its size is equal to or greater than aSrcRect + aDstPoint.
|
||||
* You can alternatively set the overwrite flag to true and have a new
|
||||
* texture memory block allocated.
|
||||
*
|
||||
* The aDstPoint parameter is ignored if no texture was provided
|
||||
* or aOverwrite is true.
|
||||
*
|
||||
* \param aData Image data to upload.
|
||||
* \param aDstRegion Region of texture to upload to.
|
||||
* \param aTexture Texture to use, or 0 to have one created for you.
|
||||
* \param aOverwrite Over an existing texture with a new one.
|
||||
* \param aSrcPoint Offset into aSrc where the region's bound's
|
||||
* TopLeft() sits.
|
||||
* \param aPixelBuffer Pass true to upload texture data with an
|
||||
* offset from the base data (generally for pixel buffer objects),
|
||||
* otherwise textures are upload with an absolute pointer to the data.
|
||||
* \param aTextureUnit, the texture unit used temporarily to upload the
|
||||
* surface. This testure may be overridden, clients should not rely on
|
||||
* the contents of this texture after this call or even on this
|
||||
* texture unit being active.
|
||||
* \return Surface format of this texture.
|
||||
*/
|
||||
gfx::SurfaceFormat
|
||||
UploadImageDataToTexture(GLContext* gl,
|
||||
unsigned char* aData,
|
||||
int32_t aStride,
|
||||
gfxImageFormat aFormat,
|
||||
const nsIntRegion& aDstRegion,
|
||||
GLuint& aTexture,
|
||||
bool aOverwrite = false,
|
||||
bool aPixelBuffer = false,
|
||||
GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
|
||||
GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D);
|
||||
|
||||
/**
|
||||
* Convenience wrapper around UploadImageDataToTexture for gfxASurfaces.
|
||||
*/
|
||||
gfx::SurfaceFormat
|
||||
UploadSurfaceToTexture(GLContext* gl,
|
||||
gfxASurface *aSurface,
|
||||
const nsIntRegion& aDstRegion,
|
||||
GLuint& aTexture,
|
||||
bool aOverwrite = false,
|
||||
const nsIntPoint& aSrcPoint = nsIntPoint(0, 0),
|
||||
bool aPixelBuffer = false,
|
||||
GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
|
||||
GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D);
|
||||
|
||||
/**
|
||||
* Convenience wrapper around UploadImageDataToTexture for gfx::DataSourceSurface's.
|
||||
*/
|
||||
gfx::SurfaceFormat
|
||||
UploadSurfaceToTexture(GLContext* gl,
|
||||
gfx::DataSourceSurface *aSurface,
|
||||
const nsIntRegion& aDstRegion,
|
||||
GLuint& aTexture,
|
||||
bool aOverwrite,
|
||||
const nsIntPoint& aSrcPoint,
|
||||
bool aPixelBuffer,
|
||||
GLenum aTextureUnit,
|
||||
GLenum aTextureTarget);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -6,6 +6,7 @@
|
||||
#include "TextureImageEGL.h"
|
||||
#include "GLLibraryEGL.h"
|
||||
#include "GLContext.h"
|
||||
#include "GLUploadHelpers.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "mozilla/gfx/Types.h"
|
||||
|
||||
@ -215,12 +216,13 @@ TextureImageEGL::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, co
|
||||
}
|
||||
|
||||
mTextureFormat =
|
||||
mGLContext->UploadSurfaceToTexture(aSurf,
|
||||
region,
|
||||
mTexture,
|
||||
mTextureState == Created,
|
||||
bounds.TopLeft() + aFrom,
|
||||
false);
|
||||
UploadSurfaceToTexture(mGLContext,
|
||||
aSurf,
|
||||
region,
|
||||
mTexture,
|
||||
mTextureState == Created,
|
||||
bounds.TopLeft() + aFrom,
|
||||
false);
|
||||
|
||||
mTextureState = Valid;
|
||||
return true;
|
||||
|
@ -44,6 +44,7 @@ EXPORTS += [
|
||||
'GLSharedHandleHelpers.h',
|
||||
'GLTextureImage.h',
|
||||
'GLTypes.h',
|
||||
'GLUploadHelpers.h',
|
||||
'ScopedGLHelpers.h',
|
||||
'SharedSurface.h',
|
||||
'SharedSurfaceEGL.h',
|
||||
@ -120,6 +121,7 @@ UNIFIED_SOURCES += [
|
||||
'GLScreenBuffer.cpp',
|
||||
'GLSharedHandleHelpers.cpp',
|
||||
'GLTextureImage.cpp',
|
||||
'GLUploadHelpers.cpp',
|
||||
'ScopedGLHelpers.cpp',
|
||||
'SharedSurface.cpp',
|
||||
'SharedSurfaceEGL.cpp',
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "TextureHostOGL.h"
|
||||
#include "GLContext.h" // for GLContext, etc
|
||||
#include "GLSharedHandleHelpers.h"
|
||||
#include "GLUploadHelpers.h"
|
||||
#include "GLContextUtils.h" // for GLContextUtils
|
||||
#include "SharedSurface.h" // for SharedSurface
|
||||
#include "SharedSurfaceEGL.h" // for SharedSurface_EGLImage
|
||||
@ -823,10 +824,11 @@ SurfaceStreamHostOGL::Lock()
|
||||
nsIntSize size(toUpload->GetSize());
|
||||
nsIntRect rect(nsIntPoint(0,0), size);
|
||||
nsIntRegion bounds(rect);
|
||||
mFormat = mGL->UploadSurfaceToTexture(toUpload,
|
||||
bounds,
|
||||
mUploadTexture,
|
||||
true);
|
||||
mFormat = UploadSurfaceToTexture(mGL,
|
||||
toUpload,
|
||||
bounds,
|
||||
mUploadTexture,
|
||||
true);
|
||||
mTextureHandle = mUploadTexture;
|
||||
mTextureTarget = LOCAL_GL_TEXTURE_2D;
|
||||
}
|
||||
|
@ -61,6 +61,7 @@
|
||||
#include "GLTextureImage.h"
|
||||
#include "GLContextProvider.h"
|
||||
#include "GLContext.h"
|
||||
#include "GLUploadHelpers.h"
|
||||
#include "mozilla/layers/GLManager.h"
|
||||
#include "mozilla/layers/CompositorCocoaWidgetHelper.h"
|
||||
#include "mozilla/layers/CompositorOGL.h"
|
||||
@ -2634,14 +2635,15 @@ RectTextureImage::EndUpdate(bool aKeepSurface)
|
||||
RefPtr<gfx::SourceSurface> snapshot = mUpdateDrawTarget->Snapshot();
|
||||
RefPtr<gfx::DataSourceSurface> dataSnapshot = snapshot->GetDataSurface();
|
||||
|
||||
mGLContext->UploadSurfaceToTexture(dataSnapshot,
|
||||
updateRegion,
|
||||
mTexture,
|
||||
overwriteTexture,
|
||||
updateRegion.GetBounds().TopLeft(),
|
||||
false,
|
||||
LOCAL_GL_TEXTURE0,
|
||||
LOCAL_GL_TEXTURE_RECTANGLE_ARB);
|
||||
UploadSurfaceToTexture(mGLContext,
|
||||
dataSnapshot,
|
||||
updateRegion,
|
||||
mTexture,
|
||||
overwriteTexture,
|
||||
updateRegion.GetBounds().TopLeft(),
|
||||
false,
|
||||
LOCAL_GL_TEXTURE0,
|
||||
LOCAL_GL_TEXTURE_RECTANGLE_ARB);
|
||||
|
||||
if (!aKeepSurface) {
|
||||
mUpdateDrawTarget = nullptr;
|
||||
|
Loading…
Reference in New Issue
Block a user