summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2015-01-12 15:39:59 -0800
committerJason Ekstrand <[email protected]>2015-01-22 10:36:24 -0800
commit8546fe900ca4c6059614dae8a77b3a97fafeb629 (patch)
treeaf14d51a9567f7b50021666ca5b529801c1d1fed /src/mesa/drivers
parent7f396189f073d626c5f7a2c232dac92b65f5a23f (diff)
meta: Add an implementation of GetTexSubImage for PBOs
Reviewed-by: Neil Roberts <[email protected]>
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/common/meta.h8
-rw-r--r--src/mesa/drivers/common/meta_tex_subimage.c117
2 files changed, 125 insertions, 0 deletions
diff --git a/src/mesa/drivers/common/meta.h b/src/mesa/drivers/common/meta.h
index 87e9cc92946..20d30f7e6ab 100644
--- a/src/mesa/drivers/common/meta.h
+++ b/src/mesa/drivers/common/meta.h
@@ -531,6 +531,14 @@ _mesa_meta_pbo_TexSubImage(struct gl_context *ctx, GLuint dims,
bool allocate_storage, bool create_pbo,
const struct gl_pixelstore_attrib *packing);
+extern bool
+_mesa_meta_pbo_GetTexSubImage(struct gl_context *ctx, GLuint dims,
+ struct gl_texture_image *tex_image,
+ int xoffset, int yoffset, int zoffset,
+ int width, int height, int depth,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *packing);
+
extern void
_mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
struct gl_texture_image *texImage,
diff --git a/src/mesa/drivers/common/meta_tex_subimage.c b/src/mesa/drivers/common/meta_tex_subimage.c
index 6c921125fc0..b32310c3091 100644
--- a/src/mesa/drivers/common/meta_tex_subimage.c
+++ b/src/mesa/drivers/common/meta_tex_subimage.c
@@ -236,3 +236,120 @@ fail:
return success;
}
+
+bool
+_mesa_meta_pbo_GetTexSubImage(struct gl_context *ctx, GLuint dims,
+ struct gl_texture_image *tex_image,
+ int xoffset, int yoffset, int zoffset,
+ int width, int height, int depth,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *packing)
+{
+ GLuint pbo = 0, pbo_tex = 0, fbos[2] = { 0, 0 };
+ struct gl_texture_image *pbo_tex_image;
+ GLenum status;
+ bool success = false;
+
+ /* XXX: This should probably be passed in from somewhere */
+ const char *where = "_mesa_meta_pbo_GetTexSubImage";
+
+ if (!_mesa_is_bufferobj(packing->BufferObj))
+ return false;
+
+ if (format == GL_DEPTH_COMPONENT ||
+ format == GL_DEPTH_STENCIL ||
+ format == GL_STENCIL_INDEX ||
+ format == GL_COLOR_INDEX)
+ return false;
+
+ if (ctx->_ImageTransferState)
+ return false;
+
+ if (!_mesa_validate_pbo_access(dims, packing, width, height, depth,
+ format, type, INT_MAX, pixels)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(out of bounds PBO access)", where);
+ return true;
+ }
+
+ if (_mesa_check_disallowed_mapping(packing->BufferObj)) {
+ /* buffer is mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
+ return true;
+ }
+
+ pbo_tex_image = create_texture_for_pbo(ctx, false, GL_PIXEL_PACK_BUFFER,
+ width, height, depth,
+ format, type, pixels, packing,
+ &pbo, &pbo_tex);
+ if (!pbo_tex_image)
+ return false;
+
+ /* Only stash the current FBO */
+ _mesa_meta_begin(ctx, 0);
+
+ _mesa_GenFramebuffers(2, fbos);
+
+ if (tex_image && tex_image->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
+ assert(depth == 1);
+ depth = height;
+ height = 1;
+ }
+
+ /* If we were given a texture, bind it to the read framebuffer. If not,
+ * we're doing a ReadPixels and we should just use whatever framebuffer
+ * the client has bound.
+ */
+ if (tex_image) {
+ _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]);
+ _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ tex_image, zoffset);
+ /* If this passes on the first layer it should pass on the others */
+ status = _mesa_CheckFramebufferStatus(GL_READ_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE)
+ goto fail;
+ } else {
+ assert(depth == 1);
+ }
+
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
+ _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ pbo_tex_image, 0);
+ /* If this passes on the first layer it should pass on the others */
+ status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE)
+ goto fail;
+
+ _mesa_update_state(ctx);
+
+ if (_mesa_meta_BlitFramebuffer(ctx, xoffset, yoffset,
+ xoffset + width, yoffset + height,
+ 0, 0, width, height,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST))
+ goto fail;
+
+ for (int z = 1; z < depth; z++) {
+ _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ tex_image, zoffset + z);
+ _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ pbo_tex_image, z);
+
+ _mesa_update_state(ctx);
+
+ _mesa_meta_BlitFramebuffer(ctx, xoffset, yoffset,
+ xoffset + width, yoffset + height,
+ 0, 0, width, height,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ }
+
+ success = true;
+
+fail:
+ _mesa_DeleteFramebuffers(2, fbos);
+ _mesa_DeleteTextures(1, &pbo_tex);
+ _mesa_DeleteBuffers(1, &pbo);
+
+ _mesa_meta_end(ctx);
+
+ return success;
+}