[Glamor] [PATCH 4/5] fallback_optimize: Prepare for downloading/uploading subregion.
Zhigang Gong
zhigang.gong at linux.intel.com
Mon Apr 9 06:42:45 PDT 2012
Introduced two function glamor_get_sub_pixmap/glamor_put_sub_pixmap,
can easily used to get and put sub region of a big textured pixmap.
And it can use pbo if possible.
To support download a big textured pixmap's sub region to another
pixmap's pbo, we introduce a new type of pixmap GLAMOR_MEMORY_MAP.
This type of pixmap has a valid devPrivate.ptr pointer, and that
pointer points to a pbo mapped address.
Now, we are ready to refine those
glamor_prepare_access/glamor_finish_access pairs.
Signed-off-by: Zhigang Gong <zhigang.gong at linux.intel.com>
---
src/glamor.c | 3 +
src/glamor.h | 1 +
src/glamor_fbo.c | 134 +++++++++++++++++++++++++++++++----
src/glamor_pixmap.c | 197 +++++++++++++++++++++++++++++++++------------------
src/glamor_priv.h | 25 +++++--
5 files changed, 272 insertions(+), 88 deletions(-)
diff --git a/src/glamor.c b/src/glamor.c
index 8fc3b05..9b1d425 100644
--- a/src/glamor.c
+++ b/src/glamor.c
@@ -155,6 +155,9 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
}
glamor_set_pixmap_private(pixmap, pixmap_priv);
+ if (usage == GLAMOR_CREATE_PIXMAP_MAP)
+ type = GLAMOR_MEMORY_MAP;
+
pixmap_priv->container = pixmap;
pixmap_priv->glamor_priv = glamor_priv;
pixmap_priv->type = type;
diff --git a/src/glamor.h b/src/glamor.h
index 4a4e9bd..c608ed8 100644
--- a/src/glamor.h
+++ b/src/glamor.h
@@ -51,6 +51,7 @@
*/
typedef enum glamor_pixmap_type {
GLAMOR_MEMORY,
+ GLAMOR_MEMORY_MAP,
GLAMOR_TEXTURE_DRM,
GLAMOR_SEPARATE_TEXTURE,
GLAMOR_DRM_ONLY,
diff --git a/src/glamor_fbo.c b/src/glamor_fbo.c
index b15450a..e9612bd 100644
--- a/src/glamor_fbo.c
+++ b/src/glamor_fbo.c
@@ -132,7 +132,6 @@ glamor_purge_fbo(glamor_pixmap_fbo *fbo)
free(fbo);
}
-
static void
glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo)
{
@@ -165,6 +164,55 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo)
#endif
}
+static void
+glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo)
+{
+ glamor_gl_dispatch *dispatch;
+ int status;
+
+ dispatch = glamor_get_dispatch(fbo->glamor_priv);
+
+ if (fbo->fb == 0)
+ dispatch->glGenFramebuffers(1, &fbo->fb);
+ assert(fbo->tex != 0);
+ dispatch->glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
+ dispatch->glFramebufferTexture2D(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, fbo->tex,
+ 0);
+ status = dispatch->glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ const char *str;
+ switch (status) {
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+ str = "incomplete attachment";
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+ str = "incomplete/missing attachment";
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
+ str = "incomplete draw buffer";
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
+ str = "incomplete read buffer";
+ break;
+ case GL_FRAMEBUFFER_UNSUPPORTED:
+ str = "unsupported";
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
+ str = "incomplete multiple";
+ break;
+ default:
+ str = "unknown error";
+ break;
+ }
+
+ FatalError("destination is framebuffer incomplete: %s [%#x]\n",
+ str, status);
+ }
+ glamor_put_dispatch(fbo->glamor_priv);
+}
+
glamor_pixmap_fbo *
glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv,
int w, int h, GLenum format, GLint tex, int flag)
@@ -183,9 +231,18 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv,
fbo->format = format;
fbo->glamor_priv = glamor_priv;
+ if (flag == GLAMOR_CREATE_PIXMAP_MAP) {
+ glamor_gl_dispatch *dispatch;
+ dispatch = glamor_get_dispatch(glamor_priv);
+ dispatch->glGenBuffers(1, &fbo->pbo);
+ glamor_put_dispatch(glamor_priv);
+ goto done;
+ }
+
if (flag != GLAMOR_CREATE_FBO_NO_FBO)
glamor_pixmap_ensure_fb(fbo);
+done:
return fbo;
}
@@ -331,6 +388,28 @@ glamor_destroy_tex_obj(glamor_pixmap_fbo * tex_obj)
glamor_pixmap_fbo_cache_put(tex_obj);
}
+int
+_glamor_create_tex(glamor_screen_private *glamor_priv,
+ int w, int h, GLenum format)
+{
+ glamor_gl_dispatch *dispatch;
+ int tex;
+
+ dispatch = glamor_get_dispatch(glamor_priv);
+ dispatch->glGenTextures(1, &tex);
+ dispatch->glBindTexture(GL_TEXTURE_2D, tex);
+ dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_NEAREST);
+ dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ GL_NEAREST);
+ dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format,
+ GL_UNSIGNED_BYTE, NULL);
+ glamor_put_dispatch(glamor_priv);
+ return tex;
+}
+
+
+
glamor_pixmap_fbo *
glamor_create_fbo(glamor_screen_private *glamor_priv,
int w, int h,
@@ -339,7 +418,7 @@ glamor_create_fbo(glamor_screen_private *glamor_priv,
{
glamor_gl_dispatch *dispatch;
glamor_pixmap_fbo *fbo;
- GLint tex;
+ GLint tex = 0;
int cache_flag;
if (!glamor_check_fbo_size(glamor_priv, w, h))
@@ -348,6 +427,9 @@ glamor_create_fbo(glamor_screen_private *glamor_priv,
if (flag == GLAMOR_CREATE_FBO_NO_FBO)
goto new_fbo;
+ if (flag == GLAMOR_CREATE_PIXMAP_MAP)
+ goto no_tex;
+
if (flag == GLAMOR_CREATE_PIXMAP_FIXUP)
cache_flag = GLAMOR_CACHE_EXACT_SIZE;
else
@@ -358,18 +440,9 @@ glamor_create_fbo(glamor_screen_private *glamor_priv,
if (fbo)
return fbo;
new_fbo:
- dispatch = glamor_get_dispatch(glamor_priv);
- dispatch->glGenTextures(1, &tex);
- dispatch->glBindTexture(GL_TEXTURE_2D, tex);
- dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- GL_NEAREST);
- dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
- GL_NEAREST);
- dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format,
- GL_UNSIGNED_BYTE, NULL);
-
+ tex = _glamor_create_tex(glamor_priv, w, h, format);
+no_tex:
fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, format, tex, flag);
- glamor_put_dispatch(glamor_priv);
return fbo;
}
@@ -424,12 +497,47 @@ glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo)
/* XXX For the Xephyr only, may be broken now.*/
pixmap_priv->gl_tex = 0;
}
+ case GLAMOR_MEMORY_MAP:
pixmap->devPrivate.ptr = NULL;
break;
default:
break;
}
}
+
+
+Bool
+glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag)
+{
+ glamor_screen_private *glamor_priv;
+ glamor_pixmap_private *pixmap_priv;
+ glamor_pixmap_fbo *fbo;
+
+ glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
+ pixmap_priv = glamor_get_pixmap_private(pixmap);
+ if (pixmap_priv == NULL || pixmap_priv->fbo == NULL) {
+
+ fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width,
+ pixmap->drawable.height,
+ format,
+ flag);
+ if (fbo == NULL)
+ return FALSE;
+
+ glamor_pixmap_attach_fbo(pixmap, fbo);
+ } else {
+ /* We do have a fbo, but it may lack of fb or tex. */
+ if (pixmap_priv->fbo->tex)
+ pixmap_priv->fbo->tex = _glamor_create_tex(glamor_priv, pixmap->drawable.width,
+ pixmap->drawable.height, format);
+
+ if (flag != GLAMOR_CREATE_FBO_NO_FBO && pixmap_priv->fbo->fb == 0)
+ glamor_pixmap_ensure_fb(pixmap_priv->fbo);
+ }
+
+ pixmap_priv = glamor_get_pixmap_private(pixmap);
+ return TRUE;
+}
/*
* XXX how to handle those pending OPs.
* By default, pending OP is disabled. Maybe we will give up the pending
diff --git a/src/glamor_pixmap.c b/src/glamor_pixmap.c
index 6b4dc30..2fbafdc 100644
--- a/src/glamor_pixmap.c
+++ b/src/glamor_pixmap.c
@@ -622,54 +622,6 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
pixmap->devPrivate.ptr);
}
-void
-glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo)
-{
- glamor_gl_dispatch *dispatch;
- int status;
-
- dispatch = glamor_get_dispatch(fbo->glamor_priv);
-
- if (fbo->fb == 0)
- dispatch->glGenFramebuffers(1, &fbo->fb);
- assert(fbo->tex != 0);
- dispatch->glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
- dispatch->glFramebufferTexture2D(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, fbo->tex,
- 0);
- status = dispatch->glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- const char *str;
- switch (status) {
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- str = "incomplete attachment";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- str = "incomplete/missing attachment";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
- str = "incomplete draw buffer";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
- str = "incomplete read buffer";
- break;
- case GL_FRAMEBUFFER_UNSUPPORTED:
- str = "unsupported";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
- str = "incomplete multiple";
- break;
- default:
- str = "unknown error";
- break;
- }
-
- FatalError("destination is framebuffer incomplete: %s [%#x]\n",
- str, status);
- }
- glamor_put_dispatch(fbo->glamor_priv);
-}
/*
* Prepare to upload a pixmap to texture memory.
@@ -681,7 +633,7 @@ glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo)
static int
glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int revert, int swap_rb)
{
- int flag;
+ int flag = 0;
glamor_pixmap_private *pixmap_priv;
glamor_screen_private *glamor_priv;
glamor_pixmap_fbo *fbo;
@@ -696,36 +648,38 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int
|| !glamor_priv->yInverted)) {
/* We don't need a fbo, a simple texture uploading should work. */
- if (pixmap_priv && pixmap_priv->fbo)
- return 0;
flag = GLAMOR_CREATE_FBO_NO_FBO;
- } else {
-
- if (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
- return 0;
- flag = 0;
}
+ if ((flag == 0 && pixmap_priv && pixmap_priv->fbo && pixmap_priv->fbo->tex)
+ || (flag != 0 && pixmap_priv && pixmap_priv->fbo && pixmap_priv->fbo->fb))
+ return 0;
+
if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
gl_iformat_for_depth(pixmap->drawable.depth, &iformat);
else
iformat = format;
+ if (pixmap_priv == NULL || pixmap_priv->fbo == NULL) {
+
+ fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width,
+ pixmap->drawable.height,
+ iformat,
+ flag);
+ if (fbo == NULL) {
+ glamor_fallback
+ ("upload failed, depth %d x %d @depth %d \n",
+ pixmap->drawable.width, pixmap->drawable.height,
+ pixmap->drawable.depth);
+ return -1;
+ }
- fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width,
- pixmap->drawable.height,
- iformat,
- flag);
- if (fbo == NULL) {
- glamor_fallback
- ("upload failed, depth %d x %d @depth %d \n",
- pixmap->drawable.width, pixmap->drawable.height,
- pixmap->drawable.depth);
- return -1;
+ glamor_pixmap_attach_fbo(pixmap, fbo);
+ } else {
+ /* We do have a fbo, but it may lack of fb or tex. */
+ glamor_pixmap_ensure_fbo(pixmap, iformat, flag);
}
- glamor_pixmap_attach_fbo(pixmap, fbo);
-
return 0;
}
@@ -1180,3 +1134,110 @@ fail:
return ret;
}
+
+/*
+ * We may use this function to reduce a large pixmap to a small sub
+ * pixmap. Two scenarios currently:
+ * 1. When fallback a large textured pixmap to CPU but we do need to
+ * do rendering within a small sub region, then we can just get a
+ * sub region.
+ *
+ * 2. When uploading a large pixmap to texture but we only need to
+ * use part of the source/mask picture. As glTexImage2D will be more
+ * efficient to upload a contingent region rather than a sub block
+ * in a large buffer. We use this function to gather the sub region
+ * to a contingent sub pixmap.
+ *
+ * The sub-pixmap must have the same format as the source pixmap.
+ *
+ * */
+PixmapPtr
+glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_access_t access)
+{
+ glamor_screen_private *glamor_priv;
+ PixmapPtr sub_pixmap;
+ glamor_pixmap_private *sub_pixmap_priv, *pixmap_priv;
+ void *data;
+ int pbo;
+ int flag;
+
+ if (access == GLAMOR_ACCESS_WO) {
+ sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h,
+ pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU);
+ ErrorF("WO\n");
+ return sub_pixmap;
+ }
+
+ glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
+ pixmap_priv = glamor_get_pixmap_private(pixmap);
+
+ if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+ return NULL;
+
+ if (glamor_priv->gl_flavor == GLAMOR_GL_ES2)
+ flag = GLAMOR_CREATE_PIXMAP_CPU;
+ else
+ flag = GLAMOR_CREATE_PIXMAP_MAP;
+
+ sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h,
+ pixmap->drawable.depth, flag);
+
+ if (sub_pixmap == NULL)
+ return NULL;
+
+ sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap);
+ pbo = sub_pixmap_priv ? (sub_pixmap_priv->fbo ? sub_pixmap_priv->fbo->pbo : 0): 0;
+
+ if (pbo)
+ data = NULL;
+ else {
+ data = sub_pixmap->devPrivate.ptr;
+ assert(flag != GLAMOR_CREATE_PIXMAP_MAP);
+ }
+ data = glamor_download_sub_pixmap_to_cpu(pixmap, x, y, w, h, sub_pixmap->devKind,
+ data, pbo, access);
+ if (pbo) {
+ assert(sub_pixmap->devPrivate.ptr == NULL);
+ sub_pixmap->devPrivate.ptr = data;
+ sub_pixmap_priv->fbo->pbo_valid = 1;
+ }
+#if 0
+ struct pixman_box16 box;
+ PixmapPtr new_sub_pixmap;
+ int dx, dy;
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = w;
+ box.y2 = h;
+
+ dx = x;
+ dy = y;
+
+ new_sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h,
+ pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU);
+ glamor_copy_n_to_n(&pixmap->drawable, &new_sub_pixmap, NULL, &box, 1, dx, dy, 0, 0, 0, NULL);
+ glamor_compare_pixmaps(new_sub_pixmap, sub_pixmap, 0, 0, w, h, 1, 1);
+#endif
+
+ return sub_pixmap;
+}
+
+PixmapPtr
+glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y, int w, int h, glamor_access_t access)
+{
+ struct pixman_box16 box;
+ int dx, dy;
+ box.x1 = x;
+ box.y1 = y;
+ box.x2 = x + w;
+ box.y2 = y + h;
+
+ dx = -(x);
+ dy = -(y);
+
+ glamor_copy_n_to_n(&sub_pixmap->drawable,
+ &pixmap->drawable,
+ NULL, &box, 1, dx, dy,
+ 0, 0, 0, NULL);
+ glamor_destroy_pixmap(sub_pixmap);
+}
diff --git a/src/glamor_priv.h b/src/glamor_priv.h
index 3e13ef8..8a6beee 100644
--- a/src/glamor_priv.h
+++ b/src/glamor_priv.h
@@ -145,8 +145,8 @@ enum glamor_gl_flavor {
#define GLAMOR_CREATE_PIXMAP_CPU 0x100
#define GLAMOR_CREATE_PIXMAP_FIXUP 0x101
-
#define GLAMOR_CREATE_FBO_NO_FBO 0x103
+#define GLAMOR_CREATE_PIXMAP_MAP 0x104
#define GLAMOR_CREATE_TEXTURE_EXACT_SIZE 0x104
@@ -615,15 +615,16 @@ Bool glamor_download_pixmap_to_cpu(PixmapPtr pixmap,
* must be 1.
**/
void glamor_restore_pixmap_to_texture(PixmapPtr pixmap);
+
/**
- * Ensure to have a fbo has a valid/complete glfbo.
+ * According to the flag,
+ * if the flag is GLAMOR_CREATE_FBO_NO_FBO then just ensure
+ * the fbo has a valid texture. Otherwise, it will ensure
+ * the fbo has valid texture and attach to a valid fb.
* If the fbo already has a valid glfbo then do nothing.
- * Otherwise, it will generate a new glfbo, and bind
- * the fbo's texture to the glfbo.
- * The fbo must has a valid texture before call this
- * API, othersie, it will trigger a assert.
*/
-void glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo);
+Bool
+glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag);
/**
* Upload a pixmap to gl texture. Used by dynamic pixmap
@@ -633,6 +634,16 @@ void glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo);
enum glamor_pixmap_status glamor_upload_pixmap_to_texture(PixmapPtr
pixmap);
+
+PixmapPtr
+glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y,
+ int w, int h, glamor_access_t access);
+
+PixmapPtr
+glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y,
+ int w, int h, glamor_access_t access);
+
+
/**
* Upload a picture to gl texture. Similar to the
* glamor_upload_pixmap_to_texture. Used in rendering.
--
1.7.4.4
More information about the Glamor
mailing list