Bug 1324312 - Handle alloc failure when uploading texture. r=sotaro

When GL_UNPACK_ROW_LENGTH is not supported and the source data has a
different stride to that of the texture (often because we are
uploading only the modified subimage) we allocate a temporary buffer
with the correct stride. This was found to be more efficient than
uploading each row of texture data individually.

Sometimes allocating the buffer will fail, however. In such cases fall
back to uploading the texture row-by-row, rather than aborting.

MozReview-Commit-ID: E7LE8nHPE0M

--HG--
extra : rebase_source : 5f6ddcb617d9f4730ce864722ee06f2f7c3b850e
This commit is contained in:
Jamie Nicol 2017-01-23 20:00:05 +00:00
Родитель 673d193089
Коммит e92d2ce49b
1 изменённых файлов: 42 добавлений и 20 удалений

Просмотреть файл

@ -161,30 +161,52 @@ TexSubImage2DWithoutUnpackSubimage(GLContext* gl,
// isn't supported. We make a copy of the texture data we're using, // isn't supported. We make a copy of the texture data we're using,
// such that we're using the whole row of data in the copy. This turns // such that we're using the whole row of data in the copy. This turns
// out to be more efficient than uploading row-by-row; see bug 698197. // out to be more efficient than uploading row-by-row; see bug 698197.
unsigned char* newPixels = new unsigned char[width*height*pixelsize]; unsigned char* newPixels = new (fallible) unsigned char[width*height*pixelsize];
unsigned char* rowDest = newPixels;
const unsigned char* rowSource = (const unsigned char*)pixels; if (newPixels) {
for (int h = 0; h < height; h++) { unsigned char* rowDest = newPixels;
const unsigned char* rowSource = (const unsigned char*)pixels;
for (int h = 0; h < height; h++) {
memcpy(rowDest, rowSource, width*pixelsize); memcpy(rowDest, rowSource, width*pixelsize);
rowDest += width*pixelsize; rowDest += width*pixelsize;
rowSource += stride; rowSource += stride;
} }
stride = width*pixelsize; stride = width*pixelsize;
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
std::min(GetAddressAlignment((ptrdiff_t)newPixels), std::min(GetAddressAlignment((ptrdiff_t)newPixels),
GetAddressAlignment((ptrdiff_t)stride))); GetAddressAlignment((ptrdiff_t)stride)));
gl->fTexSubImage2D(target, gl->fTexSubImage2D(target,
level, level,
xoffset, xoffset,
yoffset, yoffset,
width, width,
height, height,
format, format,
type, type,
newPixels); newPixels);
delete [] newPixels; delete [] newPixels;
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4); gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
} else {
// If we did not have sufficient memory for the required
// temporary buffer, then fall back to uploading row-by-row.
const unsigned char* rowSource = (const unsigned char*)pixels;
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
std::min(GetAddressAlignment((ptrdiff_t)pixels),
GetAddressAlignment((ptrdiff_t)stride)));
for (int i = 0; i < height; i++) {
gl->fTexSubImage2D(target, level,
xoffset, yoffset + i,
width, 1,
format, type, rowSource);
rowSource += stride;
}
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
}
} }
static void static void