diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 5c5f7e5dc..d6105d002 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -44,6 +44,7 @@ libglamor_la_SOURCES = \ glamor_picture.c\ glamor_window.c\ glamor_gl_dispatch.c\ + glamor_fbo.c\ glamor.h sdk_HEADERS = glamor.h diff --git a/glamor/glamor.c b/glamor/glamor.c index 6d7abd543..29f827cc4 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -85,52 +85,41 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex) glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv; glamor_gl_dispatch *dispatch; + glamor_pixmap_fbo *fbo; glamor_priv = glamor_get_screen_private(screen); dispatch = &glamor_priv->dispatch; pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv == NULL) { - pixmap_priv = calloc(sizeof(*pixmap_priv), 1); - dixSetPrivate(&pixmap->devPrivates, - glamor_pixmap_private_key, pixmap_priv); - pixmap_priv->container = pixmap; - pixmap_priv->glamor_priv = glamor_priv; + if (pixmap_priv->fbo) { + fbo = glamor_pixmap_detach_fbo(pixmap_priv); + glamor_destroy_fbo(fbo); } - if (pixmap_priv->fb) - dispatch->glDeleteFramebuffers(1, &pixmap_priv->fb); + fbo = glamor_create_fbo_from_tex(glamor_priv, pixmap->drawable.width, + pixmap->drawable.height, + pixmap->drawable.depth, tex, 0); - if (pixmap_priv->tex) - dispatch->glDeleteTextures(1, &pixmap_priv->tex); - - pixmap_priv->tex = tex; - - /* Create a framebuffer object wrapping the texture so that we can render - * to it. - */ - pixmap_priv->gl_fbo = 1; - if (tex != 0) { - glamor_pixmap_ensure_fb(pixmap); - pixmap_priv->gl_tex = 1; - } else { - pixmap_priv->fb = 0; - pixmap_priv->gl_tex = 0; + if (fbo == NULL) { + ErrorF("XXX fail to create fbo.\n"); + return; } - pixmap->devPrivate.ptr = NULL; + glamor_pixmap_attach_fbo(pixmap, fbo); } void glamor_set_screen_pixmap(PixmapPtr screen_pixmap) { - ScreenPtr screen = screen_pixmap->drawable.pScreen; glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv; - glamor_priv = glamor_get_screen_private(screen); + glamor_priv = glamor_get_screen_private(screen_pixmap->drawable.pScreen); pixmap_priv = glamor_get_pixmap_private(screen_pixmap); - glamor_priv->screen_fbo = pixmap_priv->fb; + glamor_priv->screen_fbo = pixmap_priv->fbo->fb; + + pixmap_priv->fbo->width = screen_pixmap->drawable.width; + pixmap_priv->fbo->height = screen_pixmap->drawable.height; } PixmapPtr @@ -138,13 +127,15 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned int usage) { PixmapPtr pixmap; - GLenum format; - GLuint tex; glamor_pixmap_type_t type = GLAMOR_TEXTURE_ONLY; glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_pixmap_fbo *fbo; + int pitch; + int flag; + if (w > 32767 || h > 32767) return NullPixmap; @@ -153,62 +144,53 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, || usage == GLAMOR_CREATE_PIXMAP_CPU) { /* MESA can only support upto MAX_WIDTH*MAX_HEIGHT fbo. If we exceed such limitation, we have to use framebuffer. */ - type = GLAMOR_MEMORY; - pixmap = fbCreatePixmap(screen, w, h, depth, usage); + return fbCreatePixmap(screen, w, h, depth, usage); } else pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); pixmap_priv = calloc(1, sizeof(*pixmap_priv)); - dixSetPrivate(&pixmap->devPrivates, glamor_pixmap_private_key, + + if (!pixmap_priv) + return fbCreatePixmap(screen, w, h, depth, usage); + + dixSetPrivate(&pixmap->devPrivates, + glamor_pixmap_private_key, pixmap_priv); + pixmap_priv->container = pixmap; pixmap_priv->glamor_priv = glamor_priv; - pixmap_priv->type = type; - if (w == 0 || h == 0 || type == GLAMOR_MEMORY) + + if (w == 0 || h == 0) return pixmap; - gl_iformat_for_depth(depth, &format); - /* Create the texture used to store the pixmap's data. */ - 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); + fbo = glamor_create_fbo(glamor_priv, w, h, depth, 0); - glamor_set_pixmap_texture(pixmap, tex); + if (fbo == NULL) { + fbDestroyPixmap(pixmap); + free(pixmap_priv); + return fbCreatePixmap(screen, w, h, depth, usage); + } - screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, - (((w * - pixmap->drawable. - bitsPerPixel + 7) / 8) + - 3) & ~3, NULL); + glamor_pixmap_attach_fbo(pixmap, fbo); + pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3; + screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL); return pixmap; } void glamor_destroy_textured_pixmap(PixmapPtr pixmap) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; if (pixmap->refcnt == 1) { - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); + glamor_pixmap_private *pixmap_priv; + + pixmap_priv = glamor_get_pixmap_private(pixmap); if (pixmap_priv != NULL) { - if (pixmap_priv->fb) - dispatch->glDeleteFramebuffers(1, - &pixmap_priv->fb); - if (pixmap_priv->tex) - dispatch->glDeleteTextures(1, - &pixmap_priv->tex); - if (pixmap_priv->pbo) - dispatch->glDeleteBuffers(1, - &pixmap_priv->pbo); + glamor_pixmap_fbo *fbo; + fbo = glamor_pixmap_detach_fbo(pixmap_priv); + if (fbo) + glamor_destroy_fbo(fbo); free(pixmap_priv); } } @@ -238,6 +220,7 @@ _glamor_block_handler(void *data, OSTimePtr timeout, { glamor_gl_dispatch *dispatch = data; dispatch->glFlush(); + dispatch->glFinish(); } static void diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 4310a0479..a39c97001 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -79,7 +79,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, glamor_validate_pixmap(dst_pixmap); dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, - src_pixmap_priv->fb); + src_pixmap_priv->fbo->fb); glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, @@ -167,7 +167,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, goto fail; } - if (!src_pixmap_priv->gl_fbo) { + if (!src_pixmap_priv || !src_pixmap_priv->gl_fbo) { #ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n"); goto fail; @@ -175,6 +175,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src, src_status = glamor_upload_pixmap_to_texture(src_pixmap); if (src_status != GLAMOR_UPLOAD_DONE) goto fail; + + src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); #endif } else flush_needed = 1; @@ -199,8 +201,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); - - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); @@ -216,7 +216,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, - src_pixmap_priv->tex); + src_pixmap_priv->fbo->tex); #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); #endif @@ -333,7 +333,7 @@ _glamor_copy_n_to_n(DrawablePtr src, glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); - if (src_pixmap_priv->fb == dst_pixmap_priv->fb) { + if (src_pixmap_priv->fbo && src_pixmap_priv->fbo->fb == dst_pixmap_priv->fbo->fb) { int x_shift = abs(src_x_off - dx - dst_x_off); int y_shift = abs(src_y_off - dy - dst_y_off); for (i = 0; i < nbox; i++) { diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 8ce2104a1..f6f9e832c 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -49,7 +49,7 @@ glamor_get_drawable_location(const DrawablePtr drawable) glamor_get_screen_private(drawable->pScreen); if (pixmap_priv == NULL || pixmap_priv->gl_fbo == 0) return 'm'; - if (pixmap_priv->fb == glamor_priv->screen_fbo) + if (pixmap_priv->fbo->fb == glamor_priv->screen_fbo) return 's'; else return 'f'; @@ -271,13 +271,13 @@ glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode) glamor_restore_pixmap_to_texture(pixmap); } - if (pixmap_priv->pbo != 0 && pixmap_priv->pbo_valid) { + if (pixmap_priv->fbo->pbo != 0 && pixmap_priv->fbo->pbo_valid) { assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - pixmap_priv->pbo_valid = FALSE; - dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); - pixmap_priv->pbo = 0; + pixmap_priv->fbo->pbo_valid = FALSE; + dispatch->glDeleteBuffers(1, &pixmap_priv->fbo->pbo); + pixmap_priv->fbo->pbo = 0; } else { free(pixmap->devPrivate.ptr); } diff --git a/glamor/glamor_debug.h b/glamor/glamor_debug.h index b1017490e..ac7e69870 100644 --- a/glamor/glamor_debug.h +++ b/glamor/glamor_debug.h @@ -79,5 +79,8 @@ AbortServer(void) _glamor_priv_->delayed_fallback_string); \ _glamor_priv_->delayed_fallback_pending = 0; } } while(0) +#define DEBUGF(str, ...) +//#define DEBUGF(str, ...) ErrorF(str, ##__VA_ARGS__) + #endif diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c new file mode 100644 index 000000000..068d877d7 --- /dev/null +++ b/glamor/glamor_fbo.c @@ -0,0 +1,132 @@ +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "glamor_priv.h" + +glamor_pixmap_fbo * +glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, + int w, int h, int depth, GLint tex, int flag) +{ + glamor_gl_dispatch *dispatch; + glamor_pixmap_fbo *fbo; + GLenum format; + + fbo = calloc(1, sizeof(*fbo)); + if (fbo == NULL) + return NULL; + + gl_iformat_for_depth(depth, &format); + + fbo->tex = tex; + fbo->width = w; + fbo->height = h; + fbo->format = format; + fbo->glamor_priv = glamor_priv; + + glamor_pixmap_ensure_fb(fbo); + + return fbo; +} + +/* Make sure already detached from any pixmap. */ +void +glamor_destroy_fbo(glamor_pixmap_fbo *fbo) +{ + glamor_gl_dispatch *dispatch = &fbo->glamor_priv->dispatch; + + DEBUGF("Destroy fbo %p tex %d fb %d \n", fbo, fbo->tex, fbo->fb); + if (fbo->fb) + dispatch->glDeleteFramebuffers(1, &fbo->fb); + if (fbo->tex) + dispatch->glDeleteTextures(1, &fbo->tex); + if (fbo->pbo) + dispatch->glDeleteBuffers(1, &fbo->pbo); + + free(fbo); +} + +glamor_pixmap_fbo * +glamor_create_fbo(glamor_screen_private *glamor_priv, + int w, int h, int depth, int flag) +{ + glamor_gl_dispatch *dispatch; + glamor_pixmap_fbo *fbo; + GLenum format; + GLint tex; + + gl_iformat_for_depth(depth, &format); + dispatch = &glamor_priv->dispatch; + 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); + + fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, depth, tex, flag); + DEBUGF("Creat fbo %p tex %d width %d height %d \n", fbo, tex, w, h); + + return fbo; +} + +glamor_pixmap_fbo * +glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv) +{ + glamor_pixmap_fbo *fbo; + + if (pixmap_priv == NULL) + return NULL; + + fbo = pixmap_priv->fbo; + if (fbo == NULL) + return NULL; + + pixmap_priv->fbo = NULL; + return fbo; +} + +/* The pixmap must not be attached to another fbo. */ +void +glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo) +{ + glamor_pixmap_private *pixmap_priv; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (pixmap_priv == NULL) { + glamor_screen_private *glamor_priv; + glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); + pixmap_priv = calloc(1, sizeof(*pixmap_priv)); + dixSetPrivate(&pixmap->devPrivates, + glamor_pixmap_private_key, pixmap_priv); + pixmap_priv->container = pixmap; + pixmap_priv->glamor_priv = glamor_priv; + pixmap_priv->type = GLAMOR_MEMORY; + } + + if (pixmap_priv->fbo) + return; + + pixmap_priv->fbo = fbo; + + switch (pixmap_priv->type) { + case GLAMOR_TEXTURE_ONLY: + case GLAMOR_TEXTURE_DRM: + pixmap_priv->gl_fbo = 1; + if (fbo->tex != 0) + pixmap_priv->gl_tex = 1; + else { + /* XXX For the Xephyr only, may be broken now.*/ + pixmap_priv->gl_tex = 0; + } + pixmap->devPrivate.ptr = NULL; + break; + default: + break; + } +} diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 3ed3c5173..7c76496c8 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -89,7 +89,7 @@ void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) { glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; - dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fbo->fb); #ifndef GLAMOR_GLES2 dispatch->glMatrixMode(GL_PROJECTION); dispatch->glLoadIdentity(); @@ -97,8 +97,8 @@ glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) dispatch->glLoadIdentity(); #endif dispatch->glViewport(0, 0, - pixmap_priv->container->drawable.width, - pixmap_priv->container->drawable.height); + pixmap_priv->fbo->width, + pixmap_priv->fbo->height); } @@ -242,10 +242,10 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); } - if (pixmap_priv->pbo && pixmap_priv->pbo_valid) { + if (pixmap_priv->fbo->pbo && pixmap_priv->fbo->pbo_valid) { texels = NULL; dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, - pixmap_priv->pbo); + pixmap_priv->fbo->pbo); } else texels = pixmap->devPrivate.ptr; @@ -309,7 +309,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, * to the fbo directly. */ if (no_alpha == 0 && no_revert == 1 && !need_flip) { __glamor_upload_pixmap_to_texture(pixmap, format, type, - pixmap_priv->tex); + pixmap_priv->fbo->tex); return; } @@ -363,19 +363,18 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, } void -glamor_pixmap_ensure_fb(PixmapPtr pixmap) +glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo) { int status; - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); - glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; - if (pixmap_priv->fb == 0) - dispatch->glGenFramebuffers(1, &pixmap_priv->fb); - assert(pixmap_priv->tex != 0); - dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); + glamor_gl_dispatch *dispatch = &fbo->glamor_priv->dispatch; + + 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, pixmap_priv->tex, + GL_TEXTURE_2D, fbo->tex, 0); status = dispatch->glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { @@ -422,11 +421,13 @@ static int glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) { int need_fbo; - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_pixmap_private *pixmap_priv; + glamor_screen_private *glamor_priv; + GLenum format; + glamor_pixmap_fbo *fbo; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); if (!glamor_check_fbo_size (glamor_priv, pixmap->drawable.width, pixmap->drawable.height) @@ -441,28 +442,14 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) if (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return 0; - if (no_alpha != 0 || no_revert == 0 || !glamor_priv->yInverted) - need_fbo = 1; - else - need_fbo = 0; + fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, + pixmap->drawable.height, + pixmap->drawable.depth, + 0); + if (fbo == NULL) + return -1; - if (pixmap_priv->tex == 0) - dispatch->glGenTextures(1, &pixmap_priv->tex); - - if (need_fbo) { - dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->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, GL_RGBA, - pixmap->drawable.width, - pixmap->drawable.height, 0, GL_RGBA, - GL_UNSIGNED_BYTE, NULL); - glamor_pixmap_ensure_fb(pixmap); - } + glamor_pixmap_attach_fbo(pixmap, fbo); return 0; } @@ -575,7 +562,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); - dispatch->glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->tex); + dispatch->glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->fbo->tex); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -599,7 +586,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glBindTexture(GL_TEXTURE_2D, source_priv->tex); + dispatch->glBindTexture(GL_TEXTURE_2D, source_priv->fbo->tex); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -726,11 +713,11 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) } if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - if (pixmap_priv->pbo == 0) + if (pixmap_priv->fbo->pbo == 0) dispatch->glGenBuffers(1, - &pixmap_priv->pbo); + &pixmap_priv->fbo->pbo); dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, - pixmap_priv->pbo); + pixmap_priv->fbo->pbo); dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, stride * pixmap->drawable.height, @@ -740,7 +727,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) format, type, 0); data = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, gl_access); - pixmap_priv->pbo_valid = TRUE; + pixmap_priv->fbo->pbo_valid = TRUE; if (!glamor_priv->yInverted) { assert(glamor_priv->gl_flavor == @@ -762,11 +749,11 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) data = malloc(stride * pixmap->drawable.height); assert(data); if (access != GLAMOR_ACCESS_WO) { - if (pixmap_priv->pbo == 0) + if (pixmap_priv->fbo->pbo == 0) dispatch->glGenBuffers(1, - &pixmap_priv->pbo); + &pixmap_priv->fbo->pbo); dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, - pixmap_priv->pbo); + pixmap_priv->fbo->pbo); dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, stride * pixmap->drawable.height, @@ -783,9 +770,9 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) y - 1) * stride, stride); dispatch->glUnmapBuffer(GL_PIXEL_PACK_BUFFER); dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - pixmap_priv->pbo_valid = FALSE; - dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); - pixmap_priv->pbo = 0; + pixmap_priv->fbo->pbo_valid = FALSE; + dispatch->glDeleteBuffers(1, &pixmap_priv->fbo->pbo); + pixmap_priv->fbo->pbo = 0; } } @@ -798,29 +785,3 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) return TRUE; } - - - -static void -_glamor_destroy_upload_pixmap(PixmapPtr pixmap) -{ - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); - glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; - - assert(pixmap_priv->gl_fbo == 0); - if (pixmap_priv->fb) - dispatch->glDeleteFramebuffers(1, &pixmap_priv->fb); - if (pixmap_priv->tex) - dispatch->glDeleteTextures(1, &pixmap_priv->tex); - if (pixmap_priv->pbo) - dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); - pixmap_priv->fb = pixmap_priv->tex = pixmap_priv->pbo = 0; - -} - -void -glamor_destroy_upload_pixmap(PixmapPtr pixmap) -{ - _glamor_destroy_upload_pixmap(pixmap); -} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 90ed6bb40..b4c3b74af 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -59,6 +59,8 @@ #include "glamor_debug.h" +#include + typedef struct glamor_composite_shader { GLuint prog; GLint dest_to_dest_uniform_location; @@ -123,6 +125,7 @@ enum glamor_gl_flavor { }; #define GLAMOR_CREATE_PIXMAP_CPU 0x100 +#define GLAMOR_CREATE_PIXMAP_FIXUP 0x101 #define GLAMOR_NUM_GLYPH_CACHE_FORMATS 2 @@ -156,6 +159,10 @@ struct glamor_saved_procs { UnrealizeGlyphProcPtr unrealize_glyph; }; +#define CACHE_FORMAT_COUNT 2 +#define CACHE_BUCKET_WCOUNT 16 +#define CACHE_BUCKET_HCOUNT 16 + typedef struct glamor_screen_private { struct glamor_gl_dispatch dispatch; int yInverted; @@ -238,15 +245,25 @@ typedef union _glamor_pending_op { * @container: The corresponding pixmap's pointer. **/ -typedef struct glamor_pixmap_private { - glamor_pixmap_type_t type; - unsigned char gl_fbo:1; - unsigned char gl_tex:1; - unsigned char pbo_valid:1; - unsigned char is_picture:1; +typedef struct glamor_pixmap_fbo { + unsigned char pbo_valid; GLuint tex; GLuint fb; GLuint pbo; + int width; + int height; + GLenum format; + GLenum type; + glamor_screen_private *glamor_priv; +} glamor_pixmap_fbo; + + +typedef struct glamor_pixmap_private { + unsigned char gl_fbo:1; + unsigned char is_picture:1; + unsigned char gl_tex:1; + glamor_pixmap_type_t type; + glamor_pixmap_fbo *fbo; PictFormatShort pict_format; glamor_pending_op pending_op; PixmapPtr container; @@ -311,6 +328,23 @@ PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, Bool glamor_destroy_pixmap(PixmapPtr pixmap); +glamor_pixmap_fbo* glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv); +void glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo); +glamor_pixmap_fbo * glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, + int w, int h, int depth, GLint tex, int flag); +glamor_pixmap_fbo * glamor_create_fbo(glamor_screen_private *glamor_priv, + int w, int h, int depth, int flag); +void glamor_destroy_fbo(glamor_pixmap_fbo *fbo); + +Bool glamor_pixmap_fbo_fixup(ScreenPtr screen, PixmapPtr pixmap); + +Bool glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv); + +#define GLAMOR_CACHE_GET_DEFAULT 0 +#define GLAMOR_CACHE_GET_EAXCT_SIZE 1 +#define GLAMOR_CACHE_GET_UPLOAD 2 + + /* glamor_copyarea.c */ RegionPtr glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, @@ -503,14 +537,14 @@ Bool glamor_download_pixmap_to_cpu(PixmapPtr pixmap, **/ void glamor_restore_pixmap_to_texture(PixmapPtr pixmap); /** - * Ensure to have a fbo attached to the pixmap. - * If the pixmap already has one fbo then do nothing. - * Otherwise, it will generate a new fbo, and bind - * the pixmap's texture to the fbo. - * The pixmap must has a valid texture before call this + * Ensure to have a fbo has a valid/complete glfbo. + * 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(PixmapPtr pixmap); +void glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo); /** * Upload a pixmap to gl texture. Used by dynamic pixmap diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 6a7057afb..99b60c660 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -388,7 +388,7 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; dispatch->glActiveTexture(GL_TEXTURE0 + unit); - dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); + dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->fbo->tex); switch (picture->repeatType) { case RepeatNone: #ifndef GLAMOR_GLES2 @@ -923,18 +923,16 @@ glamor_composite_with_shader(CARD8 op, mask_status = GLAMOR_NONE; } - source_status = glamor_upload_picture_to_texture(source); + source_status = glamor_upload_picture_to_texture(source); if (source_status != GLAMOR_UPLOAD_DONE) { glamor_fallback ("Failed to upload source texture.\n"); goto fail; } } else { - if (source_status == GLAMOR_UPLOAD_PENDING) { - source_status = - glamor_upload_picture_to_texture(source); + source_status = glamor_upload_picture_to_texture(source); if (source_status != GLAMOR_UPLOAD_DONE) { glamor_fallback ("Failed to upload source texture.\n"); @@ -943,9 +941,7 @@ glamor_composite_with_shader(CARD8 op, } if (mask_status == GLAMOR_UPLOAD_PENDING) { - mask_status = - glamor_upload_picture_to_texture(mask); - + mask_status = glamor_upload_picture_to_texture(mask); if (mask_status != GLAMOR_UPLOAD_DONE) { glamor_fallback ("Failed to upload mask texture.\n"); @@ -1208,22 +1204,14 @@ _glamor_composite(CARD8 op, if (source->pDrawable) { source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); - if (!source_pixmap_priv) { - glamor_set_pixmap_type(source_pixmap, GLAMOR_MEMORY); - source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); - } - if (source_pixmap_priv->type == GLAMOR_DRM_ONLY) + if (source_pixmap_priv && source_pixmap_priv->type == GLAMOR_DRM_ONLY) goto fail; } if (mask && mask->pDrawable) { mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); - if (!mask_pixmap_priv) { - glamor_set_pixmap_type(mask_pixmap, GLAMOR_MEMORY); - mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); - } - if (mask_pixmap_priv->type == GLAMOR_DRM_ONLY) + if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_DRM_ONLY) goto fail; } if ((!source->pDrawable diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index f5a6e759f..9dadf5e47 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -156,7 +156,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, - src_pixmap_priv->tex); + src_pixmap_priv->fbo->tex); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 491a1ca2e..c7d1c2943 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -13,12 +13,11 @@ #define t_from_x_coord_y_inverted(_yscale_, _y_) ((_y_) * (_yscale_)) #define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ - do { \ - *(_pxscale_) = 1.0 / (_pixmap_priv_)->container->drawable.width; \ - *(_pyscale_) = 1.0 / (_pixmap_priv_)->container->drawable.height; \ + do { \ + *(_pxscale_) = 1.0 / (_pixmap_priv_)->fbo->width; \ + *(_pyscale_) = 1.0 / (_pixmap_priv_)->fbo->height; \ } while(0) - #define xFixedToFloat(_val_) ((float)xFixedToInt(_val_) \ + ((float)xFixedFrac(_val_) / 65536.0))