Optimize streaming texture updates
This commit is contained in:
parent
c94bfd7c9c
commit
5065405e71
@ -379,6 +379,8 @@ GLenum _glGetCullFace();
|
|||||||
GLenum _glGetFrontFace();
|
GLenum _glGetFrontFace();
|
||||||
GLenum _glGetGpuBlendSrcFactor();
|
GLenum _glGetGpuBlendSrcFactor();
|
||||||
GLenum _glGetGpuBlendDstFactor();
|
GLenum _glGetGpuBlendDstFactor();
|
||||||
|
GLint _glGetUnpackRowLength();
|
||||||
|
GLint _glGetUnpackAlignment();
|
||||||
|
|
||||||
extern PolyList OP_LIST;
|
extern PolyList OP_LIST;
|
||||||
extern PolyList PT_LIST;
|
extern PolyList PT_LIST;
|
||||||
|
|||||||
40
GL/state.c
40
GL/state.c
@ -66,6 +66,9 @@ static struct {
|
|||||||
|
|
||||||
GLfloat half_point_size;
|
GLfloat half_point_size;
|
||||||
GLfloat half_line_width;
|
GLfloat half_line_width;
|
||||||
|
|
||||||
|
GLint unpack_row_length;
|
||||||
|
GLint unpack_alignment;
|
||||||
} GPUState = {
|
} GPUState = {
|
||||||
.is_dirty = GL_TRUE,
|
.is_dirty = GL_TRUE,
|
||||||
.depth_func = GL_LESS,
|
.depth_func = GL_LESS,
|
||||||
@ -102,6 +105,8 @@ static struct {
|
|||||||
.current_tex_coord1 = {0.0f, 0.0f},
|
.current_tex_coord1 = {0.0f, 0.0f},
|
||||||
.half_point_size = 0.5f,
|
.half_point_size = 0.5f,
|
||||||
.half_line_width = 0.5f,
|
.half_line_width = 0.5f,
|
||||||
|
.unpack_row_length = 0,
|
||||||
|
.unpack_alignment = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
float* _glCurrentColor() {
|
float* _glCurrentColor() {
|
||||||
@ -141,6 +146,14 @@ GLboolean _glGPUStateIsDirty() {
|
|||||||
return GPUState.is_dirty;
|
return GPUState.is_dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLint _glGetUnpackRowLength() {
|
||||||
|
return GPUState.unpack_row_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLint _glGetUnpackAlignment() {
|
||||||
|
return GPUState.unpack_alignment;
|
||||||
|
}
|
||||||
|
|
||||||
Material* _glActiveMaterial() {
|
Material* _glActiveMaterial() {
|
||||||
return &GPUState.material;
|
return &GPUState.material;
|
||||||
}
|
}
|
||||||
@ -873,8 +886,25 @@ void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha
|
|||||||
}
|
}
|
||||||
|
|
||||||
void glPixelStorei(GLenum pname, GLint param) {
|
void glPixelStorei(GLenum pname, GLint param) {
|
||||||
_GL_UNUSED(pname);
|
switch(pname) {
|
||||||
_GL_UNUSED(param);
|
case GL_UNPACK_ROW_LENGTH:
|
||||||
|
if(param < 0) {
|
||||||
|
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GPUState.unpack_row_length = param;
|
||||||
|
break;
|
||||||
|
case GL_UNPACK_ALIGNMENT:
|
||||||
|
if(param != 1 && param != 2 && param != 4 && param != 8) {
|
||||||
|
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GPUState.unpack_alignment = param;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1118,6 +1148,12 @@ void APIENTRY glGetIntegerv(GLenum pname, GLint *params) {
|
|||||||
case GL_TEXTURE_INTERNAL_FORMAT_KOS:
|
case GL_TEXTURE_INTERNAL_FORMAT_KOS:
|
||||||
*params = _glGetTextureInternalFormat();
|
*params = _glGetTextureInternalFormat();
|
||||||
break;
|
break;
|
||||||
|
case GL_UNPACK_ROW_LENGTH:
|
||||||
|
*params = GPUState.unpack_row_length;
|
||||||
|
break;
|
||||||
|
case GL_UNPACK_ALIGNMENT:
|
||||||
|
*params = GPUState.unpack_alignment;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||||
|
|||||||
57
GL/texture.c
57
GL/texture.c
@ -1625,6 +1625,15 @@ static inline GLboolean is4BPPFormat(GLenum format) {
|
|||||||
return format == GL_COLOR_INDEX4_EXT || format == GL_COLOR_INDEX4_TWID_KOS;
|
return format == GL_COLOR_INDEX4_EXT || format == GL_COLOR_INDEX4_TWID_KOS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GLuint _glGetUnpackRowPitch(GLsizei width, GLint sourceStride, GLenum format) {
|
||||||
|
GLint rowLength = _glGetUnpackRowLength();
|
||||||
|
GLint unpackAlignment = _glGetUnpackAlignment();
|
||||||
|
GLuint rowPixels = (rowLength > 0) ? (GLuint) rowLength : (GLuint) width;
|
||||||
|
GLuint rowBytes = is4BPPFormat(format) ? ((rowPixels + 1) / 2) : (rowPixels * (GLuint) sourceStride);
|
||||||
|
|
||||||
|
return (rowBytes + (GLuint) unpackAlignment - 1) & ~((GLuint) unpackAlignment - 1);
|
||||||
|
}
|
||||||
|
|
||||||
void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||||
GLsizei width, GLsizei height, GLint border,
|
GLsizei width, GLsizei height, GLint border,
|
||||||
GLenum format, GLenum type, const GLvoid *data) {
|
GLenum format, GLenum type, const GLvoid *data) {
|
||||||
@ -1745,6 +1754,12 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||||||
GLubyte* targetData = (active->baseDataOffset == 0) ? active->data : _glGetMipmapLocation(active, level);
|
GLubyte* targetData = (active->baseDataOffset == 0) ? active->data : _glGetMipmapLocation(active, level);
|
||||||
gl_assert(targetData);
|
gl_assert(targetData);
|
||||||
|
|
||||||
|
if(!data) {
|
||||||
|
gl_assert(active->index == originalId);
|
||||||
|
_glGPUStateMarkDirty();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(needs_conversion < 0) {
|
if(needs_conversion < 0) {
|
||||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||||
INFO_MSG("Couldn't find necessary texture conversion\n");
|
INFO_MSG("Couldn't find necessary texture conversion\n");
|
||||||
@ -2164,18 +2179,19 @@ void APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint y
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLboolean isPaletted = (
|
|
||||||
active->internalFormat == GL_COLOR_INDEX8_EXT ||
|
|
||||||
active->internalFormat == GL_COLOR_INDEX4_EXT ||
|
|
||||||
active->internalFormat == GL_COLOR_INDEX4_TWID_KOS ||
|
|
||||||
active->internalFormat == GL_COLOR_INDEX8_TWID_KOS
|
|
||||||
) ? GL_TRUE : GL_FALSE;
|
|
||||||
|
|
||||||
GLenum cleanInternalFormat = _cleanInternalFormat(active->internalFormat);
|
GLenum cleanInternalFormat = _cleanInternalFormat(active->internalFormat);
|
||||||
|
|
||||||
// Determine source stride
|
// Determine source stride
|
||||||
GLint sourceStride = _determineStride(format, type);
|
GLint sourceStride = _determineStride(format, type);
|
||||||
GLuint srcBytes = (width * height * sourceStride);
|
if (sourceStride < 0) {
|
||||||
|
INFO_MSG("Stride was not detected\n");
|
||||||
|
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint sourceRowWidth = is4BPPFormat(format) ? (((GLuint) width + 1) / 2) : ((GLuint) width * (GLuint) sourceStride);
|
||||||
|
GLuint sourcePitch = _glGetUnpackRowPitch(width, sourceStride, format);
|
||||||
|
GLuint srcBytes = height ? (sourcePitch * ((GLuint) height - 1) + sourceRowWidth) : 0;
|
||||||
|
|
||||||
// Calculate destination stride (this accounts for both POT and NPOT)
|
// Calculate destination stride (this accounts for both POT and NPOT)
|
||||||
GLint destStride = _determineStrideInternal(cleanInternalFormat);
|
GLint destStride = _determineStrideInternal(cleanInternalFormat);
|
||||||
@ -2220,6 +2236,7 @@ void APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint y
|
|||||||
}
|
}
|
||||||
if (needs_conversion == CONVERSION_TYPE_CONVERT) {
|
if (needs_conversion == CONVERSION_TYPE_CONVERT) {
|
||||||
for (uint32_t y = 0; y < height; ++y) {
|
for (uint32_t y = 0; y < height; ++y) {
|
||||||
|
src = (const GLubyte*) data + (y * sourcePitch);
|
||||||
dst = conversionBuffer + ((y + yoffset) * textureWidth + xoffset) * destStride;
|
dst = conversionBuffer + ((y + yoffset) * textureWidth + xoffset) * destStride;
|
||||||
for (uint32_t x = 0; x < width; ++x) {
|
for (uint32_t x = 0; x < width; ++x) {
|
||||||
conversion(src, dst);
|
conversion(src, dst);
|
||||||
@ -2233,21 +2250,24 @@ void APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint y
|
|||||||
|
|
||||||
for (uint32_t y = yoffset; y < yoffset + height; ++y) {
|
for (uint32_t y = yoffset; y < yoffset + height; ++y) {
|
||||||
for (uint32_t x = xoffset; x < xoffset + width; ++x) {
|
for (uint32_t x = xoffset; x < xoffset + width; ++x) {
|
||||||
uint32_t srcIndex = (y - yoffset) * width + (x - xoffset);
|
|
||||||
uint32_t newLocation = twid_compute_index(x, y, maskX, maskY);
|
uint32_t newLocation = twid_compute_index(x, y, maskX, maskY);
|
||||||
dst = conversionBuffer + (destStride * newLocation);
|
dst = conversionBuffer + (destStride * newLocation);
|
||||||
|
src = (const GLubyte*) data + ((y - yoffset) * sourcePitch) + ((x - xoffset) * sourceStride);
|
||||||
|
|
||||||
if (needs_conversion == 3) {
|
if (needs_conversion == 3) {
|
||||||
conversion(src + srcIndex * sourceStride, dst);
|
conversion(src, dst);
|
||||||
} else {
|
} else {
|
||||||
memcpy(dst, src + srcIndex * sourceStride, destStride);
|
memcpy(dst, src, destStride);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pack) {
|
if (pack) {
|
||||||
assert(isPaletted);
|
assert(active->internalFormat == GL_COLOR_INDEX8_EXT ||
|
||||||
|
active->internalFormat == GL_COLOR_INDEX4_EXT ||
|
||||||
|
active->internalFormat == GL_COLOR_INDEX4_TWID_KOS ||
|
||||||
|
active->internalFormat == GL_COLOR_INDEX8_TWID_KOS);
|
||||||
size_t dst_byte = 0;
|
size_t dst_byte = 0;
|
||||||
for (size_t src_byte = 0; src_byte < destBytes; ++src_byte) {
|
for (size_t src_byte = 0; src_byte < destBytes; ++src_byte) {
|
||||||
uint8_t v = conversionBuffer[src_byte];
|
uint8_t v = conversionBuffer[src_byte];
|
||||||
@ -2267,10 +2287,19 @@ void APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint y
|
|||||||
free(conversionBuffer);
|
free(conversionBuffer);
|
||||||
} else {
|
} else {
|
||||||
// No conversion necessary, we can update data directly
|
// No conversion necessary, we can update data directly
|
||||||
|
if (xoffset == 0 &&
|
||||||
|
yoffset == 0 &&
|
||||||
|
width == textureWidth &&
|
||||||
|
sourceStride == destStride &&
|
||||||
|
sourcePitch == textureWidth * destStride) {
|
||||||
|
FASTCPY(targetData, data, height * sourcePitch);
|
||||||
|
_glGPUStateMarkDirty();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (GLsizei y = 0; y < height; ++y) {
|
for (GLsizei y = 0; y < height; ++y) {
|
||||||
GLsizei srcRowWidth = width * sourceStride;
|
|
||||||
GLubyte* destRow = targetData + ((y + yoffset) * textureWidth + xoffset) * destStride;
|
GLubyte* destRow = targetData + ((y + yoffset) * textureWidth + xoffset) * destStride;
|
||||||
FASTCPY(destRow, (GLubyte*)data + y * srcRowWidth, srcRowWidth);
|
FASTCPY(destRow, (GLubyte*)data + y * sourcePitch, sourceRowWidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user