mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 859608 - Flush GL on overdraw on Tegra devices. - r=bjacob
This commit is contained in:
parent
e32f79e41c
commit
717900bdd3
@ -158,7 +158,7 @@ WebGLContext::WebGLContext()
|
||||
|
||||
mScissorTestEnabled = 0;
|
||||
mDitherEnabled = 1;
|
||||
|
||||
|
||||
// initialize some GL values: we're going to get them from the GL and use them as the sizes of arrays,
|
||||
// so in case glGetIntegerv leaves them uninitialized because of a GL bug, we would have very weird crashes.
|
||||
mGLMaxVertexAttribs = 0;
|
||||
@ -198,6 +198,8 @@ WebGLContext::WebGLContext()
|
||||
mIsScreenCleared = false;
|
||||
|
||||
mDisableFragHighP = false;
|
||||
|
||||
mDrawCallsSinceLastFlush = 0;
|
||||
}
|
||||
|
||||
WebGLContext::~WebGLContext()
|
||||
@ -520,12 +522,12 @@ WebGLContext::SetDimensions(int32_t width, int32_t height)
|
||||
|
||||
// try the default provider, whatever that is
|
||||
if (!gl && useOpenGL) {
|
||||
GLContext::ContextFlags flag = useMesaLlvmPipe
|
||||
GLContext::ContextFlags flag = useMesaLlvmPipe
|
||||
? GLContext::ContextFlagsMesaLLVMPipe
|
||||
: GLContext::ContextFlagsNone;
|
||||
gl = gl::GLContextProvider::CreateOffscreen(size, caps, flag);
|
||||
if (gl && !InitAndValidateGL()) {
|
||||
GenerateWarning("Error during %s initialization",
|
||||
GenerateWarning("Error during %s initialization",
|
||||
useMesaLlvmPipe ? "Mesa LLVMpipe" : "OpenGL");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -806,6 +808,7 @@ public:
|
||||
|
||||
// Present our screenbuffer, if needed.
|
||||
context->PresentScreenBuffer();
|
||||
context->mDrawCallsSinceLastFlush = 0;
|
||||
}
|
||||
|
||||
/** DidTransactionCallback gets called by the Layers code everytime the WebGL canvas gets composite,
|
||||
@ -975,9 +978,9 @@ bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) con
|
||||
case WEBGL_compressed_texture_pvrtc:
|
||||
return gl->IsExtensionSupported(GLContext::IMG_texture_compression_pvrtc);
|
||||
case WEBGL_depth_texture:
|
||||
if (gl->IsGLES2() &&
|
||||
if (gl->IsGLES2() &&
|
||||
gl->IsExtensionSupported(GLContext::OES_packed_depth_stencil) &&
|
||||
gl->IsExtensionSupported(GLContext::OES_depth_texture))
|
||||
gl->IsExtensionSupported(GLContext::OES_depth_texture))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -1389,7 +1392,7 @@ WebGLContext::MaybeRestoreContext()
|
||||
resetStatus = GLContext::CONTEXT_GUILTY_CONTEXT_RESET_ARB;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (resetStatus != GLContext::CONTEXT_NO_ERROR) {
|
||||
// It's already lost, but clean up after it and signal to JS that it is
|
||||
// lost.
|
||||
|
@ -1128,6 +1128,10 @@ protected:
|
||||
ContextStatus mContextStatus;
|
||||
bool mContextLostErrorSet;
|
||||
|
||||
// Used for some hardware (particularly Tegra 2 and 4) that likes to
|
||||
// be Flushed while doing hundreds of draw calls.
|
||||
int mDrawCallsSinceLastFlush;
|
||||
|
||||
int mAlreadyGeneratedWarnings;
|
||||
bool mAlreadyWarnedAboutFakeVertexAttrib0;
|
||||
|
||||
|
@ -38,6 +38,9 @@ using namespace mozilla::dom;
|
||||
static bool BaseTypeAndSizeFromUniformType(WebGLenum uType, WebGLenum *baseType, WebGLint *unitSize);
|
||||
static WebGLenum InternalFormatForFormatAndType(WebGLenum format, WebGLenum type, bool isGLES2);
|
||||
|
||||
// For a Tegra workaround.
|
||||
static const int MAX_DRAW_CALLS_SINCE_FLUSH = 100;
|
||||
|
||||
//
|
||||
// WebGL API
|
||||
//
|
||||
@ -1477,6 +1480,17 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
|
||||
mShouldPresent = true;
|
||||
mIsScreenCleared = false;
|
||||
}
|
||||
|
||||
if (gl->WorkAroundDriverBugs()) {
|
||||
if (gl->Renderer() == gl::GLContext::RendererTegra) {
|
||||
mDrawCallsSinceLastFlush++;
|
||||
|
||||
if (mDrawCallsSinceLastFlush >= MAX_DRAW_CALLS_SINCE_FLUSH) {
|
||||
gl->fFlush();
|
||||
mDrawCallsSinceLastFlush = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -1576,6 +1590,17 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
|
||||
mShouldPresent = true;
|
||||
mIsScreenCleared = false;
|
||||
}
|
||||
|
||||
if (gl->WorkAroundDriverBugs()) {
|
||||
if (gl->Renderer() == gl::GLContext::RendererTegra) {
|
||||
mDrawCallsSinceLastFlush++;
|
||||
|
||||
if (mDrawCallsSinceLastFlush >= MAX_DRAW_CALLS_SINCE_FLUSH) {
|
||||
gl->fFlush();
|
||||
mDrawCallsSinceLastFlush = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -355,7 +355,8 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
||||
"Adreno (TM) 205",
|
||||
"Adreno (TM) 320",
|
||||
"PowerVR SGX 530",
|
||||
"PowerVR SGX 540"
|
||||
"PowerVR SGX 540",
|
||||
"NVIDIA Tegra"
|
||||
};
|
||||
|
||||
mRenderer = RendererOther;
|
||||
@ -534,7 +535,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
||||
mSymbols.fEGLImageTargetRenderbufferStorage = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Load developer symbols, don't fail if we can't find them.
|
||||
SymLoadStruct auxSymbols[] = {
|
||||
{ (PRFuncPtr*) &mSymbols.fGetTexImage, { "GetTexImage", nullptr } },
|
||||
@ -779,10 +780,10 @@ GLContext::ListHasExtension(const GLubyte *extensions, const char *extension)
|
||||
if (where || *extension == '\0')
|
||||
return false;
|
||||
|
||||
/*
|
||||
/*
|
||||
* It takes a bit of care to be fool-proof about parsing the
|
||||
* OpenGL extensions string. Don't be fooled by sub-strings,
|
||||
* etc.
|
||||
* etc.
|
||||
*/
|
||||
start = extensions;
|
||||
for (;;) {
|
||||
@ -1385,7 +1386,7 @@ GLContext::GetTexImage(GLuint aTexture, bool aYInvert, ShaderProgramType aShader
|
||||
gfxIntSize size;
|
||||
fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_WIDTH, &size.width);
|
||||
fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_HEIGHT, &size.height);
|
||||
|
||||
|
||||
nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(size, gfxASurface::ImageFormatARGB32);
|
||||
if (!surf || surf->CairoStatus()) {
|
||||
return NULL;
|
||||
@ -1400,7 +1401,7 @@ GLContext::GetTexImage(GLuint aTexture, bool aYInvert, ShaderProgramType aShader
|
||||
if (currentPackAlignment != 4) {
|
||||
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
|
||||
}
|
||||
|
||||
|
||||
if (aShader == RGBALayerProgramType || aShader == RGBXLayerProgramType) {
|
||||
SwapRAndBComponents(surf);
|
||||
}
|
||||
@ -1838,8 +1839,8 @@ GLContext::BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect,
|
||||
if (srcSubRect.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// We now have the intersection of
|
||||
// the current source tile
|
||||
// We now have the intersection of
|
||||
// the current source tile
|
||||
// and the desired source rectangle
|
||||
// and the destination tile
|
||||
// and the desired destination rectange
|
||||
@ -1922,7 +1923,7 @@ GLContext::BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect,
|
||||
fEnable(LOCAL_GL_BLEND);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
static unsigned int
|
||||
DataOffset(gfxImageSurface *aSurf, const nsIntPoint &aPoint)
|
||||
{
|
||||
unsigned int data = aPoint.y * aSurf->Stride();
|
||||
@ -1930,8 +1931,8 @@ DataOffset(gfxImageSurface *aSurf, const nsIntPoint &aPoint)
|
||||
return data;
|
||||
}
|
||||
|
||||
ShaderProgramType
|
||||
GLContext::UploadSurfaceToTexture(gfxASurface *aSurface,
|
||||
ShaderProgramType
|
||||
GLContext::UploadSurfaceToTexture(gfxASurface *aSurface,
|
||||
const nsIntRegion& aDstRegion,
|
||||
GLuint& aTexture,
|
||||
bool aOverwrite,
|
||||
@ -1942,21 +1943,21 @@ GLContext::UploadSurfaceToTexture(gfxASurface *aSurface,
|
||||
bool textureInited = aOverwrite ? false : true;
|
||||
MakeCurrent();
|
||||
fActiveTexture(aTextureUnit);
|
||||
|
||||
|
||||
if (!aTexture) {
|
||||
fGenTextures(1, &aTexture);
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D,
|
||||
LOCAL_GL_TEXTURE_MIN_FILTER,
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D,
|
||||
LOCAL_GL_TEXTURE_MIN_FILTER,
|
||||
LOCAL_GL_LINEAR);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D,
|
||||
LOCAL_GL_TEXTURE_MAG_FILTER,
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D,
|
||||
LOCAL_GL_TEXTURE_MAG_FILTER,
|
||||
LOCAL_GL_LINEAR);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D,
|
||||
LOCAL_GL_TEXTURE_WRAP_S,
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D,
|
||||
LOCAL_GL_TEXTURE_WRAP_S,
|
||||
LOCAL_GL_CLAMP_TO_EDGE);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D,
|
||||
LOCAL_GL_TEXTURE_WRAP_T,
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D,
|
||||
LOCAL_GL_TEXTURE_WRAP_T,
|
||||
LOCAL_GL_CLAMP_TO_EDGE);
|
||||
textureInited = false;
|
||||
} else {
|
||||
@ -1973,17 +1974,17 @@ GLContext::UploadSurfaceToTexture(gfxASurface *aSurface,
|
||||
nsRefPtr<gfxImageSurface> imageSurface = aSurface->GetAsImageSurface();
|
||||
unsigned char* data = NULL;
|
||||
|
||||
if (!imageSurface ||
|
||||
if (!imageSurface ||
|
||||
(imageSurface->Format() != gfxASurface::ImageFormatARGB32 &&
|
||||
imageSurface->Format() != gfxASurface::ImageFormatRGB24 &&
|
||||
imageSurface->Format() != gfxASurface::ImageFormatRGB16_565 &&
|
||||
imageSurface->Format() != gfxASurface::ImageFormatA8)) {
|
||||
// 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),
|
||||
imageSurface =
|
||||
new gfxImageSurface(gfxIntSize(bounds.width, bounds.height),
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
|
||||
|
||||
nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
|
||||
|
||||
context->Translate(-gfxPoint(aSrcPoint.x, aSrcPoint.y));
|
||||
@ -2052,10 +2053,10 @@ GLContext::UploadSurfaceToTexture(gfxASurface *aSurface,
|
||||
// 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 =
|
||||
unsigned char *rectData =
|
||||
data + DataOffset(imageSurface, iterRect->TopLeft() - topLeft);
|
||||
|
||||
NS_ASSERTION(textureInited || (iterRect->x == 0 && iterRect->y == 0),
|
||||
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()) {
|
||||
@ -2545,7 +2546,7 @@ GLContext::UseBlitProgram()
|
||||
shaders[0] = fCreateShader(LOCAL_GL_VERTEX_SHADER);
|
||||
shaders[1] = fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
|
||||
|
||||
const char *blitVSSrc =
|
||||
const char *blitVSSrc =
|
||||
"attribute vec2 aVertex;"
|
||||
"attribute vec2 aTexCoord;"
|
||||
"varying vec2 vTexCoord;"
|
||||
|
@ -262,7 +262,7 @@ public:
|
||||
bool IsGLES2() const {
|
||||
return mIsGLES2;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if either this is the GLES2 API, or had the GL_ARB_ES2_compatibility extension
|
||||
*/
|
||||
@ -301,6 +301,7 @@ public:
|
||||
RendererAdrenoTM320,
|
||||
RendererSGX530,
|
||||
RendererSGX540,
|
||||
RendererTegra,
|
||||
RendererOther
|
||||
};
|
||||
|
||||
@ -859,14 +860,14 @@ public:
|
||||
* The aDstPoint parameter is ignored if no texture was provided
|
||||
* or aOverwrite is true.
|
||||
*
|
||||
* \param aSurface Surface to upload.
|
||||
* \param aSurface Surface 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
|
||||
* \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),
|
||||
* 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
|
||||
@ -874,7 +875,7 @@ public:
|
||||
* texture unit being active.
|
||||
* \return Shader program needed to render this texture.
|
||||
*/
|
||||
ShaderProgramType UploadSurfaceToTexture(gfxASurface *aSurface,
|
||||
ShaderProgramType UploadSurfaceToTexture(gfxASurface *aSurface,
|
||||
const nsIntRegion& aDstRegion,
|
||||
GLuint& aTexture,
|
||||
bool aOverwrite = false,
|
||||
@ -882,16 +883,16 @@ public:
|
||||
bool aPixelBuffer = false,
|
||||
GLenum aTextureUnit = LOCAL_GL_TEXTURE0);
|
||||
|
||||
|
||||
void TexImage2D(GLenum target, GLint level, GLint internalformat,
|
||||
|
||||
void TexImage2D(GLenum target, GLint level, GLint internalformat,
|
||||
GLsizei width, GLsizei height, GLsizei stride,
|
||||
GLint pixelsize, GLint border, GLenum format,
|
||||
GLint pixelsize, GLint border, GLenum format,
|
||||
GLenum type, const GLvoid *pixels);
|
||||
|
||||
void TexSubImage2D(GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset,
|
||||
void TexSubImage2D(GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset,
|
||||
GLsizei width, GLsizei height, GLsizei stride,
|
||||
GLint pixelsize, GLenum format,
|
||||
GLint pixelsize, GLenum format,
|
||||
GLenum type, const GLvoid* pixels);
|
||||
|
||||
/**
|
||||
@ -1399,19 +1400,19 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/** \returns the first GL error, and guarantees that all GL error flags are cleared,
|
||||
* i.e. that a subsequent GetError call will return NO_ERROR
|
||||
*/
|
||||
GLenum GetAndClearError() {
|
||||
// the first error is what we want to return
|
||||
GLenum error = fGetError();
|
||||
|
||||
|
||||
if (error) {
|
||||
// clear all pending errors
|
||||
while(fGetError()) {}
|
||||
}
|
||||
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -1460,7 +1461,7 @@ public:
|
||||
if (DebugMode() & DebugTrace)
|
||||
printf_stderr("[gl:%p] < %s [0x%04x]\n", this, glFunction, mGLError);
|
||||
if (mGLError != LOCAL_GL_NO_ERROR) {
|
||||
printf_stderr("GL ERROR: %s generated GL error %s(0x%04x)\n",
|
||||
printf_stderr("GL ERROR: %s generated GL error %s(0x%04x)\n",
|
||||
glFunction,
|
||||
GLErrorToString(mGLError),
|
||||
mGLError);
|
||||
@ -1497,7 +1498,7 @@ public:
|
||||
#define BEFORE_GL_CALL do { \
|
||||
BeforeGLCall(MOZ_FUNCTION_NAME); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define AFTER_GL_CALL do { \
|
||||
AfterGLCall(MOZ_FUNCTION_NAME); \
|
||||
} while (0)
|
||||
@ -1591,7 +1592,7 @@ private:
|
||||
// we use viewport instead and assume viewport size matches the
|
||||
// destination. If we ever try use partial viewports for layers we need
|
||||
// to fix this, and remove the assertion.
|
||||
NS_ASSERTION(!mFlipped || (x == 0 && y == 0), "TODO: Need to flip the viewport rect");
|
||||
NS_ASSERTION(!mFlipped || (x == 0 && y == 0), "TODO: Need to flip the viewport rect");
|
||||
mSymbols.fViewport(x, y, width, height);
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
@ -1985,7 +1986,7 @@ public:
|
||||
}
|
||||
|
||||
void fGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params)
|
||||
{
|
||||
{
|
||||
BEFORE_GL_CALL;
|
||||
ASSERT_SYMBOL_PRESENT(fGetTexLevelParameteriv);
|
||||
mSymbols.fGetTexLevelParameteriv(target, level, pname, params);
|
||||
|
Loading…
Reference in New Issue
Block a user