<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Jun 13, 2014 at 5:59 PM, Neil Roberts <span dir="ltr"><<a href="mailto:neil@linux.intel.com" target="_blank">neil@linux.intel.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This adds the driver entry point for glClearTexSubImage and fills in the<br>
_mesa_ClearTexImage and _mesa_ClearTexSubImage functions that call it.<br>
---<br>
src/mesa/main/dd.h | 14 +++<br>
src/mesa/main/teximage.c | 241 ++++++++++++++++++++++++++++++++++++++++++++++-<br>
src/mesa/main/teximage.h | 12 +++<br>
3 files changed, 266 insertions(+), 1 deletion(-)<br>
<br>
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h<br>
index 633ea2c..8976535 100644<br>
--- a/src/mesa/main/dd.h<br>
+++ b/src/mesa/main/dd.h<br>
@@ -239,6 +239,20 @@ struct dd_function_table {<br>
struct gl_texture_image *texImage );<br>
<br>
/**<br>
+ * Called by glClearTex[Sub]Image<br>
+ *<br>
+ * Clears a rectangular region of the image to a given value. The<br>
+ * clearValue argument is either NULL or points to a single texel to use as<br>
+ * the clear value in the same internal format as the texture image. If it<br>
+ * is NULL then the texture should be cleared to zeroes.<br>
+ */<br>
+ void (*ClearTexSubImage)(struct gl_context *ctx,<br>
+ struct gl_texture_image *texImage,<br>
+ GLint xoffset, GLint yoffset, GLint zoffset,<br>
+ GLsizei width, GLsizei height, GLsizei depth,<br>
+ const GLvoid *clearValue);<br>
+<br>
+ /**<br>
* Called by glCopyTex[Sub]Image[123]D().<br>
*<br>
* This function should copy a rectangular region in the rb to a single<br>
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c<br>
index a893c70..d5baac8 100644<br>
--- a/src/mesa/main/teximage.c<br>
+++ b/src/mesa/main/teximage.c<br>
@@ -51,6 +51,7 @@<br>
#include "textureview.h"<br>
#include "mtypes.h"<br>
#include "glformats.h"<br>
+#include "texstore.h"<br>
<br>
<br>
/**<br>
@@ -3848,20 +3849,259 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level,<br>
x, y, width, height);<br>
}<br>
<br>
+static bool<br>
+clear_tex_image(struct gl_context *ctx,<br>
+ const char *function,<br>
+ struct gl_texture_image *texImage, GLint level,<br>
+ GLint xoffset, GLint yoffset, GLint zoffset,<br>
+ GLsizei width, GLsizei height, GLsizei depth,<br>
+ GLenum format, GLenum type,<br>
+ const void *data)<br>
+{<br>
+ struct gl_texture_object *texObj = texImage->TexObject;<br>
+ static const GLubyte zeroData[MAX_PIXEL_BYTES];<br>
+ GLubyte clearValue[MAX_PIXEL_BYTES];<br>
+ GLubyte *clearValuePtr = clearValue;<br>
+ GLenum internalFormat = texImage->InternalFormat;<br>
+ GLenum err;<br>
+<br>
+ if (texObj->Target == GL_TEXTURE_BUFFER) {<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+ "%s(buffer texture)", function);<br>
+ return false;<br>
+ }<br>
+<br>
+ if (_mesa_is_compressed_format(ctx, internalFormat)) {<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+ "%s(compressed texture)", function);<br>
+ return false;<br>
+ }<br>
+<br>
+ err = _mesa_error_check_format_and_type(ctx, format, type);<br>
+ if (err != GL_NO_ERROR) {<br>
+ _mesa_error(ctx, err,<br>
+ "%s(incompatible format = %s, type = %s)",<br>
+ function,<br>
+ _mesa_lookup_enum_by_nr(format),<br>
+ _mesa_lookup_enum_by_nr(type));<br>
+ return false;<br>
+ }<br>
+<br>
+ /* make sure internal format and format basically agree */<br>
+ if (!texture_formats_agree(internalFormat, format)) {<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+ "%s(incompatible internalFormat = %s, format = %s)",<br>
+ function,<br>
+ _mesa_lookup_enum_by_nr(internalFormat),<br>
+ _mesa_lookup_enum_by_nr(format));<br>
+ return false;<br>
+ }<br>
+<br>
+ if (ctx->Version >= 30 || ctx->Extensions.EXT_texture_integer) {<br>
+ /* both source and dest must be integer-valued, or neither */<br>
+ if (_mesa_is_format_integer_color(texImage->TexFormat) !=<br>
+ _mesa_is_enum_format_integer(format)) {<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+ "%s(integer/non-integer format mismatch)",<br>
+ function);<br>
+ return false;<br>
+ }<br>
+ }<br>
+<br>
+ if (!_mesa_texstore(ctx,<br>
+ 1, /* dims */<br>
+ texImage->_BaseFormat,<br>
+ texImage->TexFormat,<br>
+ 0, /* dstRowStride */<br>
+ &clearValuePtr,<br>
+ 1, 1, 1, /* srcWidth/Height/Depth */<br>
+ format, type,<br>
+ data ? data : zeroData,<br>
+ &ctx->DefaultPacking)) {<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid format)", function);<br>
+ return false;<br>
+ }<br>
+<br>
+ ctx->Driver.ClearTexSubImage(ctx,<br>
+ texImage,<br>
+ xoffset, yoffset, zoffset,<br>
+ width, height, depth,<br>
+ data ? clearValue : NULL);<br>
+<br>
+ return true;<br>
+}<br>
+<br>
+static struct gl_texture_object *<br>
+get_tex_obj_for_clear(struct gl_context *ctx,<br>
+ const char *function,<br>
+ GLuint texture)<br>
+{<br>
+ struct gl_texture_object *texObj;<br>
+<br>
+ if (texture == 0) {<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(zero texture)", function);<br>
+ return NULL;<br>
+ }<br>
+<br>
+ texObj = _mesa_lookup_texture(ctx, texture);<br>
+<br>
+ if (texObj == NULL) {<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", function);<br>
+ return NULL;<br>
+ }<br>
+<br>
+ if (texObj->Target == 0) {<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unbound tex)", function);<br>
+ return NULL;<br>
+ }<br>
+<br>
+ return texObj;<br>
+}<br>
+<br>
+static int<br>
+get_tex_images_for_clear(struct gl_context *ctx,<br>
+ const char *function,<br>
+ struct gl_texture_object *texObj,<br>
+ GLint level,<br>
+ struct gl_texture_image **texImages)<br>
+{<br>
+ GLenum target;<br>
+ int i;<br>
+<br>
+ if (level < 0 || level >= MAX_TEXTURE_LEVELS) {<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid level)", function);<br>
+ return 0;<br>
+ }<br>
+<br>
+ if (texObj->Target == GL_TEXTURE_CUBE_MAP) {<br>
+ for (i = 0; i < MAX_FACES; i++) {<br>
+ target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;<br>
+<br>
+ texImages[i] = _mesa_select_tex_image(ctx, texObj, target, level);<br>
+ if (texImages[i] == NULL) {<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+ "%s(invalid level)", function);<br>
+ return 0;<br>
+ }<br>
+ }<br>
+<br>
+ return MAX_FACES;<br>
+ }<br>
+<br>
+ texImages[0] = _mesa_select_tex_image(ctx, texObj, texObj->Target, level);<br></blockquote><div><br></div><div>Do you want this inside an else block?<br><br></div><div>Other than that, looks good to me.<br></div><div>
--Jason Ekstrand<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+ if (texImages[0] == NULL) {<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid level)", function);<br>
+ return 0;<br>
+ }<br>
+<br>
+ return 1;<br>
+}<br>
+<br>
void GLAPIENTRY<br>
_mesa_ClearTexSubImage( GLuint texture, GLint level,<br>
GLint xoffset, GLint yoffset, GLint zoffset,<br>
GLsizei width, GLsizei height, GLsizei depth,<br>
GLenum format, GLenum type, const void *data )<br>
{<br>
+ GET_CURRENT_CONTEXT(ctx);<br>
+ struct gl_texture_object *texObj;<br>
+ struct gl_texture_image *texImages[MAX_FACES];<br>
+ int i, numImages;<br>
+ int minDepth, maxDepth;<br>
+ bool res;<br>
<br>
+ texObj = get_tex_obj_for_clear(ctx, "glClearTexSubImage", texture);<br>
+<br>
+ if (texObj == NULL)<br>
+ return;<br>
+<br>
+ _mesa_lock_texture(ctx, texObj);<br>
+<br>
+ numImages = get_tex_images_for_clear(ctx, "glClearTexSubImage",<br>
+ texObj, level, texImages);<br>
+ if (numImages == 0)<br>
+ goto out;<br>
+<br>
+ if (numImages == 1) {<br>
+ minDepth = -(int) texImages[0]->Border;<br>
+ maxDepth = texImages[0]->Depth;<br>
+ } else {<br>
+ minDepth = 0;<br>
+ maxDepth = numImages;<br>
+ }<br>
+<br>
+ if (xoffset < -(GLint) texImages[0]->Border ||<br>
+ yoffset < -(GLint) texImages[0]->Border ||<br>
+ zoffset < minDepth ||<br>
+ width < 0 ||<br>
+ height < 0 ||<br>
+ depth < 0 ||<br>
+ xoffset + width > texImages[0]->Width ||<br>
+ yoffset + height > texImages[0]->Height ||<br>
+ zoffset + depth > maxDepth) {<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+ "glClearSubTexImage(invalid dimensions)");<br>
+ goto out;<br>
+ }<br>
+<br>
+ if (numImages == 1) {<br>
+ clear_tex_image(ctx, "glClearTexSubImage",<br>
+ texImages[0], level,<br>
+ xoffset, yoffset, zoffset,<br>
+ width, height, depth,<br>
+ format, type, data);<br>
+ } else {<br>
+ for (i = zoffset; i < zoffset + depth; i++) {<br>
+ res = clear_tex_image(ctx, "glClearTexSubImage",<br>
+ texImages[i], level,<br>
+ xoffset, yoffset, 0,<br>
+ width, height, 1,<br>
+ format, type, data);<br>
+ if (!res)<br>
+ break;<br>
+ }<br>
+ }<br>
+<br>
+ out:<br>
+ _mesa_unlock_texture(ctx, texObj);<br>
}<br>
<br>
void GLAPIENTRY<br>
_mesa_ClearTexImage( GLuint texture, GLint level,<br>
GLenum format, GLenum type, const void *data )<br>
{<br>
+ GET_CURRENT_CONTEXT(ctx);<br>
+ struct gl_texture_object *texObj;<br>
+ struct gl_texture_image *texImages[MAX_FACES];<br>
+ int i, numImages;<br>
+ bool res;<br>
+<br>
+ texObj = get_tex_obj_for_clear(ctx, "glClearTexImage", texture);<br>
<br>
+ if (texObj == NULL)<br>
+ return;<br>
+<br>
+ _mesa_lock_texture(ctx, texObj);<br>
+<br>
+ numImages = get_tex_images_for_clear(ctx, "glClearTexImage",<br>
+ texObj, level, texImages);<br>
+<br>
+ for (i = 0; i < numImages; i++) {<br>
+ res = clear_tex_image(ctx, "glClearTexImage",<br>
+ texImages[i], level,<br>
+ -(GLint) texImages[i]->Border, /* xoffset */<br>
+ -(GLint) texImages[i]->Border, /* yoffset */<br>
+ -(GLint) texImages[i]->Border, /* zoffset */<br>
+ texImages[i]->Width,<br>
+ texImages[i]->Height,<br>
+ texImages[i]->Depth,<br>
+ format, type, data);<br>
+ if (!res)<br>
+ break;<br>
+ }<br>
+<br>
+ _mesa_unlock_texture(ctx, texObj);<br>
}<br>
<br>
<br>
@@ -4624,7 +4864,6 @@ _mesa_TexStorage2DMultisample(GLenum target, GLsizei samples,<br>
"glTexStorage2DMultisample");<br>
}<br>
<br>
-<br>
void GLAPIENTRY<br>
_mesa_TexStorage3DMultisample(GLenum target, GLsizei samples,<br>
GLenum internalformat, GLsizei width,<br>
diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h<br>
index 42305f4..984321c 100644<br>
--- a/src/mesa/main/teximage.h<br>
+++ b/src/mesa/main/teximage.h<br>
@@ -336,6 +336,18 @@ _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples,<br>
GLsizei height, GLsizei depth,<br>
GLboolean fixedsamplelocations);<br>
<br>
+extern void GLAPIENTRY<br>
+_mesa_ClearTexImage(GLuint texture, GLint level,<br>
+ GLenum format, GLenum type,<br>
+ const void *data);<br>
+<br>
+extern void GLAPIENTRY<br>
+_mesa_ClearTexSubImage(GLuint texture, GLint level,<br>
+ GLint xoffset, GLint yoffset, GLint zoffset,<br>
+ GLsizei width, GLsizei height, GLsizei depth,<br>
+ GLenum format, GLenum type,<br>
+ const void *data);<br>
+<br>
bool<br>
_mesa_compressed_texture_pixel_storage_error_check(struct gl_context *ctx,<br>
GLint dimensions,<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.9.3<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>