_X_EXPORT void glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex) { ScreenPtr screen = pixmap->drawable.pScreen; glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv; glamor_pixmap_fbo *fbo; GLenum format; glamor_priv = glamor_get_screen_private(screen); pixmap_priv = glamor_get_pixmap_private(pixmap); if (pixmap_priv->base.fbo) { fbo = glamor_pixmap_detach_fbo(pixmap_priv); glamor_destroy_fbo(fbo); } format = gl_iformat_for_pixmap(pixmap); fbo = glamor_create_fbo_from_tex(glamor_priv, pixmap->drawable.width, pixmap->drawable.height, format, tex, 0); if (fbo == NULL) { ErrorF("XXX fail to create fbo.\n"); return; } glamor_pixmap_attach_fbo(pixmap, fbo); }
/** * Upload pixmap to a specified texture. * This texture may not be the one attached to it. **/ static Bool __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex, GLenum format, GLenum type, int x, int y, int w, int h, void *bits, int pbo) { glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); int non_sub = 0; unsigned int iformat = 0; glamor_make_current(glamor_priv); if (*tex == 0) { glGenTextures(1, tex); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) iformat = gl_iformat_for_pixmap(pixmap); else iformat = format; non_sub = 1; assert(x == 0 && y == 0); } glBindTexture(GL_TEXTURE_2D, *tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); assert(pbo || bits != 0); if (bits == NULL) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); } glamor_priv->suppress_gl_out_of_memory_logging = true; if (non_sub) glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, format, type, bits); else glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, format, type, bits); glamor_priv->suppress_gl_out_of_memory_logging = false; if (glGetError() == GL_OUT_OF_MEMORY) { if (non_sub) { glDeleteTextures(1, tex); *tex = 0; } return FALSE; } if (bits == NULL) glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); return TRUE; }
/* * Prepare to upload a pixmap to texture memory. * no_alpha equals 1 means the format needs to wire alpha to 1. */ static int glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int revert, int swap_rb) { int flag = 0; glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv; glamor_pixmap_fbo *fbo; GLenum iformat; pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); if (pixmap_priv->base.gl_fbo != GLAMOR_FBO_UNATTACHED) return 0; if (pixmap_priv->base.fbo && (pixmap_priv->base.fbo->width < pixmap->drawable.width || pixmap_priv->base.fbo->height < pixmap->drawable.height)) { fbo = glamor_pixmap_detach_fbo(pixmap_priv); glamor_destroy_fbo(fbo); } if (pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb) return 0; if (!(no_alpha || (revert == REVERT_NORMAL) || (swap_rb != SWAP_NONE_UPLOADING))) { /* We don't need a fbo, a simple texture uploading should work. */ flag = GLAMOR_CREATE_FBO_NO_FBO; } if ((flag == GLAMOR_CREATE_FBO_NO_FBO && pixmap_priv->base.fbo && pixmap_priv->base.fbo->tex) || (flag == 0 && pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb)) return 0; if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) iformat = gl_iformat_for_pixmap(pixmap); else iformat = format; if (!glamor_pixmap_ensure_fbo(pixmap, iformat, flag)) return -1; return 0; }
PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned int usage) { PixmapPtr pixmap; glamor_pixmap_type_t type = GLAMOR_TEXTURE_ONLY; glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_pixmap_fbo *fbo = NULL; int pitch; GLenum format; if (w > 32767 || h > 32767) return NullPixmap; if ((usage == GLAMOR_CREATE_PIXMAP_CPU || (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 64 && h <= 64) || (w == 0 && h == 0) || !glamor_check_pixmap_fbo_depth(depth)) || (!GLAMOR_TEXTURED_LARGE_PIXMAP && !glamor_check_fbo_size(glamor_priv, w, h))) return fbCreatePixmap(screen, w, h, depth, usage); else pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); pixmap_priv = calloc(1, sizeof(*pixmap_priv)); if (!pixmap_priv) { fbDestroyPixmap(pixmap); return fbCreatePixmap(screen, w, h, depth, usage); } glamor_set_pixmap_private(pixmap, pixmap_priv); if (usage == GLAMOR_CREATE_PIXMAP_MAP) type = GLAMOR_MEMORY_MAP; pixmap_priv->base.pixmap = pixmap; pixmap_priv->base.glamor_priv = glamor_priv; format = gl_iformat_for_pixmap(pixmap); pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3; screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL); if (usage == GLAMOR_CREATE_PIXMAP_NO_TEXTURE) { pixmap_priv->type = GLAMOR_TEXTURE_ONLY; pixmap_priv->base.box.x1 = 0; pixmap_priv->base.box.y1 = 0; pixmap_priv->base.box.x2 = w; pixmap_priv->base.box.y2 = h; return pixmap; } else if (type == GLAMOR_MEMORY_MAP || usage == GLAMOR_CREATE_NO_LARGE || glamor_check_fbo_size(glamor_priv, w, h)) { pixmap_priv->type = type; pixmap_priv->base.box.x1 = 0; pixmap_priv->base.box.y1 = 0; pixmap_priv->base.box.x2 = w; pixmap_priv->base.box.y2 = h; fbo = glamor_create_fbo(glamor_priv, w, h, format, usage); } else { int tile_size = glamor_priv->max_fbo_size; DEBUGF("Create LARGE pixmap %p width %d height %d, tile size %d\n", pixmap, w, h, tile_size); pixmap_priv->type = GLAMOR_TEXTURE_LARGE; fbo = glamor_create_fbo_array(glamor_priv, w, h, format, usage, tile_size, tile_size, pixmap_priv); } if (fbo == NULL) { fbDestroyPixmap(pixmap); free(pixmap_priv); return fbCreatePixmap(screen, w, h, depth, usage); } glamor_pixmap_attach_fbo(pixmap, fbo); return pixmap; }