int glamor_set_destination_pixmap_priv(glamor_pixmap_private *pixmap_priv) { if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return -1; glamor_set_destination_pixmap_priv_nc(pixmap_priv); return 0; }
static void _glamor_tile(PixmapPtr pixmap, PixmapPtr tile, int x, int y, int width, int height, int tile_x, int tile_y) { ScreenPtr screen = pixmap->drawable.pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); int x1 = x; int x2 = x + width; int y1 = y; int y2 = y + height; int tile_x1 = tile_x; int tile_x2 = tile_x + width; int tile_y1 = tile_y; int tile_y2 = tile_y + height; float vertices[8]; float source_texcoords[8]; GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; glamor_pixmap_private *src_pixmap_priv; glamor_pixmap_private *dst_pixmap_priv; float wh[4]; src_pixmap_priv = glamor_get_pixmap_private(tile); dst_pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); glamor_make_current(glamor_priv); glUseProgram(glamor_priv->tile_prog); glamor_pixmap_fbo_fix_wh_ratio(wh, src_pixmap_priv); glUniform2fv(glamor_priv->tile_wh, 1, wh); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->base.fbo->tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glamor_set_repeat_normalize_tcoords (src_pixmap_priv, RepeatNormal, src_xscale, src_yscale, tile_x1, tile_y1, tile_x2, tile_y2, glamor_priv->yInverted, source_texcoords); glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), source_texcoords); glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, dst_yscale, x1, y1, x2, y2, glamor_priv->yInverted, vertices); glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); glamor_priv->state = RENDER_STATE; glamor_priv->render_idle_cnt = 0; }
static Bool glamor_copy_n_to_n_textured(DrawablePtr src, DrawablePtr dst, GCPtr gc, BoxPtr box, int nbox, int dx, int dy) { glamor_screen_private *glamor_priv = glamor_get_screen_private(dst->pScreen); glamor_gl_dispatch *dispatch; PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); int i; float vertices[8], texcoords[8]; glamor_pixmap_private *src_pixmap_priv; glamor_pixmap_private *dst_pixmap_priv; int src_x_off, src_y_off, dst_x_off, dst_y_off; GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); if (!src_pixmap_priv->base.gl_fbo) { /* Optimize when the source doesn't have an FBO, just upload the data directly to the dest FBO */ int src_stride = src_pixmap->devKind; int bpp = src_pixmap->drawable.bitsPerPixel; void *src_data = NULL; if (src->bitsPerPixel != dst->bitsPerPixel) { DEBUGF("Non-matching bpp\n"); return FALSE; } if (src->bitsPerPixel < 8) { DEBUGF("bpp < 8\n"); return FALSE; } if (gc && !(gc->alu == GXcopy && glamor_pm_is_solid(src, gc->planemask))) { DEBUGF("non gxcopy and solid\n"); return FALSE; } for (i = 0; i < nbox; i++) { int x = box[i].x1 + dst_x_off; int y = box[i].y1 + dst_y_off; int w = box[i].x2 - box[i].x1; int h = box[i].y2 - box[i].y1; src_data = (char *)src_pixmap->devPrivate.ptr + (box[i].y1 + dy + src_y_off) * src_stride + (box[i].x1 + dx + src_x_off) * (bpp / 8); if (!glamor_upload_sub_pixmap_to_texture(dst_pixmap, x, y, w, h, src_stride, src_data, 0)) { ErrorF("Failed to upload the sub pixmap to dst\n"); return FALSE; } } return TRUE; } pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); dispatch = glamor_get_dispatch(glamor_priv); glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); dx += src_x_off; dy += src_y_off; dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->base.fbo->tex); #ifndef GLAMOR_GLES2 dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); #endif dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), texcoords); dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glUseProgram(glamor_priv->finish_access_prog[0]); dispatch->glUniform1i(glamor_priv->finish_access_revert[0], REVERT_NONE); dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0], SWAP_NONE_UPLOADING); for (i = 0; i < nbox; i++) { glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, dst_yscale, box[i].x1 + dst_x_off, box[i].y1 + dst_y_off, box[i].x2 + dst_x_off, box[i].y2 + dst_y_off, glamor_priv->yInverted, vertices); glamor_set_normalize_tcoords(src_pixmap_priv, src_xscale, src_yscale, box[i].x1 + dx, box[i].y1 + dy, box[i].x2 + dx, box[i].y2 + dy, glamor_priv->yInverted, texcoords); dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); /* The source texture is bound to a fbo, we have to flush it here. */ glamor_put_dispatch(glamor_priv); glamor_priv->state = RENDER_STATE; glamor_priv->render_idle_cnt = 0; return TRUE; }
static void _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color) { ScreenPtr screen = pixmap->drawable.pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); GLfloat xscale, yscale; float vertices[32]; float *pvertices = vertices; int valid_nbox = ARRAY_SIZE(vertices); glamor_set_destination_pixmap_priv_nc(pixmap_priv); glamor_get_context(glamor_priv); glUseProgram(glamor_priv->solid_prog); glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color); pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale); if (_X_UNLIKELY(nbox * 4 * 2 > ARRAY_SIZE(vertices))) { int allocated_box; if (nbox * 6 > GLAMOR_COMPOSITE_VBO_VERT_CNT) { allocated_box = GLAMOR_COMPOSITE_VBO_VERT_CNT / 6; } else allocated_box = nbox; pvertices = malloc(allocated_box * 4 * 2 * sizeof(float)); if (pvertices) valid_nbox = allocated_box; else { pvertices = vertices; valid_nbox = ARRAY_SIZE(vertices) / (4 * 2); } } if (_X_UNLIKELY(nbox > 1)) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), pvertices); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); while (nbox) { int box_cnt, i; float *valid_vertices; valid_vertices = pvertices; box_cnt = nbox > valid_nbox ? valid_nbox : nbox; for (i = 0; i < box_cnt; i++) { glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale, box[i].x1, box[i].y1, box[i].x2, box[i].y2, glamor_priv->yInverted, valid_vertices); valid_vertices += 4 * 2; } if (box_cnt == 1) glDrawArrays(GL_TRIANGLE_FAN, 0, box_cnt * 4); else { if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { glDrawRangeElements(GL_TRIANGLES, 0, box_cnt * 4, box_cnt * 6, GL_UNSIGNED_SHORT, NULL); } else { glDrawElements(GL_TRIANGLES, box_cnt * 6, GL_UNSIGNED_SHORT, NULL); } } nbox -= box_cnt; box += box_cnt; } if (pvertices != vertices) free(pvertices); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); glUseProgram(0); glamor_put_context(glamor_priv); glamor_priv->state = RENDER_STATE; glamor_priv->render_idle_cnt = 0; }
static Bool _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum type, int no_alpha, int revert, int swap_rb, int x, int y, int w, int h, int stride, void *bits, int pbo) { ScreenPtr screen = pixmap->drawable.pScreen; glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); static float vertices[8]; static float texcoords_inv[8] = { 0, 0, 1, 0, 1, 1, 0, 1 }; float *ptexcoords; float dst_xscale, dst_yscale; GLuint tex = 0; int need_free_bits = 0; if (bits == NULL) goto ready_to_upload; if (revert > REVERT_NORMAL) { /* XXX if we are restoring the pixmap, then we may not need to allocate * new buffer */ void *converted_bits; if (pixmap->drawable.depth == 1) stride = (((w * 8 + 7) / 8) + 3) & ~3; converted_bits = xallocarray(h, stride); if (converted_bits == NULL) return FALSE; bits = glamor_color_convert_to_bits(bits, converted_bits, w, h, stride, no_alpha, revert, swap_rb); if (bits == NULL) { free(converted_bits); ErrorF("Failed to convert pixmap no_alpha %d," "revert mode %d, swap mode %d\n", no_alpha, revert, swap_rb); return FALSE; } no_alpha = 0; revert = REVERT_NONE; swap_rb = SWAP_NONE_UPLOADING; need_free_bits = TRUE; } ready_to_upload: /* Try fast path firstly, upload the pixmap to the texture attached * to the fbo directly. */ if (no_alpha == 0 && revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING #ifdef WALKAROUND_LARGE_TEXTURE_MAP && glamor_pixmap_priv_is_small(pixmap_priv) #endif ) { int fbo_x_off, fbo_y_off; assert(pixmap_priv->fbo->tex); pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off); assert(x + fbo_x_off >= 0 && y + fbo_y_off >= 0); assert(x + fbo_x_off + w <= pixmap_priv->fbo->width); assert(y + fbo_y_off + h <= pixmap_priv->fbo->height); __glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->fbo->tex, format, type, x + fbo_x_off, y + fbo_y_off, w, h, bits, pbo); } else { ptexcoords = texcoords_inv; pixmap_priv_get_dest_scale(pixmap, pixmap_priv, &dst_xscale, &dst_yscale); glamor_set_normalize_vcoords(pixmap_priv, dst_xscale, dst_yscale, x, y, x + w, y + h, vertices); /* Slow path, we need to flip y or wire alpha to 1. */ glamor_make_current(glamor_priv); glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), ptexcoords); glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); glamor_set_destination_pixmap_priv_nc(glamor_priv, pixmap, pixmap_priv); glamor_set_alu(screen, GXcopy); __glamor_upload_pixmap_to_texture(pixmap, &tex, format, type, 0, 0, w, h, bits, pbo); glActiveTexture(GL_TEXTURE0); 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); glUseProgram(glamor_priv->finish_access_prog[no_alpha]); glUniform1i(glamor_priv->finish_access_revert[no_alpha], revert); glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); glDeleteTextures(1, &tex); glBindFramebuffer(GL_FRAMEBUFFER, 0); } if (need_free_bits) free(bits); return TRUE; }