<div dir="ltr"><div>After sending this review, I think it would be best (to avoid a gigantic merge snarl) for me to send another patch where I manually merge this with my patch <span style="font-weight:normal"><font>"[PATCH 29/41] main: Added entry point for glGetTextureImage."<br><br></font></span></div><span style="font-weight:normal"><font>Laura<br></font></span></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Dec 18, 2014 at 10:07 AM, Laura Ekstrand <span dir="ltr"><<a href="mailto:laura@jlekstrand.net" target="_blank">laura@jlekstrand.net</a>></span> wrote:<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Brian,<br><br></div>I dealt with a lot of the TEXTURE_CUBE_MAP stuff when I implemented GetTextureImage (in my recent DSA textures patch series).<br><div><br>Ian and I have filed a bug on the spec for missing faces and mismatched formats/sizes. Right now, I am saying if (texObj->NumLayers < 6), throw invalid operation (not enough storage). Moreover, I discovered Monday (12/15) that in the spec for GenerateMipmap there is a pre-existing idea of "cube completeness." In section 8.14.4 of GL 4.5 spec, it defines cube completeness as having all the same formats/sizes on the faces. So I am checking if the texObj is cube complete and throwing invalid operation if it is not.<br><br>So for now, I think invalid operation is the right plan.<br><br></div><div>I agree, this is an absolute mess.<span class="HOEnZb"><font color="#888888"><br><br></font></span></div><span class="HOEnZb"><font color="#888888"><div>Laura<br></div></font></span></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Dec 18, 2014 at 7:32 AM, Brian Paul <span dir="ltr"><<a href="mailto:brianp@vmware.com" target="_blank">brianp@vmware.com</a>></span> wrote:<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span>On 12/17/2014 05:03 PM, Laura Ekstrand wrote:<br>
</span><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span>
<br>
<br>
On Sat, Dec 13, 2014 at 6:42 AM, Brian Paul <<a href="mailto:brianp@vmware.com" target="_blank">brianp@vmware.com</a><br></span><div><div>
<mailto:<a href="mailto:brianp@vmware.com" target="_blank">brianp@vmware.com</a>>> wrote:<br>
<br>
One of the two new functions in GL_ARB_get_texture_sub_image.<br>
---<br>
src/mesa/main/texgetimage.c | 305<br>
++++++++++++++++++++++++++++++<u></u>++++++++------<br>
src/mesa/main/texgetimage.h | 8 ++<br>
2 files changed, 277 insertions(+), 36 deletions(-)<br>
<br>
diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c<br>
index 71c25bb..e1f238b 100644<br>
--- a/src/mesa/main/texgetimage.c<br>
+++ b/src/mesa/main/texgetimage.c<br>
@@ -44,6 +44,7 @@<br>
#include "texcompress.h"<br>
#include "texgetimage.h"<br>
#include "teximage.h"<br>
+#include "texobj.h"<br>
#include "texstore.h"<br>
<br>
<br>
@@ -803,41 +804,36 @@ legal_getteximage_target(<u></u>struct gl_context<br>
*ctx, GLenum target)<br>
<br>
In my work with DSA textures, I have discovered that it's more robust to<br>
pass in both the texture object and target. I originally just passed in<br>
the texObj instead of the target in error checks and used<br>
texObj->Target, but I failed a number of Piglit tests afterwards. This<br>
is because, for non-DSA texture objects, the target passed into the<br>
function and the texObj->Target don't always match (especially for proxy<br>
targets).<br>
<br>
/**<br>
- * Do error checking for a glGetTexImage() call.<br>
+ * Do error checking for a glGetTexImage() or<br>
glGetTextureSubImage() call.<br>
* \return GL_TRUE if any error, GL_FALSE if no errors.<br>
*/<br>
static GLboolean<br>
-getteximage_error_check(<u></u>struct gl_context *ctx, GLenum target,<br>
GLint level,<br>
+getteximage_error_check(<u></u>struct gl_context *ctx,<br>
+ struct gl_texture_object *texObj, GLint level,<br>
GLenum format, GLenum type, GLsizei<br>
clientMemSize,<br>
- GLvoid *pixels )<br>
+ GLvoid *pixels, const char *caller)<br>
{<br>
- struct gl_texture_object *texObj;<br>
+ GLenum target = texObj->Target;<br>
struct gl_texture_image *texImage;<br>
const GLint maxLevels = _mesa_max_texture_levels(ctx, target);<br>
- const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;<br>
GLenum baseFormat, err;<br>
<br>
- if (!legal_getteximage_target(<u></u>ctx, target)) {<br>
- _mesa_error(ctx, GL_INVALID_ENUM,<br>
"glGetTexImage(target=0x%x)", target);<br>
- return GL_TRUE;<br>
- }<br>
-<br>
assert(maxLevels != 0);<br>
if (level < 0 || level >= maxLevels) {<br>
- _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );<br>
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", caller);<br>
return GL_TRUE;<br>
}<br>
<br>
err = _mesa_error_check_format_and_<u></u>type(ctx, format, type);<br>
if (err != GL_NO_ERROR) {<br>
- _mesa_error(ctx, err, "glGetTexImage(format/type)");<br>
+ _mesa_error(ctx, err, "%s(format/type)", caller);<br>
return GL_TRUE;<br>
}<br>
<br>
texObj = _mesa_get_current_tex_object(<u></u>ctx, target);<br>
<br>
if (!texObj) {<br>
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");<br>
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", caller);<br>
return GL_TRUE;<br>
}<br>
<br>
@@ -854,64 +850,79 @@ getteximage_error_check(struct gl_context<br>
*ctx, GLenum target, GLint level,<br>
*/<br>
if (_mesa_is_color_format(format)<br>
&& !_mesa_is_color_format(<u></u>baseFormat)) {<br>
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format<br>
mismatch)");<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format mismatch)",<br>
caller);<br>
return GL_TRUE;<br>
}<br>
else if (_mesa_is_depth_format(format)<br>
&& !_mesa_is_depth_format(<u></u>baseFormat)<br>
&& !_mesa_is_depthstencil_format(<u></u>baseFormat)) {<br>
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format<br>
mismatch)");<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format mismatch)",<br>
caller);<br>
return GL_TRUE;<br>
}<br>
else if (_mesa_is_stencil_format(<u></u>format)<br>
&& !ctx->Extensions.ARB_texture_<u></u>stencil8) {<br>
- _mesa_error(ctx, GL_INVALID_ENUM,<br>
"glGetTexImage(format=GL_<u></u>STENCIL_INDEX)");<br>
+ _mesa_error(ctx, GL_INVALID_ENUM,<br>
"%s(format=GL_STENCIL_INDEX)", caller);<br>
return GL_TRUE;<br>
}<br>
else if (_mesa_is_ycbcr_format(format)<br>
&& !_mesa_is_ycbcr_format(<u></u>baseFormat)) {<br>
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format<br>
mismatch)");<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format mismatch)",<br>
caller);<br>
return GL_TRUE;<br>
}<br>
else if (_mesa_is_depthstencil_format(<u></u>format)<br>
&& !_mesa_is_depthstencil_format(<u></u>baseFormat)) {<br>
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format<br>
mismatch)");<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format mismatch)",<br>
caller);<br>
return GL_TRUE;<br>
}<br>
else if (_mesa_is_enum_format_integer(<u></u>format) !=<br>
_mesa_is_format_integer(<u></u>texImage->TexFormat)) {<br>
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format<br>
mismatch)");<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format mismatch)",<br>
caller);<br>
return GL_TRUE;<br>
}<br>
<br>
- if (!_mesa_validate_pbo_access(<u></u>dimensions, &ctx->Pack,<br>
texImage->Width,<br>
- texImage->Height, texImage->Depth,<br>
- format, type, clientMemSize,<br>
pixels)) {<br>
+ return GL_FALSE;<br>
+}<br>
+<br>
+<br>
+/**<br>
+ * Do error checking related to the PBO and image size.<br>
+ */<br>
+static bool<br>
+pbo_error_check(struct gl_context *ctx, GLenum target,<br>
+ GLenum format, GLenum type,<br>
+ GLsizei width, GLsizei height, GLsizei depth,<br>
+ GLsizei bufferSize, void *pixels,<br>
+ const char *caller)<br>
+{<br>
+ const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;<br>
+<br>
+ if (!_mesa_validate_pbo_access(<u></u>dimensions, &ctx->Pack,<br>
+ width, height, depth,<br>
+ format, type, bufferSize, pixels)) {<br>
if (_mesa_is_bufferobj(ctx->Pack.<u></u>BufferObj)) {<br>
_mesa_error(ctx, GL_INVALID_OPERATION,<br>
- "glGetTexImage(out of bounds PBO access)");<br>
+ "%s(out of bounds PBO access)", caller);<br>
} else {<br>
_mesa_error(ctx, GL_INVALID_OPERATION,<br>
- "glGetnTexImageARB(out of bounds access:"<br>
- " bufSize (%d) is too small)", clientMemSize);<br>
+ "%s(out of bounds access: bufSize (%d) is too<br>
small)",<br>
+ caller, bufferSize);<br>
}<br>
- return GL_TRUE;<br>
+ return true;<br>
}<br>
<br>
if (_mesa_is_bufferobj(ctx->Pack.<u></u>BufferObj)) {<br>
/* PBO should not be mapped */<br>
if (_mesa_check_disallowed_<u></u>mapping(ctx->Pack.BufferObj)) {<br>
_mesa_error(ctx, GL_INVALID_OPERATION,<br>
- "glGetTexImage(PBO is mapped)");<br>
- return GL_TRUE;<br>
+ "%s(PBO is mapped)", caller);<br>
+ return true;<br>
}<br>
}<br>
<br>
- return GL_FALSE;<br>
+ return false;<br>
}<br>
<br>
<br>
-<br>
/**<br>
* Get texture image. Called by glGetTexImage.<br>
*<br>
@@ -932,21 +943,36 @@ _mesa_GetnTexImageARB( GLenum target, GLint<br>
level, GLenum format,<br>
<br>
FLUSH_VERTICES(ctx, 0);<br>
<br>
- if (getteximage_error_check(ctx, target, level, format, type,<br>
- bufSize, pixels)) {<br>
+ if (!legal_getteximage_target(<u></u>ctx, target)) {<br>
+ _mesa_error(ctx, GL_INVALID_ENUM,<br>
"glGetTexImage(target=0x%x)", target);<br>
return;<br>
}<br>
<br>
- if (!_mesa_is_bufferobj(ctx-><u></u>Pack.BufferObj) && !pixels) {<br>
- /* not an error, do nothing */<br>
+ texObj = _mesa_get_current_tex_object(<u></u>ctx, target);<br>
+<br>
+ if (getteximage_error_check(ctx, texObj, level, format, type,<br>
+ bufSize, pixels, "glGet[n]TexImage")) {<br>
return;<br>
}<br>
<br>
- texObj = _mesa_get_current_tex_object(<u></u>ctx, target);<br>
texImage = _mesa_select_tex_image(ctx, texObj, target, level);<br>
+ if (!texImage) {<br>
+ return; /* no texture image */<br>
+ }<br>
<br>
- if (_mesa_is_zero_size_texture(<u></u>texImage))<br>
+ if (pbo_error_check(ctx, target, format, type,<br>
+ texImage->Width, texImage->Height,<br>
texImage->Depth,<br>
+ bufSize, pixels, "glGet[n]TexImage")) {<br>
return;<br>
+ }<br>
+<br>
+ if (_mesa_is_zero_size_texture(<u></u>texImage)) {<br>
+ return; /* nothing to get */<br>
+ }<br>
+<br>
+ if (!_mesa_is_bufferobj(ctx-><u></u>Pack.BufferObj) && !pixels) {<br>
+ return; /* not an error, do nothing */<br>
+ }<br>
<br>
if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {<br>
_mesa_debug(ctx, "glGetTexImage(tex %u) format = %s, w=%d,<br>
h=%d,"<br>
@@ -1110,3 +1136,210 @@ _mesa_GetCompressedTexImage(<u></u>GLenum target,<br>
GLint level, GLvoid *img)<br>
{<br>
_mesa_<u></u>GetnCompressedTexImageARB(<u></u>target, level, INT_MAX, img);<br>
}<br>
<br>
<br>
Note: When this gets merged with my DSA work, the target should maybe<br>
get passed into this function. This is because DSA and traditional<br>
functions share a backend function, and that backend function will have<br>
to resemble your GetTextureSubImage function (thus calling<br>
dimensions_error_check). As aforementioned, not passing the target<br>
could cause trouble.<br>
<br>
+<br>
+<br>
+<br>
+/**<br>
+ * Error-check the offset and size arguments to<br>
+ * glGet[Compressed]<u></u>TextureSubImage().<br>
+ * \return true if error, false if no error.<br>
+ */<br>
+static bool<br>
+dimensions_error_check(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>
+{<br>
+ const GLenum target = texImage->TexObject->Target;<br>
+<br>
+ switch (target) {<br>
+ case GL_TEXTURE_1D:<br>
+ if (yoffset != 0) {<br>
+ _mesa_error(ctx, GL_INVALID_VALUE,<br>
+ "glGetTextureSubImage(1D, yoffset = %d)\n",<br>
yoffset);<br>
+ return true;<br>
+ }<br>
+ if (height != 1) {<br>
+ _mesa_error(ctx, GL_INVALID_VALUE,<br>
+ "glGetTextureSubImage(1D, height = %d)\n",<br>
height);<br>
+ return true;<br>
+ }<br>
+ /* fall-through */<br>
+ case GL_TEXTURE_1D_ARRAY:<br>
+ case GL_TEXTURE_2D:<br>
+ case GL_TEXTURE_RECTANGLE:<br>
+ if (zoffset != 0) {<br>
+ _mesa_error(ctx, GL_INVALID_VALUE,<br>
+ "glGetTextureSubImage(zoffset = %d)\n", zoffset);<br>
+ return true;<br>
+ }<br>
+ if (depth != 1) {<br>
+ _mesa_error(ctx, GL_INVALID_VALUE,<br>
+ "glGetTextureSubImage(depth = %d)\n", depth);<br>
+ return true;<br>
+ }<br>
+ break;<br>
+ default:<br>
+ ; /* nothing */<br>
+ }<br>
+<br>
+ if (xoffset < 0) {<br>
+ _mesa_error(ctx, GL_INVALID_VALUE,<br>
+ "glGetTextureSubImage(xoffset = %d)\n", xoffset);<br>
+ return true;<br>
+ }<br>
+<br>
+ if (yoffset < 0) {<br>
+ _mesa_error(ctx, GL_INVALID_VALUE,<br>
+ "glGetTextureSubImage(yoffset = %d)\n", yoffset);<br>
+ return true;<br>
+ }<br>
+<br>
+ if (zoffset < 0) {<br>
+ _mesa_error(ctx, GL_INVALID_VALUE,<br>
+ "glGetTextureSubImage(zoffset = %d)\n", zoffset);<br>
+ return true;<br>
+ }<br>
+<br>
<br>
Why didn't you put xoffset %d + width %d > image_width %u ?<br>
</div></div></blockquote>
<br>
IMHO, the error message has enough info to convey the problem. If you feel strongly that this needs to be fixed, there's a bunch of similar instances (with more terse messages) in teximage.c that should be fixed as well.<div><div><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
+ if (xoffset + width > texImage->Width) {<br>
+ _mesa_error(ctx, GL_INVALID_VALUE,<br>
+ "glGetTextureSubImage(xoffset %d + width %d > %u)\n",<br>
+ xoffset, width, texImage->Width);<br>
+ return true;<br>
+ }<br>
+<br>
+ if (yoffset + height > texImage->Height) {<br>
+ _mesa_error(ctx, GL_INVALID_VALUE,<br>
+ "glGetTextureSubImage(yoffset %d + height %d ><br>
%u)\n",<br>
+ yoffset, height, texImage->Height);<br>
+ return true;<br>
+ }<br>
+<br>
+ if (zoffset + depth > texImage->Depth) {<br>
+ _mesa_error(ctx, GL_INVALID_VALUE,<br>
+ "glGetTextureSubImage(zoffset %d + depth %d > %u)\n",<br>
+ zoffset, depth, texImage->Depth);<br>
+ return true;<br>
+ }<br>
+<br>
+ /* Extra checks for compressed textures */<br>
+ {<br>
+ GLuint bw, bh;<br>
+ _mesa_get_format_block_size(<u></u>texImage->TexFormat, &bw, &bh);<br>
<br>
+ if (bw > 1 || bh > 1) {<br>
+ /* offset must be multiple of block size */<br>
<br>
This should be an INVALID_VALUE error according to the GL 4.5 spec.<br>
</blockquote>
<br></div></div>
Fixed in v2.<span><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
+ if (xoffset % bw != 0) {<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+ "glGetTextureSubImage(xoffset = %d)", xoffset);<br>
+ return true;<br>
+ }<br>
+ if (target != GL_TEXTURE_1D && target !=<br>
GL_TEXTURE_1D_ARRAY) {<br>
<br>
This should be an INVALID_VALUE error according to the GL 4.5 spec.<br>
</blockquote>
<br></span>
Fixed in v2.<span><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Also, shouldn't it be yoffset % bh != 0 ? You have bw.<br>
</blockquote>
<br></span>
Fixed in v2.<span><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
+ if (yoffset % bw != 0) {<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+ "glGetTextureSubImage(yoffset = %d)",<br>
yoffset);<br>
+ return true;<br>
+ }<br>
+ }<br>
<br>
Why is there no similar zoffset check? Is it because Mesa doesn't have<br>
a concept of block depth?<br>
</blockquote>
<br></span>
Correct.<span><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
+<br>
+ /* The size must be a multiple of bw x bh, or we must be<br>
using a<br>
+ * offset+size that exactly hits the edge of the image.<br>
+ */<br>
<br>
Note: xoffset + width != (GLint) texImage->Width is more permissive than<br>
the spec document, which says (xoffset != 0) || (width != (GLint)<br>
texImage->Width).<br>
</blockquote>
<br></span>
I believe there was discussion about this a few years ago and Mesa's behavior matches nvidia's driver. The same logic is used in the glTexImage code. It allows sub-regions of compressed textures to be read/written on block boundaries.<span><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Again, the spec document says INVALID_VALUE.<br>
</blockquote>
<br></span>
Fixed.<span><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
+ if ((width % bw != 0) &&<br>
+ (xoffset + width != (GLint) texImage->Width)) {<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+ "glGetTextureSubImage(width = %d)", width);<br>
+ return true;<br>
+ }<br>
+<br>
<br>
Again, the spec document says INVALID_VALUE.<br>
</blockquote>
<br></span>
Fixed.<span><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
+ if ((height % bh != 0) &&<br>
+ (yoffset + height != (GLint) texImage->Height)) {<br>
+ _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+ "glGetTextureSubImage(height = %d)", height);<br>
+ return true;<br>
+ }<br>
+ }<br>
+ }<br>
<br>
No depth check?<br>
</blockquote>
<br></span>
No. We have no 3D compression formats.<br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div>
<br>
+<br>
+ if (width == 0 || height == 0 || depth == 0) {<br>
+ /* Not an error, but nothing to do. Return 'true' so that the<br>
+ * caller simply returns.<br>
+ */<br>
+ return true;<br>
+ }<br>
+<br>
+ return false;<br>
+}<br>
+<br>
+<br>
+<br>
+void GLAPIENTRY<br>
+_mesa_GetTextureSubImage(<u></u>GLuint texture, GLint level,<br>
+ GLint xoffset, GLint yoffset, GLint zoffset,<br>
+ GLsizei width, GLsizei height, GLsizei depth,<br>
+ GLenum format, GLenum type, GLsizei bufSize,<br>
+ void *pixels)<br>
+{<br>
+ struct gl_texture_object *texObj;<br>
+ struct gl_texture_image *texImage;<br>
+ GLenum target;<br>
+<br>
+ GET_CURRENT_CONTEXT(ctx);<br>
+<br>
+ texObj = _mesa_lookup_texture(ctx, texture);<br>
+ if (!texObj) {<br>
<br>
<br>
I think this error might be a mistake in the spec. According to<br>
<a href="https://www.opengl.org/registry/specs/ARB/get_texture_sub_image.txt" target="_blank">https://www.opengl.org/<u></u>registry/specs/ARB/get_<u></u>texture_sub_image.txt</a><br></div></div>
<<a href="https://urldefense.proofpoint.com/v2/url?u=https-3A__www.opengl.org_registry_specs_ARB_get-5Ftexture-5Fsub-5Fimage.txt&d=AwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=T0t4QG7chq2ZwJo6wilkFznRSFy-8uDKartPGbomVj8&m=WWWcDPCoYwfOyILpH0kA7-k-qpSPTsIs1qycAmB5GNA&s=ZhWz0mRK6xg9KPHqEvdXdXdSYxLyX81SGDpO0VoV-nw&e=" target="_blank">https://urldefense.<u></u>proofpoint.com/v2/url?u=https-<u></u>3A__www.opengl.org_registry_<u></u>specs_ARB_get-5Ftexture-5Fsub-<u></u>5Fimage.txt&d=AwMFaQ&c=<u></u>Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-<u></u>YihVMNtXt-uEs&r=<u></u>T0t4QG7chq2ZwJo6wilkFznRSFy-<u></u>8uDKartPGbomVj8&m=<u></u>WWWcDPCoYwfOyILpH0kA7-k-<u></u>qpSPTsIs1qycAmB5GNA&s=<u></u>ZhWz0mRK6xg9KPHqEvdXdXdSYxLyX8<u></u>1SGDpO0VoV-nw&e=</a>>,<span><br>
it should be INVALID_OPERATION in the case where the user passed in an<br>
unknown texture name. Oddly enough, the OpenGL 4.5 core spec<br>
(30.10.2014) has INVALID_VALUE (consistent with what you have here) in<br>
section 8.11 Texture Queries. But that is very strange because all the<br>
DSA functions consistently throw INVALID_OPERATION for this error (such<br>
as GetTextureImage and TextureSubImage*D, etc.) in the OpenGL 4.5 spec.<br>
I'm not sure why they wouldn't agree.<br>
<br>
In my DSA patch series, I have a convenience function for throwing<br>
INVALID_OPERATION for an unknown texture name because this occurs<br>
absolutely everywhere (_mesa_lookup_texture_err).<br>
</span></blockquote>
<br>
Actually, a later patch in the series changed this to INVALID_OPERATION (and fixed the error string). I'll move that bit into this patch.<br>
<br>
INVALID_OPERATION seems to be the right thing.<span><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
+ _mesa_error(ctx, GL_INVALID_VALUE,<br>
+ "glGetTextureSubImage(invalid texture ID %u\n",<br>
texture);<br>
+ return;<br>
+ }<br>
+<br>
+ /* common error checking */<br>
+ if (getteximage_error_check(ctx, texObj, level, format, type,<br>
bufSize,<br>
+ pixels, "glGetTextureSubImage")) {<br>
+ return;<br>
+ }<br>
+<br>
<br>
<br>
You forgot to call legal_getteximage_target.<br>
</blockquote>
<br></span>
I don't think that's needed since it's not possible for texObj->Target to be an invalid value at this point.<span><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
+ target = texObj->Target;<br>
<br>
<br>
This doesn't seem like it will return more than one face of the cube<br>
map. In fact, it will throw INVALID_OPERATION if the user tries to do<br>
so (depth != 1). But the GL 4.5 spec says the user should be able to<br>
get as many faces as he or she wants from GetTextureSubImage (up to all<br>
six).<br>
</blockquote>
<br></span>
Ugh, something got lost from my early versions of the GL_ARB_get_texture_sub_image spec to what's in the final spec, and the 4.5 spec.<br>
<br>
The problem is OpenGL doesn't disallow specifying different dimensions for each of the cube map faces. For example, it's perfectly legal to<br>
create a cube map texture like this:<br>
<br>
glTexImage2D(POSITIVE_X, width=32, height=32)<br>
glTexImage2D(NEGATIVE_X, width=16, height=16)<br>
glTexImage2D(POSITIVE_Y, width=64, height=64)<br>
etc.<br>
<br>
You can even have different internal formats per face!<br>
<br>
The texture will be flagged as 'incomplete' and you can't render with it. But you can create such a texture and you can query the face dimensions with glGetTexLevelParameter() and get back the per-face sizes. Plus, glGetTexImage operates per-face. (I should probably whip up a piglit test to verify this).<br>
<br>
So, what should happen with glGetTextureSubImage() if we try to get two or more mismatched-size faces at once? I can't find any spec language about this. Maybe just raise GL_INVALID_OPERATION??<br>
<br>
My first few drafts of the GL_ARB_get_texture_sub_image spec had a target parameter which only allowed GL_TEXTURE_CUBE_MAP_POSITIVE/<u></u>NEGATIVE_X/Y/Z so that this situation would be handled consistently.<br>
<br>
I didn't see that this got changed in the spec so I implemented what I originally intended (only allow getting one face/slice at a time).<br>
<br>
<br>
BTW, it would be nice in Mesa if we could treat GL_TEXTURE_CUBE_MAP textures more like GL_TEXTURE_CUBE_MAP_ARRAY textures. That is, the faces would just be treated as slices in a depth=6 array.<br>
<br>
Ideally, gl_texture_object::Image[face]<u></u>[level] would become gl_texture_object::Image[<u></u>level]. But we can't really do that since according to the spec, we need to keep track of possibly different dimensions and formats for each face.<br>
<br>
This is a mess. What do you think about the GL_INVALID_OPERATION idea?<br>
<br>
<br>
In any case, I'm on vacation after Friday so I probably won't have time to go further on this until the new year.<br>
<br>
-Brian<br>
<br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div>
In my GetTextureImage patch, I just call the backend<br>
_mesa_get_texture_image multiple times. When they are merged, the<br>
backend will be _mesa_get_texture_sub_image and GetTextureSubImage can<br>
call that multiple times in the same way.<br>
<br>
+ if (target == GL_TEXTURE_CUBE_MAP) {<br>
+ /* convert z to face/target */<br>
+ if (zoffset >= 6) {<br>
+ _mesa_error(ctx, GL_INVALID_VALUE,<br>
+ "glGetTextureSubImage(cube, zoffset = %d\n",<br>
zoffset);<br>
+ return;<br>
+ }<br>
+ if (depth != 1) {<br>
+ _mesa_error(ctx, GL_INVALID_VALUE,<br>
+ "glGetTextureSubImage(cube, depth = %d\n", depth);<br>
+ return;<br>
+ }<br>
+ target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset;<br>
+ }<br>
+<br>
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);<br>
+<br>
+ /* check dimensions */<br>
+ if (dimensions_error_check(ctx, texImage, xoffset, yoffset, zoffset,<br>
+ width, height, depth)) {<br>
+ return;<br>
+ }<br>
+<br>
+ if (pbo_error_check(ctx, target, format, type,<br>
+ width, height, depth,<br>
+ bufSize, pixels, "glGetTextureSubImage")) {<br>
+ return;<br>
+ }<br>
+<br>
+ if (_mesa_is_zero_size_texture(<u></u>texImage)) {<br>
+ return; /* nothing to get */<br>
+ }<br>
+<br>
+ if (!_mesa_is_bufferobj(ctx-><u></u>Pack.BufferObj) && pixels == NULL) {<br>
+ return; /* not an error, do nothing */<br>
+ }<br>
+<br>
+ _mesa_lock_texture(ctx, texObj);<br>
+ {<br>
+ ctx->Driver.GetTexSubImage(<u></u>ctx, xoffset, yoffset, zoffset,<br>
width, height,<br>
+ depth, format, type, pixels,<br>
texImage);<br>
+ }<br>
+ _mesa_unlock_texture(ctx, texObj);<br>
+}<br>
diff --git a/src/mesa/main/texgetimage.h b/src/mesa/main/texgetimage.h<br>
index c9af5b9..40f152c 100644<br>
--- a/src/mesa/main/texgetimage.h<br>
+++ b/src/mesa/main/texgetimage.h<br>
@@ -65,4 +65,12 @@ extern void GLAPIENTRY<br>
_mesa_<u></u>GetnCompressedTexImageARB(<u></u>GLenum target, GLint level,<br>
GLsizei bufSize,<br>
GLvoid *img);<br>
<br>
+extern void GLAPIENTRY<br>
+_mesa_GetTextureSubImage(<u></u>GLuint texture, GLint level,<br>
+ GLint xoffset, GLint yoffset, GLint zoffset,<br>
+ GLsizei width, GLsizei height, GLsizei depth,<br>
+ GLenum format, GLenum type, GLsizei bufSize,<br>
+ void *pixels);<br>
+<br>
+<br>
#endif /* TEXGETIMAGE_H */<br>
--<br>
1.9.1<br>
<br>
______________________________<u></u>_________________<br>
mesa-dev mailing list<br></div></div>
<a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank">mesa-dev@lists.freedesktop.org</a> <mailto:<a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank">mesa-dev@lists.<u></u>freedesktop.org</a>><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" target="_blank">http://lists.freedesktop.org/<u></u>mailman/listinfo/mesa-dev</a><br>
<<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__lists.freedesktop.org_mailman_listinfo_mesa-2Ddev&d=AwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=T0t4QG7chq2ZwJo6wilkFznRSFy-8uDKartPGbomVj8&m=WWWcDPCoYwfOyILpH0kA7-k-qpSPTsIs1qycAmB5GNA&s=GrUeebJuM5x75DOASs1ezQdYEv5z61wojf4LHxr7Rvc&e=" target="_blank">https://urldefense.<u></u>proofpoint.com/v2/url?u=http-<u></u>3A__lists.freedesktop.org_<u></u>mailman_listinfo_mesa-2Ddev&d=<u></u>AwMFaQ&c=<u></u>Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-<u></u>YihVMNtXt-uEs&r=<u></u>T0t4QG7chq2ZwJo6wilkFznRSFy-<u></u>8uDKartPGbomVj8&m=<u></u>WWWcDPCoYwfOyILpH0kA7-k-<u></u>qpSPTsIs1qycAmB5GNA&s=<u></u>GrUeebJuM5x75DOASs1ezQdYEv5z61<u></u>wojf4LHxr7Rvc&e=</a>><br>
<br>
</blockquote>
<br>
</blockquote></div></div>
</div></div></blockquote></div></div>