diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 8f6292020..53877dcbe 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -31,6 +31,8 @@ libglamor_la_SOURCES = \ glamor_render.c \ glamor_tile.c \ glamor_triangles.c\ + glamor_pixmap.c\ + glamor_picture.c\ glamor.h libglamor_la_LIBADD = \ glu3/libglu3.la diff --git a/glamor/glamor.c b/glamor/glamor.c index d6d6d950a..c10ff4021 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -59,8 +59,7 @@ glamor_get_drawable_pixmap(DrawablePtr drawable) return (PixmapPtr)drawable; } - -void +static void glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) { ScreenPtr screen = pixmap->drawable.pScreen; @@ -73,6 +72,8 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) /* Create a framebuffer object wrapping the texture so that we can render * to it. */ + pixmap_priv->gl_fbo = 1; + pixmap_priv->gl_tex = 1; glGenFramebuffersEXT(1, &pixmap_priv->fb); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, @@ -87,13 +88,24 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) NULL); } +/* Set screen pixmap. If tex equal to 0, means it is called from ephyr. */ +void +glamor_set_screen_pixmap_texture(ScreenPtr screen, int w, int h, unsigned int tex) +{ + PixmapPtr pixmap = screen->GetScreenPixmap(screen); + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + glamor_set_pixmap_texture(pixmap, w, h, tex); + glamor_priv->screen_fbo = pixmap_priv->fb; +} + + + +#define GLAMOR_PIXMAP_MEMORY 0 +#define GLAMOR_PIXMAP_TEXTURE 1 + -/* XXX For the screen pixmap, the w and h maybe 0,0 too, but it should - * be GLAMOR_GL pixmap. Now, all the pixmap will have a valid pixmap_priv. - * This is not good enough. After we can identify which is the screen - * pixmap and which is not, then we can split the pixmap to exclusive - * two types GLAMOR_GL and GLAMOR_FB, and for those GLAMOR_FB pixmaps, - * we don't need to allocate pixmap_priv. */ static PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, @@ -102,22 +114,24 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, PixmapPtr pixmap; GLenum format; GLuint tex; - enum glamor_pixmap_type type = GLAMOR_GL; + int type = GLAMOR_PIXMAP_TEXTURE; + glamor_pixmap_private *pixmap_priv; if (w > 32767 || h > 32767) return NullPixmap; - if (w > MAX_WIDTH || h > MAX_HEIGHT || ( depth == 1 && w != 0 && h != 0)) { + if (!glamor_check_fbo_width_height(w,h) || !glamor_check_fbo_depth(depth)) { /* MESA can only support upto MAX_WIDTH*MAX_HEIGHT fbo. If we exceed such limitation, we have to use framebuffer.*/ - type = GLAMOR_FB; + type = GLAMOR_PIXMAP_MEMORY; pixmap = fbCreatePixmap (screen, w, h, depth, usage); screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3, NULL); - glamor_fallback("fallback to software fb for pixmap %p , %d x %d depth %d\n", pixmap, w, h, depth); + glamor_fallback("choose cpu memory for pixmap %p ," + " %d x %d depth %d\n", pixmap, w, h, depth); } else pixmap = fbCreatePixmap (screen, 0, 0, depth, usage); @@ -127,7 +141,10 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, return NullPixmap; } - if (w == 0 || h == 0 || type == GLAMOR_FB) + pixmap_priv = glamor_get_pixmap_private(pixmap); + pixmap_priv->container = pixmap; + + if (w == 0 || h == 0 || type == GLAMOR_PIXMAP_MEMORY) return pixmap; /* We should probably take advantage of ARB_fbo's allowance of GL_ALPHA. @@ -136,7 +153,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, switch (depth) { case 24: format = GL_RGB; - break; + break; default: format = GL_RGBA; break; @@ -154,13 +171,51 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, return pixmap; } + +/** + * For Xephyr use only. set up the screen pixmap to correct state. + **/ +static PixmapPtr +glamor_create_screen_pixmap(ScreenPtr screen, int w, int h, int depth, + unsigned int usage) +{ + PixmapPtr pixmap; + glamor_pixmap_private *pixmap_priv; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + assert(w ==0 && h == 0); + + glamor_priv->screen_fbo = 0; + pixmap = fbCreatePixmap (screen, 0, 0, depth, usage); + + if (dixAllocatePrivates(&pixmap->devPrivates, PRIVATE_PIXMAP) != TRUE) { + fbDestroyPixmap(pixmap); + ErrorF("Fail to allocate privates for PIXMAP.\n"); + return NullPixmap; + } + + pixmap_priv = glamor_get_pixmap_private(pixmap); + pixmap_priv->tex = 0; + pixmap_priv->gl_fbo = 1; + pixmap_priv->gl_tex = 1; + + screen->CreatePixmap = glamor_create_pixmap; + return pixmap; +} + + + + static Bool glamor_destroy_pixmap(PixmapPtr pixmap) { if (pixmap->refcnt == 1) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - glDeleteFramebuffersEXT(1, &pixmap_priv->fb); - glDeleteTextures(1, &pixmap_priv->tex); + if (pixmap_priv->fb) + glDeleteFramebuffersEXT(1, &pixmap_priv->fb); + if (pixmap_priv->tex) + glDeleteTextures(1, &pixmap_priv->tex); + if (pixmap_priv->pbo) + glDeleteBuffersARB(1, &pixmap_priv->pbo); } return fbDestroyPixmap(pixmap); @@ -177,6 +232,18 @@ glamor_wakeup_handler(void *data, int result, void *last_select_mask) { } +static void +glamor_set_debug_level(int *debug_level) +{ + char *debug_level_string; + debug_level_string = getenv("GLAMOR_DEBUG"); + if (debug_level_string && sscanf(debug_level_string, "%d", debug_level) == 1) + return; + *debug_level = 0; +} + +int glamor_debug_level; + /** Set up glamor for an already-configured GL context. */ Bool glamor_init(ScreenPtr screen, unsigned int flags) @@ -186,7 +253,6 @@ glamor_init(ScreenPtr screen, unsigned int flags) #ifdef RENDER PictureScreenPtr ps = GetPictureScreenIfSet(screen); #endif - if (flags & ~GLAMOR_VALID_FLAGS) { ErrorF("glamor_init: Invalid flags %x\n", flags); return FALSE; @@ -205,7 +271,9 @@ glamor_init(ScreenPtr screen, unsigned int flags) LogMessage(X_WARNING, "glamor%d: Failed to allocate screen private\n", screen->myNum); + return FALSE; } + dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, glamor_priv); if (!dixRegisterPrivateKey(glamor_pixmap_private_key,PRIVATE_PIXMAP, @@ -213,6 +281,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) LogMessage(X_WARNING, "glamor%d: Failed to allocate pixmap private\n", screen->myNum); + return FALSE; } glewInit(); @@ -243,7 +312,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) goto fail; } - + glamor_set_debug_level(&glamor_debug_level); glamor_priv->saved_close_screen = screen->CloseScreen; screen->CloseScreen = glamor_close_screen; @@ -251,7 +320,11 @@ glamor_init(ScreenPtr screen, unsigned int flags) screen->CreateGC = glamor_create_gc; glamor_priv->saved_create_pixmap = screen->CreatePixmap; - screen->CreatePixmap = glamor_create_pixmap; + + if (flags & GLAMOR_HOSTX) + screen->CreatePixmap = glamor_create_screen_pixmap; + else + screen->CreatePixmap = glamor_create_pixmap; glamor_priv->saved_destroy_pixmap = screen->DestroyPixmap; screen->DestroyPixmap = glamor_destroy_pixmap; @@ -281,6 +354,10 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_priv->saved_triangles = ps->Triangles; ps->Triangles = glamor_triangles; glamor_init_composite_shaders(screen); + glamor_priv->saved_create_picture = ps->CreatePicture; + ps->CreatePicture = glamor_create_picture; + glamor_priv->saved_destroy_picture = ps->DestroyPicture; + ps->DestroyPicture = glamor_destroy_picture; #endif glamor_init_solid_shader(screen); glamor_init_tile_shader(screen); @@ -288,7 +365,6 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_init_finish_access_shaders(screen); glamor_glyphs_init(screen); - return TRUE; fail: @@ -319,6 +395,7 @@ glamor_close_screen(int idx, ScreenPtr screen) ps->Trapezoids = glamor_priv->saved_trapezoids; ps->Glyphs = glamor_priv->saved_glyphs; ps->Triangles = glamor_priv->saved_triangles; + ps->CreatePicture = glamor_priv->saved_create_picture; } #endif free(glamor_priv); diff --git a/glamor/glamor.h b/glamor/glamor.h index c49662e89..2c1b241ba 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -39,9 +39,10 @@ #endif /* GLAMOR_H */ -#define GLAMOR_INVERTED_Y_AXIS 0x1 -#define GLAMOR_VALID_FLAGS (GLAMOR_INVERTED_Y_AXIS) +#define GLAMOR_INVERTED_Y_AXIS 1 +#define GLAMOR_HOSTX 2 +#define GLAMOR_VALID_FLAGS (GLAMOR_INVERTED_Y_AXIS | GLAMOR_HOSTX) Bool glamor_init(ScreenPtr screen, unsigned int flags); void glamor_fini(ScreenPtr screen); -void glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex); +void glamor_set_screen_pixmap_texture(ScreenPtr screen, int w, int h, unsigned int tex); diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 07d8b1456..766c9e2b3 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -31,7 +31,6 @@ * * GC CopyArea implementation */ - static Bool glamor_copy_n_to_n_fbo_blit(DrawablePtr src, DrawablePtr dst, @@ -49,45 +48,36 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, int dst_x_off, dst_y_off, src_x_off, src_y_off, i; if (src == dst) { - glamor_delayed_fallback(screen, "glamor_copy_n_to_n_fbo_blit(): " - "src == dest\n"); + glamor_delayed_fallback(screen,"src == dest\n"); return FALSE; } if (!GLEW_EXT_framebuffer_blit) { - glamor_delayed_fallback(screen, "glamor_copy_n_to_n_fbo_blit(): " - "no EXT_framebuffer_blit\n"); + glamor_delayed_fallback(screen,"no EXT_framebuffer_blit\n"); return FALSE; } src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); - if (src_pixmap_priv->fb == 0) { - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); - - if (src_pixmap != screen_pixmap) { - glamor_delayed_fallback(screen, "glamor_copy_n_to_n_fbo_blit(): " - "no src fbo\n"); - return FALSE; - } - } - if (gc) { if (gc->alu != GXcopy) { - glamor_delayed_fallback(screen, "glamor_copy_n_to_n_fbo_blit(): " - "non-copy ALU\n"); + glamor_delayed_fallback(screen, "non-copy ALU\n"); return FALSE; } if (!glamor_pm_is_solid(dst, gc->planemask)) { - glamor_delayed_fallback(screen, "glamor_copy_n_to_n_fbo_blit(): " - "non-solid planemask\n"); + glamor_delayed_fallback(screen, "non-solid planemask\n"); return FALSE; } } - if (!glamor_set_destination_pixmap(dst_pixmap)) - return FALSE; + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) { + glamor_delayed_fallback(screen, "no src fbo\n"); + return FALSE; + } + if (glamor_set_destination_pixmap(dst_pixmap)) { + return FALSE; + } glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, src_pixmap_priv->fb); glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); @@ -124,7 +114,6 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, GL_NEAREST); } } - return TRUE; } @@ -142,29 +131,26 @@ glamor_copy_n_to_n_copypixels(DrawablePtr src, glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); int x_off, y_off, i; - if (src != dst) { - glamor_delayed_fallback(screen, "glamor_copy_n_to_n_copypixels(): " - "src != dest\n"); + glamor_delayed_fallback(screen, "src != dest\n"); return FALSE; } if (gc) { if (gc->alu != GXcopy) { - glamor_delayed_fallback(screen, "glamor_copy_n_to_n_copypixels(): " - "non-copy ALU\n"); + glamor_delayed_fallback(screen,"non-copy ALU\n"); return FALSE; } if (!glamor_pm_is_solid(dst, gc->planemask)) { - glamor_delayed_fallback(screen, "glamor_copy_n_to_n_copypixels(): " - "non-solid planemask\n"); + glamor_delayed_fallback(screen,"non-solid planemask\n"); return FALSE; } } - if (!glamor_set_destination_pixmap(dst_pixmap)) + if (glamor_set_destination_pixmap(dst_pixmap)) { + glamor_delayed_fallback(screen, "dst has no fbo.\n"); return FALSE; - + } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glOrtho(0, dst_pixmap->drawable.width, @@ -196,7 +182,6 @@ glamor_copy_n_to_n_copypixels(DrawablePtr src, GL_COLOR); } } - return TRUE; } @@ -216,29 +201,43 @@ glamor_copy_n_to_n_textured(DrawablePtr src, int i; float vertices[4][2], texcoords[4][2]; 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; - + enum glamor_pixmap_status src_status = GLAMOR_NONE; src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); + dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); if (src == dst) { - glamor_fallback("glamor_copy_n_to_n with same src/dst\n"); + glamor_delayed_fallback(dst->pScreen, "same src/dst\n"); goto fail; } - if (!src_pixmap_priv || !src_pixmap_priv->tex) { - glamor_fallback("glamor_copy_n_to_n with non-texture src\n"); - goto fail; + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { + glamor_delayed_fallback(dst->pScreen, "dst has no fbo.\n"); + goto fail; } - if (!glamor_set_destination_pixmap(dst_pixmap)) + if (!src_pixmap_priv->gl_tex) { +#ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD + glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n"); goto fail; +#else + /* XXX in yInverted mode we have bug here.*/ + if (!glamor_priv->yInverted) goto fail; + src_status = glamor_upload_pixmap_to_texture(src_pixmap); + if (src_status != GLAMOR_UPLOAD_DONE) + goto fail; +#endif + } if (gc) { glamor_set_alu(gc->alu); if (!glamor_set_planemask(dst_pixmap, gc->planemask)) - goto fail; + goto fail; } + glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); + glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); dx += src_x_off; @@ -258,7 +257,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glEnableClientState(GL_TEXTURE_COORD_ARRAY); assert(GLEW_ARB_fragment_shader); - glUseProgramObjectARB(glamor_priv->finish_access_prog); + glUseProgramObjectARB(glamor_priv->finish_access_prog[0]); for (i = 0; i < nbox; i++) { @@ -324,23 +323,23 @@ glamor_copy_n_to_n(DrawablePtr src, void *closure) { if (glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) { - glamor_clear_delayed_fallbacks(dst->pScreen); + goto done; return; } - if (glamor_copy_n_to_n_copypixels(src, dst, gc, box, nbox, dx, dy)) { - glamor_clear_delayed_fallbacks(dst->pScreen); + if (glamor_copy_n_to_n_copypixels(src, dst, gc, box, nbox, dx, dy)){ + goto done; return; - } + } if (glamor_copy_n_to_n_textured(src, dst, gc, box, nbox, dx, dy)) { - glamor_clear_delayed_fallbacks(dst->pScreen); + goto done; return; } - + glamor_report_delayed_fallbacks(src->pScreen); glamor_report_delayed_fallbacks(dst->pScreen); - glamor_fallback("glamor_copy_area() from %p to %p (%c,%c)\n", src, dst, + glamor_fallback("from %p to %p (%c,%c)\n", src, dst, glamor_get_drawable_location(src), glamor_get_drawable_location(dst)); if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW)) { @@ -352,6 +351,11 @@ glamor_copy_n_to_n(DrawablePtr src, } glamor_finish_access(dst); } + return; + +done: + glamor_clear_delayed_fallbacks(src->pScreen); + glamor_clear_delayed_fallbacks(dst->pScreen); } RegionPtr diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index a517045a5..a61b8ae53 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -42,144 +42,27 @@ const Bool glamor_get_drawable_location(const DrawablePtr drawable) { - PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv == NULL) - return 'm'; - if (pixmap_priv->fb == 0) - return 's'; - else - return 'f'; + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + glamor_screen_private *glamor_priv = + 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) + return 's'; + else + return 'f'; } -/** - * Sets the offsets to add to coordinates to make them address the same bits in - * the backing drawable. These coordinates are nonzero only for redirected - * windows. - */ -void -glamor_get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap, - int *x, int *y) -{ -#ifdef COMPOSITE - if (drawable->type == DRAWABLE_WINDOW) { - *x = -pixmap->screen_x; - *y = -pixmap->screen_y; - return; - } -#endif - - *x = 0; - *y = 0; -} - -Bool -glamor_set_destination_pixmap(PixmapPtr pixmap) -{ - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - - if (pixmap_priv == NULL) { - glamor_fallback("glamor_set_destination_pixmap(): no pixmap priv"); - return FALSE; - } - - if (pixmap_priv->fb == 0) { - ScreenPtr screen = pixmap->drawable.pScreen; - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); - - if (pixmap != screen_pixmap) { - glamor_fallback("glamor_set_destination_pixmap(): no fbo"); - return FALSE; - } - } - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); - - glViewport(0, 0, - pixmap->drawable.width, - pixmap->drawable.height); - - return TRUE; -} - -Bool -glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask) -{ - if (glamor_pm_is_solid(&pixmap->drawable, planemask)) { - return GL_TRUE; - } - - ErrorF("unsupported planemask\n"); - return GL_FALSE; -} - -void -glamor_set_alu(unsigned char alu) -{ - if (alu == GXcopy) { - glDisable(GL_COLOR_LOGIC_OP); - return; - } - glEnable(GL_COLOR_LOGIC_OP); - switch (alu) { - case GXclear: - glLogicOp(GL_CLEAR); - break; - case GXand: - glLogicOp(GL_AND); - break; - case GXandReverse: - glLogicOp(GL_AND_REVERSE); - break; - case GXandInverted: - glLogicOp(GL_AND_INVERTED); - break; - case GXnoop: - glLogicOp(GL_NOOP); - break; - case GXxor: - glLogicOp(GL_XOR); - break; - case GXor: - glLogicOp(GL_OR); - break; - case GXnor: - glLogicOp(GL_NOR); - break; - case GXequiv: - glLogicOp(GL_EQUIV); - break; - case GXinvert: - glLogicOp(GL_INVERT); - break; - case GXorReverse: - glLogicOp(GL_OR_REVERSE); - break; - case GXcopyInverted: - glLogicOp(GL_COPY_INVERTED); - break; - case GXorInverted: - glLogicOp(GL_OR_INVERTED); - break; - case GXnand: - glLogicOp(GL_NAND); - break; - case GXset: - glLogicOp(GL_SET); - break; - default: - FatalError("unknown logic op\n"); - } -} void glamor_get_transform_uniform_locations(GLint prog, glamor_transform_uniforms *uniform_locations) { - uniform_locations->x_bias = glGetUniformLocationARB(prog, "x_bias"); - uniform_locations->x_scale = glGetUniformLocationARB(prog, "x_scale"); - uniform_locations->y_bias = glGetUniformLocationARB(prog, "y_bias"); - uniform_locations->y_scale = glGetUniformLocationARB(prog, "y_scale"); + uniform_locations->x_bias = glGetUniformLocationARB(prog, "x_bias"); + uniform_locations->x_scale = glGetUniformLocationARB(prog, "x_scale"); + uniform_locations->y_bias = glGetUniformLocationARB(prog, "y_bias"); + uniform_locations->y_scale = glGetUniformLocationARB(prog, "y_scale"); } /* We don't use a full matrix for our transformations because it's @@ -190,400 +73,163 @@ void glamor_set_transform_for_pixmap(PixmapPtr pixmap, glamor_transform_uniforms *uniform_locations) { - glUniform1fARB(uniform_locations->x_bias, -pixmap->drawable.width / 2.0f); - glUniform1fARB(uniform_locations->x_scale, 2.0f / pixmap->drawable.width); - glUniform1fARB(uniform_locations->y_bias, -pixmap->drawable.height / 2.0f); - glUniform1fARB(uniform_locations->y_scale, -2.0f / pixmap->drawable.height); + glUniform1fARB(uniform_locations->x_bias, -pixmap->drawable.width / 2.0f); + glUniform1fARB(uniform_locations->x_scale, 2.0f / pixmap->drawable.width); + glUniform1fARB(uniform_locations->y_bias, -pixmap->drawable.height / 2.0f); + glUniform1fARB(uniform_locations->y_scale, -2.0f / pixmap->drawable.height); } GLint glamor_compile_glsl_prog(GLenum type, const char *source) { - GLint ok; - GLint prog; + GLint ok; + GLint prog; - prog = glCreateShaderObjectARB(type); - glShaderSourceARB(prog, 1, (const GLchar **)&source, NULL); - glCompileShaderARB(prog); - glGetObjectParameterivARB(prog, GL_OBJECT_COMPILE_STATUS_ARB, &ok); - if (!ok) { - GLchar *info; - GLint size; + prog = glCreateShaderObjectARB(type); + glShaderSourceARB(prog, 1, (const GLchar **)&source, NULL); + glCompileShaderARB(prog); + glGetObjectParameterivARB(prog, GL_OBJECT_COMPILE_STATUS_ARB, &ok); + if (!ok) { + GLchar *info; + GLint size; - glGetObjectParameterivARB(prog, GL_OBJECT_INFO_LOG_LENGTH_ARB, &size); - info = malloc(size); + glGetObjectParameterivARB(prog, GL_OBJECT_INFO_LOG_LENGTH_ARB, &size); + info = malloc(size); - glGetInfoLogARB(prog, size, NULL, info); - ErrorF("Failed to compile %s: %s\n", - type == GL_FRAGMENT_SHADER ? "FS" : "VS", - info); - ErrorF("Program source:\n%s", source); - FatalError("GLSL compile failure\n"); - } + glGetInfoLogARB(prog, size, NULL, info); + ErrorF("Failed to compile %s: %s\n", + type == GL_FRAGMENT_SHADER ? "FS" : "VS", + info); + ErrorF("Program source:\n%s", source); + FatalError("GLSL compile failure\n"); + } - return prog; + return prog; } void glamor_link_glsl_prog(GLint prog) { - GLint ok; + GLint ok; - glLinkProgram(prog); - glGetObjectParameterivARB(prog, GL_OBJECT_LINK_STATUS_ARB, &ok); - if (!ok) { - GLchar *info; - GLint size; + glLinkProgram(prog); + glGetObjectParameterivARB(prog, GL_OBJECT_LINK_STATUS_ARB, &ok); + if (!ok) { + GLchar *info; + GLint size; - glGetObjectParameterivARB(prog, GL_OBJECT_INFO_LOG_LENGTH_ARB, &size); - info = malloc(size); + glGetObjectParameterivARB(prog, GL_OBJECT_INFO_LOG_LENGTH_ARB, &size); + info = malloc(size); - glGetInfoLogARB(prog, size, NULL, info); - ErrorF("Failed to link: %s\n", - info); - FatalError("GLSL link failure\n"); - } + glGetInfoLogARB(prog, size, NULL, info); + ErrorF("Failed to link: %s\n", + info); + FatalError("GLSL link failure\n"); + } } -static float ubyte_to_float(uint8_t b) -{ - return b / 255.0f; -} - -void -glamor_get_color_4f_from_pixel(PixmapPtr pixmap, unsigned long fg_pixel, - GLfloat *color) -{ - switch (pixmap->drawable.depth) { - case 1: - color[0] = 0.0; - color[1] = 0.0; - color[2] = 0.0; - color[3] = fg_pixel & 0x01; - break; - case 8: - color[0] = 0.0; - color[1] = 0.0; - color[2] = 0.0; - color[3] = (fg_pixel & 0xff) / 255.0; - break; - case 24: - case 32: - color[0] = ubyte_to_float((fg_pixel >> 16) & 0xFF); - color[1] = ubyte_to_float((fg_pixel >> 8) & 0xFF); - color[2] = ubyte_to_float((fg_pixel >> 0) & 0xFF); - color[3] = ubyte_to_float((fg_pixel >> 24) & 0xFF); - break; - default: - ErrorF("pixmap with bad depth: %d\n", pixmap->drawable.depth); - color[0] = 1.0; - color[1] = 0.0; - color[2] = 1.0; - color[3] = 1.0; - break; - } -} Bool glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) { - PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - unsigned int stride, row_length, y; - GLenum format, type; - uint8_t *data, *read; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(drawable->pScreen); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - if (!pixmap_priv) - return TRUE; - - if (pixmap_priv->fb == 0) { - ScreenPtr screen = pixmap->drawable.pScreen; - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); - - if (pixmap != screen_pixmap) - return TRUE; - } - - stride = pixmap->devKind; - row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; - - assert(drawable->depth != 1); - switch (drawable->depth) { - case 8: - format = GL_ALPHA; - type = GL_UNSIGNED_BYTE; - break; - case 24: - assert(drawable->bitsPerPixel == 32); - /* FALLTHROUGH */ - case 32: - format = GL_BGRA; - type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - default: - ErrorF("Unknown prepareaccess depth %d\n", drawable->depth); - return FALSE; - } - - pixmap_priv->access_mode = access; - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ROW_LENGTH, row_length); - - if (GLEW_MESA_pack_invert || glamor_priv->yInverted) { - - if (!glamor_priv->yInverted) - glPixelStorei(GL_PACK_INVERT_MESA, 1); - - glGenBuffersARB (1, &pixmap_priv->pbo); - glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); - glBufferDataARB (GL_PIXEL_PACK_BUFFER_EXT, - stride * pixmap->drawable.height, - NULL, GL_DYNAMIC_DRAW_ARB); - glReadPixels (0, 0, - row_length, pixmap->drawable.height, - format, type, 0); - - data = glMapBufferARB (GL_PIXEL_PACK_BUFFER_EXT, GL_READ_WRITE_ARB); - - if (!glamor_priv->yInverted) - glPixelStorei(GL_PACK_INVERT_MESA, 0); - - } else { - data = malloc(stride * pixmap->drawable.height); - - glGenBuffersARB(1, &pixmap_priv->pbo); - glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); - glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT, - stride * pixmap->drawable.height, - NULL, GL_STREAM_READ_ARB); - glReadPixels (0, 0, row_length, pixmap->drawable.height, - format, type, 0); - read = glMapBufferARB(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_ONLY_ARB); - - for (y = 0; y < pixmap->drawable.height; y++) - memcpy(data + y * stride, - read + (pixmap->drawable.height - y - 1) * stride, stride); - glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_EXT); - glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0); - glDeleteBuffersARB(1, &pixmap_priv->pbo); - pixmap_priv->pbo = 0; - } - - pixmap->devPrivate.ptr = data; - - return TRUE; + return glamor_download_pixmap_to_cpu(pixmap, access); } void glamor_init_finish_access_shaders(ScreenPtr screen) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - const char *vs_source = - "void main()\n" - "{\n" - " gl_Position = gl_Vertex;\n" - " gl_TexCoord[0] = gl_MultiTexCoord0;\n" - "}\n"; - const char *fs_source = - "varying vec2 texcoords;\n" - "uniform sampler2D sampler;\n" - "void main()\n" - "{\n" - " gl_FragColor = texture2D(sampler, gl_TexCoord[0].xy);\n" - "}\n"; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + const char *vs_source = + "void main()\n" + "{\n" + " gl_Position = gl_Vertex;\n" + " gl_TexCoord[0] = gl_MultiTexCoord0;\n" + "}\n"; + const char *fs_source = + "varying vec2 texcoords;\n" + "uniform sampler2D sampler;\n" + "void main()\n" + "{\n" + " gl_FragColor = texture2D(sampler, gl_TexCoord[0].xy);\n" + "}\n"; - const char *aswizzle_source = - "varying vec2 texcoords;\n" - "uniform sampler2D sampler;\n" - "void main()\n" - "{\n" - " gl_FragColor = vec4(texture2D(sampler, gl_TexCoord[0].xy).rgb, 1);\n" - "}\n"; + const char *aswizzle_source = + "varying vec2 texcoords;\n" + "uniform sampler2D sampler;\n" + "void main()\n" + "{\n" + " gl_FragColor = vec4(texture2D(sampler, gl_TexCoord[0].xy).rgb, 1);\n" + "}\n"; - GLint fs_prog, vs_prog, avs_prog, aswizzle_prog; + GLint fs_prog, vs_prog, avs_prog, aswizzle_prog; - glamor_priv->finish_access_prog = glCreateProgramObjectARB(); - glamor_priv->aswizzle_prog = glCreateProgramObjectARB(); + glamor_priv->finish_access_prog[0] = glCreateProgramObjectARB(); + glamor_priv->finish_access_prog[1] = glCreateProgramObjectARB(); - if (GLEW_ARB_fragment_shader) { - vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, vs_source); - fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, fs_source); - glAttachObjectARB(glamor_priv->finish_access_prog, vs_prog); - glAttachObjectARB(glamor_priv->finish_access_prog, fs_prog); + if (GLEW_ARB_fragment_shader) { + vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, vs_source); + fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, fs_source); + glAttachObjectARB(glamor_priv->finish_access_prog[0], vs_prog); + glAttachObjectARB(glamor_priv->finish_access_prog[0], fs_prog); - avs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, vs_source); - aswizzle_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, aswizzle_source); - glAttachObjectARB(glamor_priv->aswizzle_prog, avs_prog); - glAttachObjectARB(glamor_priv->aswizzle_prog, aswizzle_prog); - } else { - vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, vs_source); - glAttachObjectARB(glamor_priv->finish_access_prog, vs_prog); - ErrorF("Lack of framgment shader support.\n"); - } + avs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, vs_source); + aswizzle_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, aswizzle_source); + glAttachObjectARB(glamor_priv->finish_access_prog[1], avs_prog); + glAttachObjectARB(glamor_priv->finish_access_prog[1], aswizzle_prog); + } else { + vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, vs_source); + glAttachObjectARB(glamor_priv->finish_access_prog[0], vs_prog); + ErrorF("Lack of framgment shader support.\n"); + } - glamor_link_glsl_prog(glamor_priv->finish_access_prog); - glamor_link_glsl_prog(glamor_priv->aswizzle_prog); + glamor_link_glsl_prog(glamor_priv->finish_access_prog[0]); + glamor_link_glsl_prog(glamor_priv->finish_access_prog[1]); - if (GLEW_ARB_fragment_shader) { - GLint sampler_uniform_location; + if (GLEW_ARB_fragment_shader) { + GLint sampler_uniform_location; - sampler_uniform_location = - glGetUniformLocationARB(glamor_priv->finish_access_prog, "sampler"); - glUseProgramObjectARB(glamor_priv->finish_access_prog); - glUniform1iARB(sampler_uniform_location, 0); - glUseProgramObjectARB(0); - - sampler_uniform_location = - glGetUniformLocationARB(glamor_priv->aswizzle_prog, "sampler"); - glUseProgramObjectARB(glamor_priv->aswizzle_prog); - glUniform1iARB(sampler_uniform_location, 0); - glUseProgramObjectARB(0); - } -} - -/* - * Load texture from the pixmap's data pointer and then - * draw the texture to the fbo, and flip the y axis. - * */ -static void -glamor_load_texture_pixmap(PixmapPtr pixmap) -{ - - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - unsigned int stride, row_length; - GLenum format, type; - static float vertices[8] = {-1, -1, - 1, -1, - 1, 1, - -1, 1}; - static float texcoords[8] = {0, 1, - 1, 1, - 1, 0, - 0, 0}; - static float texcoords_inverted[8] = {0, 0, - 1, 0, - 1, 1, - 0, 1}; - float *ptexcoords; - - void * texel; - GLuint tex; - int alfa_mode = 0; - - if (glamor_priv->yInverted) - ptexcoords = texcoords_inverted; - else - ptexcoords = texcoords; - - assert(pixmap->drawable.depth != 1); - stride = pixmap->devKind; - row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; - switch (pixmap->drawable.depth) { - case 8: - format = GL_ALPHA; - type = GL_UNSIGNED_BYTE; - break; - case 24: - assert(pixmap->drawable.bitsPerPixel == 32); - /* FALLTHROUGH */ - alfa_mode = 1; - case 32: - format = GL_BGRA; - type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - default: - ErrorF("Unknown finishaccess depth %d\n", pixmap->drawable.depth); - return; - } - - glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); - glEnableClientState(GL_VERTEX_ARRAY); - - glClientActiveTexture(GL_TEXTURE0); - glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, ptexcoords); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); - glViewport(0, 0, pixmap->drawable.width, pixmap->drawable.height); - - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); - - glGenTextures(1, &tex); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, tex); - - if (glamor_priv->yInverted || GLEW_MESA_pack_invert) { - texel = NULL; - glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pixmap_priv->pbo); - } - else - texel = pixmap->devPrivate.ptr; - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - pixmap->drawable.width, pixmap->drawable.height, 0, - format, type, texel); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glEnable(GL_TEXTURE_2D); - - assert(GLEW_ARB_fragment_shader); - if (alfa_mode == 0) - glUseProgramObjectARB(glamor_priv->finish_access_prog); - else - glUseProgramObjectARB(glamor_priv->aswizzle_prog); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisable(GL_TEXTURE_2D); + sampler_uniform_location = + glGetUniformLocationARB(glamor_priv->finish_access_prog[0], "sampler"); + glUseProgramObjectARB(glamor_priv->finish_access_prog[0]); + glUniform1iARB(sampler_uniform_location, 0); glUseProgramObjectARB(0); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDeleteTextures(1, &tex); + + sampler_uniform_location = + glGetUniformLocationARB(glamor_priv->finish_access_prog[1], "sampler"); + glUseProgramObjectARB(glamor_priv->finish_access_prog[1]); + glUniform1iARB(sampler_uniform_location, 0); + glUseProgramObjectARB(0); + } } void glamor_finish_access(DrawablePtr drawable) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(drawable->pScreen); - PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - /* Check if finish_access was already called once on this */ - if (pixmap->devPrivate.ptr == NULL) - return; + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + return; - if (!pixmap_priv) - return; + if ( pixmap_priv->access_mode != GLAMOR_ACCESS_RO) { + glamor_restore_pixmap_to_texture(pixmap); + } - if (pixmap_priv->fb == 0) { - ScreenPtr screen = pixmap->drawable.pScreen; - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); + if (pixmap_priv->pbo != 0 && pixmap_priv->pbo_valid) { + glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, 0); + glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_EXT, 0); + pixmap_priv->pbo_valid = FALSE; + glDeleteBuffersARB(1, &pixmap_priv->pbo); + pixmap_priv->pbo = 0; + } else + free(pixmap->devPrivate.ptr); - if (pixmap != screen_pixmap) - return; - } - - if ( pixmap_priv->access_mode != GLAMOR_ACCESS_RO) { - glamor_load_texture_pixmap(pixmap); - } - - if (GLEW_MESA_pack_invert || glamor_priv->yInverted) { - glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); - glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, 0); - glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_EXT, 0); - glDeleteBuffersARB (1, &pixmap_priv->pbo); - pixmap_priv->pbo = 0; - } else - free(pixmap->devPrivate.ptr); - - pixmap->devPrivate.ptr = NULL; + pixmap->devPrivate.ptr = NULL; } + + /** * Calls uxa_prepare_access with UXA_PREPARE_SRC for the tile, if that is the * current fill style. @@ -595,18 +241,18 @@ glamor_finish_access(DrawablePtr drawable) Bool glamor_prepare_access_gc(GCPtr gc) { - if (gc->stipple) - if (!glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RO)) - return FALSE; - if (gc->fillStyle == FillTiled) { - if (!glamor_prepare_access (&gc->tile.pixmap->drawable, - GLAMOR_ACCESS_RO)) { - if (gc->stipple) - glamor_finish_access(&gc->stipple->drawable); - return FALSE; - } + if (gc->stipple) + if (!glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RO)) + return FALSE; + if (gc->fillStyle == FillTiled) { + if (!glamor_prepare_access (&gc->tile.pixmap->drawable, + GLAMOR_ACCESS_RO)) { + if (gc->stipple) + glamor_finish_access(&gc->stipple->drawable); + return FALSE; } - return TRUE; + } + return TRUE; } /** @@ -615,10 +261,10 @@ glamor_prepare_access_gc(GCPtr gc) void glamor_finish_access_gc(GCPtr gc) { - if (gc->fillStyle == FillTiled) - glamor_finish_access(&gc->tile.pixmap->drawable); - if (gc->stipple) - glamor_finish_access(&gc->stipple->drawable); + if (gc->fillStyle == FillTiled) + glamor_finish_access(&gc->tile.pixmap->drawable); + if (gc->stipple) + glamor_finish_access(&gc->stipple->drawable); } Bool @@ -628,33 +274,31 @@ glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, unsigned long fg_pixel, unsigned long bg_pixel, int stipple_x, int stipple_y) { - glamor_fallback("stubbed out stipple depth %d\n", pixmap->drawable.depth); - return FALSE; -// ErrorF("stubbed out stipple depth %d\n", pixmap->drawable.depth); -// glamor_solid_fail_region(pixmap, x, y, width, height); + glamor_fallback("stubbed out stipple depth %d\n", pixmap->drawable.depth); + return FALSE; } GCOps glamor_gc_ops = { - .FillSpans = glamor_fill_spans, - .SetSpans = glamor_set_spans, - .PutImage = glamor_put_image, - .CopyArea = glamor_copy_area, - .CopyPlane = miCopyPlane, - .PolyPoint = miPolyPoint, - .Polylines = glamor_poly_lines, - .PolySegment = miPolySegment, - .PolyRectangle = miPolyRectangle, - .PolyArc = miPolyArc, - .FillPolygon = miFillPolygon, - .PolyFillRect = glamor_poly_fill_rect, - .PolyFillArc = miPolyFillArc, - .PolyText8 = miPolyText8, - .PolyText16 = miPolyText16, - .ImageText8 = miImageText8, - .ImageText16 = miImageText16, - .ImageGlyphBlt = miImageGlyphBlt, - .PolyGlyphBlt = miPolyGlyphBlt, - .PushPixels = miPushPixels, + .FillSpans = glamor_fill_spans, + .SetSpans = glamor_set_spans, + .PutImage = glamor_put_image, + .CopyArea = glamor_copy_area, + .CopyPlane = miCopyPlane, + .PolyPoint = miPolyPoint, + .Polylines = glamor_poly_lines, + .PolySegment = miPolySegment, + .PolyRectangle = miPolyRectangle, + .PolyArc = miPolyArc, + .FillPolygon = miFillPolygon, + .PolyFillRect = glamor_poly_fill_rect, + .PolyFillArc = miPolyFillArc, + .PolyText8 = miPolyText8, + .PolyText16 = miPolyText16, + .ImageText8 = miImageText8, + .ImageText16 = miImageText16, + .ImageGlyphBlt = miImageGlyphBlt, + .PolyGlyphBlt = miPolyGlyphBlt, + .PushPixels = miPushPixels, }; /** @@ -664,84 +308,84 @@ GCOps glamor_gc_ops = { static void glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) { - /* fbValidateGC will do direct access to pixmaps if the tiling has changed. - * Preempt fbValidateGC by doing its work and masking the change out, so - * that we can do the Prepare/finish_access. - */ + /* fbValidateGC will do direct access to pixmaps if the tiling has changed. + * Preempt fbValidateGC by doing its work and masking the change out, so + * that we can do the Prepare/finish_access. + */ #ifdef FB_24_32BIT - if ((changes & GCTile) && fbGetRotatedPixmap(gc)) { - gc->pScreen->DestroyPixmap(fbGetRotatedPixmap(gc)); - fbGetRotatedPixmap(gc) = 0; - } + if ((changes & GCTile) && fbGetRotatedPixmap(gc)) { + gc->pScreen->DestroyPixmap(fbGetRotatedPixmap(gc)); + fbGetRotatedPixmap(gc) = 0; + } - if (gc->fillStyle == FillTiled) { - PixmapPtr old_tile, new_tile; + if (gc->fillStyle == FillTiled) { + PixmapPtr old_tile, new_tile; - old_tile = gc->tile.pixmap; - if (old_tile->drawable.bitsPerPixel != drawable->bitsPerPixel) { - new_tile = fbGetRotatedPixmap(gc); - if (!new_tile || - new_tile ->drawable.bitsPerPixel != drawable->bitsPerPixel) - { - if (new_tile) - gc->pScreen->DestroyPixmap(new_tile); - /* fb24_32ReformatTile will do direct access of a newly- - * allocated pixmap. - */ - if (glamor_prepare_access(&old_tile->drawable, - GLAMOR_ACCESS_RO)) { - new_tile = fb24_32ReformatTile(old_tile, - drawable->bitsPerPixel); - glamor_finish_access(&old_tile->drawable); - } - } - if (new_tile) { - fbGetRotatedPixmap(gc) = old_tile; - gc->tile.pixmap = new_tile; - changes |= GCTile; - } - } - } -#endif - if (changes & GCTile) { - if (!gc->tileIsPixel && FbEvenTile(gc->tile.pixmap->drawable.width * - drawable->bitsPerPixel)) + old_tile = gc->tile.pixmap; + if (old_tile->drawable.bitsPerPixel != drawable->bitsPerPixel) { + new_tile = fbGetRotatedPixmap(gc); + if (!new_tile || + new_tile ->drawable.bitsPerPixel != drawable->bitsPerPixel) { - if (glamor_prepare_access(&gc->tile.pixmap->drawable, - GLAMOR_ACCESS_RW)) { - fbPadPixmap(gc->tile.pixmap); - glamor_finish_access(&gc->tile.pixmap->drawable); - } + if (new_tile) + gc->pScreen->DestroyPixmap(new_tile); + /* fb24_32ReformatTile will do direct access of a newly- + * allocated pixmap. + */ + if (glamor_prepare_access(&old_tile->drawable, + GLAMOR_ACCESS_RO)) { + new_tile = fb24_32ReformatTile(old_tile, + drawable->bitsPerPixel); + glamor_finish_access(&old_tile->drawable); + } } - /* Mask out the GCTile change notification, now that we've done FB's - * job for it. - */ - changes &= ~GCTile; + if (new_tile) { + fbGetRotatedPixmap(gc) = old_tile; + gc->tile.pixmap = new_tile; + changes |= GCTile; + } } - - if (changes & GCStipple && gc->stipple) { - /* We can't inline stipple handling like we do for GCTile because - * it sets fbgc privates. - */ - if (glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RW)) { - fbValidateGC(gc, changes, drawable); - glamor_finish_access(&gc->stipple->drawable); + } +#endif + if (changes & GCTile) { + if (!gc->tileIsPixel && FbEvenTile(gc->tile.pixmap->drawable.width * + drawable->bitsPerPixel)) + { + if (glamor_prepare_access(&gc->tile.pixmap->drawable, + GLAMOR_ACCESS_RW)) { + fbPadPixmap(gc->tile.pixmap); + glamor_finish_access(&gc->tile.pixmap->drawable); } - } else { - fbValidateGC(gc, changes, drawable); - } + } + /* Mask out the GCTile change notification, now that we've done FB's + * job for it. + */ + changes &= ~GCTile; + } - gc->ops = &glamor_gc_ops; + if (changes & GCStipple && gc->stipple) { + /* We can't inline stipple handling like we do for GCTile because + * it sets fbgc privates. + */ + if (glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RW)) { + fbValidateGC(gc, changes, drawable); + glamor_finish_access(&gc->stipple->drawable); + } + } else { + fbValidateGC(gc, changes, drawable); + } + + gc->ops = &glamor_gc_ops; } static GCFuncs glamor_gc_funcs = { - glamor_validate_gc, - miChangeGC, - miCopyGC, - miDestroyGC, - miChangeClip, - miDestroyClip, - miCopyClip + glamor_validate_gc, + miChangeGC, + miCopyGC, + miDestroyGC, + miChangeClip, + miDestroyClip, + miCopyClip }; /** @@ -751,54 +395,54 @@ static GCFuncs glamor_gc_funcs = { int glamor_create_gc(GCPtr gc) { - if (!fbCreateGC(gc)) - return FALSE; + if (!fbCreateGC(gc)) + return FALSE; - gc->funcs = &glamor_gc_funcs; + gc->funcs = &glamor_gc_funcs; - return TRUE; + return TRUE; } Bool glamor_prepare_access_window(WindowPtr window) { - if (window->backgroundState == BackgroundPixmap) { - if (!glamor_prepare_access(&window->background.pixmap->drawable, - GLAMOR_ACCESS_RO)) - return FALSE; - } + if (window->backgroundState == BackgroundPixmap) { + if (!glamor_prepare_access(&window->background.pixmap->drawable, + GLAMOR_ACCESS_RO)) + return FALSE; + } - if (window->borderIsPixel == FALSE) { - if (!glamor_prepare_access(&window->border.pixmap->drawable, - GLAMOR_ACCESS_RO)) { - if (window->backgroundState == BackgroundPixmap) - glamor_finish_access(&window->background.pixmap->drawable); - return FALSE; - } + if (window->borderIsPixel == FALSE) { + if (!glamor_prepare_access(&window->border.pixmap->drawable, + GLAMOR_ACCESS_RO)) { + if (window->backgroundState == BackgroundPixmap) + glamor_finish_access(&window->background.pixmap->drawable); + return FALSE; } - return TRUE; + } + return TRUE; } void glamor_finish_access_window(WindowPtr window) { - if (window->backgroundState == BackgroundPixmap) - glamor_finish_access(&window->background.pixmap->drawable); + if (window->backgroundState == BackgroundPixmap) + glamor_finish_access(&window->background.pixmap->drawable); - if (window->borderIsPixel == FALSE) - glamor_finish_access(&window->border.pixmap->drawable); + if (window->borderIsPixel == FALSE) + glamor_finish_access(&window->border.pixmap->drawable); } Bool glamor_change_window_attributes(WindowPtr window, unsigned long mask) { - Bool ret; + Bool ret; - if (!glamor_prepare_access_window(window)) - return FALSE; - ret = fbChangeWindowAttributes(window, mask); - glamor_finish_access_window(window); - return ret; + if (!glamor_prepare_access_window(window)) + return FALSE; + ret = fbChangeWindowAttributes(window, mask); + glamor_finish_access_window(window); + return ret; } RegionPtr diff --git a/glamor/glamor_debug.h b/glamor/glamor_debug.h new file mode 100644 index 000000000..aad4b3ca6 --- /dev/null +++ b/glamor/glamor_debug.h @@ -0,0 +1,67 @@ +#ifndef __GLAMOR_DEBUG_H__ +#define __GLAMOR_DEBUG_H__ + + +#define GLAMOR_DELAYED_STRING_MAX 64 + +#define GLAMOR_DEBUG_NONE 0 +#define GLAMOR_DEBUG_FALLBACK 1 +#define GLAMOR_DEBUG_TEXTURE_DYNAMIC_UPLOAD 2 +#define GLAMOR_DEBUG_TEXTURE_DOWNLOAD 3 + + +#define __debug_output_message(_format_, _prefix_, ...) \ + LogMessageVerb(X_NONE, 0, \ + "%32s:\t" _format_ , \ + /*_prefix_,*/ \ + __FUNCTION__, \ + ##__VA_ARGS__) + +#define glamor_debug_output(_level_, _format_,...) \ + do { \ + if (glamor_debug_level >= _level_) \ + __debug_output_message(_format_, \ + "Glamor debug", \ + ##__VA_ARGS__); \ + } while(0) + + +#define glamor_fallback(_format_,...) \ + do { \ + if (glamor_debug_level >= GLAMOR_DEBUG_FALLBACK) \ + __debug_output_message(_format_, \ + "Glamor fallback", \ + ##__VA_ARGS__);} while(0) + + + +#define glamor_delayed_fallback(_screen_, _format_,...) \ + do { \ + if (glamor_debug_level >= GLAMOR_DEBUG_FALLBACK) { \ + glamor_screen_private *_glamor_priv_; \ + _glamor_priv_ = glamor_get_screen_private(_screen_); \ + _glamor_priv_->delayed_fallback_pending = 1; \ + snprintf(_glamor_priv_->delayed_fallback_string, \ + GLAMOR_DELAYED_STRING_MAX, \ + "glamor delayed fallback: \t%s " _format_ , \ + __FUNCTION__, ##__VA_ARGS__); } } while(0) + + +#define glamor_clear_delayed_fallbacks(_screen_) \ + do { \ + if (glamor_debug_level >= GLAMOR_DEBUG_FALLBACK) { \ + glamor_screen_private *_glamor_priv_; \ + _glamor_priv_ = glamor_get_screen_private(_screen_); \ + _glamor_priv_->delayed_fallback_pending = 0; } } while(0) + +#define glamor_report_delayed_fallbacks(_screen_) \ + do { \ + if (glamor_debug_level >= GLAMOR_DEBUG_FALLBACK) { \ + glamor_screen_private *_glamor_priv_; \ + _glamor_priv_ = glamor_get_screen_private(_screen_); \ + LogMessageVerb(X_INFO, 0, "%s", \ + _glamor_priv_->delayed_fallback_string); \ + _glamor_priv_->delayed_fallback_pending = 0; } } while(0) + + +#endif diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 2b94934b6..fade2b3cd 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -89,7 +89,6 @@ glamor_fill(DrawablePtr drawable, } return; fail: - glamor_fallback("glamor_fill()"); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_gc(gc)) { fbFill(drawable, gc, x, y, width, height); @@ -154,16 +153,22 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, GLfloat color[4]; float vertices[4][2]; - if (!glamor_set_destination_pixmap(pixmap)) + if (glamor_set_destination_pixmap(pixmap)) { + glamor_fallback("dest has no fbo.\n"); goto fail; + } glamor_set_alu(alu); if (!glamor_set_planemask(pixmap, planemask)) { - ErrorF("Failedto set planemask in glamor_solid.\n"); + glamor_fallback("Failedto set planemask in glamor_solid.\n"); goto fail; } - glUseProgramObjectARB(glamor_priv->solid_prog); - glamor_get_color_4f_from_pixel(pixmap, fg_pixel, color); + glamor_get_rgba_from_pixel(fg_pixel, + &color[0], + &color[1], + &color[2], + &color[3], + format_for_pixmap(pixmap)); glUniform4fvARB(glamor_priv->solid_color_uniform_location, 1, color); glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); @@ -196,22 +201,4 @@ fail: return FALSE; } -/* Highlight places where we're doing it wrong. */ -void -glamor_solid_fail_region(PixmapPtr pixmap, int x, int y, int width, int height) -{ - unsigned long pixel; - switch (pixmap->drawable.depth) { - case 24: - case 32: - pixel = 0x00ff00ff; /* our favorite color */ - break; - default: - case 8: - pixel = 0xd0d0d0d0; - break; - } - - glamor_solid(pixmap, x, y, width, height, GXcopy, ~0, pixel); -} diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c index c6976c376..b1f79a9d8 100644 --- a/glamor/glamor_fillspans.c +++ b/glamor/glamor_fillspans.c @@ -47,10 +47,9 @@ glamor_fill_spans(DrawablePtr drawable, PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) + if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) goto fail; - glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); ppt = points; while (n--) { @@ -82,7 +81,7 @@ glamor_fill_spans(DrawablePtr drawable, } return; fail: - glamor_fallback("glamor_fillspans(): to %p (%c)\n", drawable, + glamor_fallback("to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_gc(gc)) { diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index dba23a89d..10fa2a2c3 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -31,18 +31,6 @@ #include "glamor_priv.h" -static void -set_bit(uint8_t *bitfield, unsigned int index, unsigned int val) -{ - int i = index / 8; - int mask = 1 << (index % 8); - - if (val) - bitfield[i] |= mask; - else - bitfield[i] &= ~mask; -} - void glamor_get_spans(DrawablePtr drawable, int wmax, @@ -53,39 +41,27 @@ glamor_get_spans(DrawablePtr drawable, { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); GLenum format, type; + int ax; glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); - int i, j; - uint8_t *temp_dst = NULL, *readpixels_dst = (uint8_t *)dst; + int i; + uint8_t *readpixels_dst = (uint8_t *)dst; int x_off, y_off; - - switch (drawable->depth) { - case 1: - temp_dst = malloc(wmax); - format = GL_ALPHA; - type = GL_UNSIGNED_BYTE; - readpixels_dst = temp_dst; - break; - case 8: - format = GL_ALPHA; - type = GL_UNSIGNED_BYTE; - break; - case 24: - case 32: - format = GL_BGRA; - type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - default: - glamor_fallback("glamor_get_spans(): " - "Unknown getspans depth %d\n", drawable->depth); - goto fail; + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &format, + &type, + &ax + )) { + glamor_fallback("unknown depth. %d \n", + drawable->depth); + goto fail; } - if (!glamor_set_destination_pixmap(pixmap)) + if (glamor_set_destination_pixmap(pixmap)) { + glamor_fallback("pixmap has no fbo.\n"); goto fail; - + } glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); - for (i = 0; i < count; i++) { if (glamor_priv->yInverted) { glReadPixels(points[i].x + x_off, @@ -102,21 +78,12 @@ glamor_get_spans(DrawablePtr drawable, format, type, readpixels_dst); } - if (temp_dst) { - for (j = 0; j < widths[i]; j++) { - set_bit((uint8_t *)dst, j, temp_dst[j] & 0x1); - } - dst += PixmapBytePad(widths[i], drawable->depth); - } else { - readpixels_dst += PixmapBytePad(widths[i], drawable->depth); - } + readpixels_dst += PixmapBytePad(widths[i], drawable->depth); } - free(temp_dst); return; fail: - free(temp_dst); - glamor_fallback("glamor_get_spans() from %p (%c)\n", drawable, + glamor_fallback("from %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RO)) { fbGetSpans(drawable, wmax, points, widths, count, dst); diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index e24b222f4..26e08470a 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -67,6 +67,7 @@ */ #define GLYPH_BUFFER_SIZE 256 + typedef struct { PicturePtr source; glamor_composite_rect_t rects[GLYPH_BUFFER_SIZE]; @@ -573,6 +574,7 @@ static void glamor_glyphs_to_mask(PicturePtr mask, glamor_glyph_buffer_t *buffer) { #ifdef RENDER + glamor_composite_rects(PictOpAdd, buffer->source, mask, buffer->count, buffer->rects); #endif diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c new file mode 100644 index 000000000..c94c07cd7 --- /dev/null +++ b/glamor/glamor_picture.c @@ -0,0 +1,93 @@ +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "glamor_priv.h" + +/* Upload picture to texture. We may need to flip the y axis or + * wire alpha to 1. So we may conditional create fbo for the picture. + * */ +enum glamor_pixmap_status +glamor_upload_picture_to_texture(PicturePtr picture) +{ + PixmapPtr pixmap; + glamor_pixmap_private *pixmap_priv; + assert(picture->pDrawable); + pixmap = glamor_get_drawable_pixmap(picture->pDrawable); + pixmap_priv = glamor_get_pixmap_private(pixmap); + + assert(GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) == 1); + return glamor_upload_pixmap_to_texture(pixmap); +} + + +Bool +glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access) +{ + if (!picture || !picture->pDrawable) + return TRUE; + + return glamor_prepare_access(picture->pDrawable, access); +} + +void +glamor_finish_access_picture(PicturePtr picture) +{ + if (!picture || !picture->pDrawable) + return; + + glamor_finish_access(picture->pDrawable); +} + +/* + * We should already has drawable attached to it, if it has one. + * Then set the attached pixmap to is_picture format, and set + * the pict format. + * */ +int +glamor_create_picture(PicturePtr picture) +{ + PixmapPtr pixmap; + glamor_pixmap_private *pixmap_priv; + glamor_screen_private *glamor_priv; + + if (!picture || !picture->pDrawable) + return 0; + + glamor_priv = glamor_get_screen_private(picture->pDrawable->pScreen); + pixmap = glamor_get_drawable_pixmap(picture->pDrawable); + pixmap_priv = glamor_get_pixmap_private(pixmap); + assert(pixmap_priv); + + pixmap_priv->is_picture = 1; + pixmap_priv->pict_format = picture->format; + return glamor_priv->saved_create_picture(picture); +} + +void +glamor_destroy_picture(PicturePtr picture) +{ + PixmapPtr pixmap; + glamor_pixmap_private *pixmap_priv; + glamor_screen_private *glamor_priv; + + if (!picture || !picture->pDrawable) + return; + + glamor_priv = glamor_get_screen_private(picture->pDrawable->pScreen); + pixmap = glamor_get_drawable_pixmap(picture->pDrawable); + pixmap_priv = glamor_get_pixmap_private(pixmap); + assert(pixmap_priv); + + pixmap_priv->is_picture = 0; + pixmap_priv->pict_format = 0; + glamor_priv->saved_destroy_picture(picture); +} + +void glamor_picture_format_fixup(PicturePtr picture, glamor_pixmap_private *pixmap_priv) +{ + pixmap_priv->pict_format = picture->format; +} + diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c new file mode 100644 index 000000000..6e2d9d576 --- /dev/null +++ b/glamor/glamor_pixmap.c @@ -0,0 +1,483 @@ +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "glamor_priv.h" +/** + * Sets the offsets to add to coordinates to make them address the same bits in + * the backing drawable. These coordinates are nonzero only for redirected + * windows. + */ +void +glamor_get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap, + int *x, int *y) +{ +#ifdef COMPOSITE + if (drawable->type == DRAWABLE_WINDOW) { + *x = -pixmap->screen_x; + *y = -pixmap->screen_y; + return; + } +#endif + + *x = 0; + *y = 0; +} + +void +glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv) +{ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); + + glViewport(0, 0, + pixmap_priv->container->drawable.width, + pixmap_priv->container->drawable.height); +} + +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; +} + +int +glamor_set_destination_pixmap(PixmapPtr pixmap) +{ + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + + return glamor_set_destination_pixmap_priv(pixmap_priv); +} + +Bool +glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask) +{ + if (glamor_pm_is_solid(&pixmap->drawable, planemask)) { + return GL_TRUE; + } + + glamor_fallback("unsupported planemask %lx\n", planemask); + return GL_FALSE; +} + + + +void +glamor_set_alu(unsigned char alu) +{ + if (alu == GXcopy) { + glDisable(GL_COLOR_LOGIC_OP); + return; + } + glEnable(GL_COLOR_LOGIC_OP); + switch (alu) { + case GXclear: + glLogicOp(GL_CLEAR); + break; + case GXand: + glLogicOp(GL_AND); + break; + case GXandReverse: + glLogicOp(GL_AND_REVERSE); + break; + case GXandInverted: + glLogicOp(GL_AND_INVERTED); + break; + case GXnoop: + glLogicOp(GL_NOOP); + break; + case GXxor: + glLogicOp(GL_XOR); + break; + case GXor: + glLogicOp(GL_OR); + break; + case GXnor: + glLogicOp(GL_NOR); + break; + case GXequiv: + glLogicOp(GL_EQUIV); + break; + case GXinvert: + glLogicOp(GL_INVERT); + break; + case GXorReverse: + glLogicOp(GL_OR_REVERSE); + break; + case GXcopyInverted: + glLogicOp(GL_COPY_INVERTED); + break; + case GXorInverted: + glLogicOp(GL_OR_INVERTED); + break; + case GXnand: + glLogicOp(GL_NAND); + break; + case GXset: + glLogicOp(GL_SET); + break; + default: + FatalError("unknown logic op\n"); + } +} + + + + +/** + * Upload pixmap to a specified texture. + * This texture may not be the one attached to it. + **/ + +static void +__glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, GLuint tex) +{ + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + unsigned int stride, row_length; + void *texels; + GLenum iformat = GL_RGBA; + + stride = pixmap->devKind; + row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; + + glBindTexture(GL_TEXTURE_2D, tex); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); + + if (pixmap_priv->pbo && pixmap_priv->pbo_valid) { + texels = NULL; + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pixmap_priv->pbo); + } + else + texels = pixmap->devPrivate.ptr; + + glTexImage2D(GL_TEXTURE_2D, + 0, + iformat, + pixmap->drawable.width, + pixmap->drawable.height, 0, + format, type, texels); +} + + +/* + * Load texture from the pixmap's data pointer and then + * draw the texture to the fbo, and flip the y axis. + * */ + +static void +_glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, int ax, int flip) +{ + + 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] = {-1, -1, + 1, -1, + 1, 1, + -1, 1}; + static float texcoords[8] = {0, 1, + 1, 1, + 1, 0, + 0, 0}; + static float texcoords_inv[8] = {0, 0, + 1, 0, + 1, 1, + 0, 1}; + float *ptexcoords; + + GLuint tex; + int need_flip; + need_flip = (flip && !glamor_priv->yInverted); + + /* Try fast path firstly, upload the pixmap to the texture attached + * to the fbo directly. */ + + if (ax == 0 && !need_flip) { + __glamor_upload_pixmap_to_texture(pixmap, format, type, pixmap_priv->tex); + return; + } + + + if (need_flip) + ptexcoords = texcoords; + else + ptexcoords = texcoords_inv; + + /* Slow path, we need to flip y or wire alpha to 1. */ + glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); + glEnableClientState(GL_VERTEX_ARRAY); + + glClientActiveTexture(GL_TEXTURE0); + glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, ptexcoords); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); + glViewport(0, 0, pixmap->drawable.width, pixmap->drawable.height); + + glGenTextures(1, &tex); + + __glamor_upload_pixmap_to_texture(pixmap, format, type, tex); + 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); + glEnable(GL_TEXTURE_2D); + glUseProgramObjectARB(glamor_priv->finish_access_prog[ax]); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glDisable(GL_TEXTURE_2D); + glUseProgramObjectARB(0); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDeleteTextures(1, &tex); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +} + + +/* */ +static int +glamor_pixmap_upload_prepare(PixmapPtr pixmap, int need_fbo) +{ + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (!glamor_check_fbo_width_height(pixmap->drawable.width , pixmap->drawable.height) + || !glamor_check_fbo_depth(pixmap->drawable.depth)) { + glamor_fallback("upload failed reason: bad size or depth %d x %d @depth %d \n", + pixmap->drawable.width, pixmap->drawable.height, pixmap->drawable.depth); + return -1; + } + if (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + return 0; + if (pixmap_priv->tex == 0) { + /* Create a framebuffer object wrapping the texture so that we can render + * to it. + */ + glGenTextures(1, &pixmap_priv->tex); + glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); + } + + if (need_fbo && pixmap_priv->fb == 0) { + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pixmap->drawable.width, + pixmap->drawable.height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + glGenFramebuffersEXT(1, &pixmap_priv->fb); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, + pixmap_priv->tex, + 0); + } + + return 0; +} + +enum glamor_pixmap_status +glamor_upload_pixmap_to_texture(PixmapPtr pixmap) +{ + GLenum format, type; + int ax; + + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &format, + &type, + &ax)) { + glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth); + return GLAMOR_UPLOAD_FAILED; + } + if (glamor_pixmap_upload_prepare(pixmap, ax)) + return GLAMOR_UPLOAD_FAILED; + glamor_debug_output(GLAMOR_DEBUG_TEXTURE_DYNAMIC_UPLOAD, + "Uploading pixmap %p %dx%d depth%d.\n", + pixmap, + pixmap->drawable.width, + pixmap->drawable.height, + pixmap->drawable.depth); + _glamor_upload_pixmap_to_texture(pixmap, format, type, ax, 0); + return GLAMOR_UPLOAD_DONE; +} + +#if 0 +enum glamor_pixmap_status +glamor_upload_pixmap_to_texure_from_data(PixmapPtr pixmap, void *data) +{ + enum glamor_pixmap_status upload_status; + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + + assert(pixmap_priv->pbo_valid == 0); + assert(pixmap->devPrivate.ptr == NULL); + pixmap->devPrivate.ptr = data; + upload_status = glamor_upload_pixmap_to_texture(pixmap); + pixmap->devPrivate.ptr = NULL; + return upload_status; +} +#endif + +void +glamor_restore_pixmap_to_texture(PixmapPtr pixmap) +{ + GLenum format, type; + int ax; + + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &format, + &type, + &ax)) { + ErrorF("Unknown pixmap depth %d.\n", pixmap->drawable.depth); + assert(0); + } + _glamor_upload_pixmap_to_texture(pixmap, format, type, ax, 1); +} + + +/** + * Move a pixmap to CPU memory. + * The input data is the pixmap's fbo. + * The output data is at pixmap->devPrivate.ptr. We always use pbo + * to read the fbo and then map it to va. If possible, we will use + * it directly as devPrivate.ptr. + * If successfully download a fbo to cpu then return TRUE. + * Otherwise return FALSE. + **/ + +Bool +glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) +{ + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + unsigned int stride, row_length, y; + GLenum format, type, gl_access, gl_usage; + int ax; + uint8_t *data, *read; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + return TRUE; + + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &format, + &type, + &ax)) { + ErrorF("Unknown pixmap depth %d.\n", pixmap->drawable.depth); + assert(0); // Should never happen. + return FALSE; + } + + pixmap_priv->access_mode = access; + + switch (access) { + case GLAMOR_ACCESS_RO: + gl_access = GL_READ_ONLY_ARB; + gl_usage = GL_STREAM_READ_ARB; + break; + case GLAMOR_ACCESS_WO: + gl_access = GL_WRITE_ONLY_ARB; + gl_usage = GL_STREAM_DRAW_ARB; + break; + case GLAMOR_ACCESS_RW: + gl_access = GL_READ_WRITE_ARB; + gl_usage = GL_DYNAMIC_DRAW_ARB; + break; + default: + ErrorF("Glamor: Invalid access code. %d\n", access); + assert(0); + } + + glamor_debug_output(GLAMOR_DEBUG_TEXTURE_DOWNLOAD, + "Downloading pixmap %p %dx%d depth%d\n", + pixmap, + pixmap->drawable.width, + pixmap->drawable.height, + pixmap->drawable.depth); + + stride = pixmap->devKind; + row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ROW_LENGTH, row_length); + + if (GLEW_MESA_pack_invert || glamor_priv->yInverted) { + + if (!glamor_priv->yInverted) + glPixelStorei(GL_PACK_INVERT_MESA, 1); + if (pixmap_priv->pbo == 0) + glGenBuffersARB (1, &pixmap_priv->pbo); + glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); + glBufferDataARB (GL_PIXEL_PACK_BUFFER_EXT, + stride * pixmap->drawable.height, + NULL, gl_usage); + if (access != GLAMOR_ACCESS_WO) + glReadPixels (0, 0, + row_length, pixmap->drawable.height, + format, type, 0); + data = glMapBufferARB (GL_PIXEL_PACK_BUFFER_EXT, gl_access); + pixmap_priv->pbo_valid = TRUE; + + if (!glamor_priv->yInverted) + glPixelStorei(GL_PACK_INVERT_MESA, 0); + + } else { + data = malloc(stride * pixmap->drawable.height); + assert(data); + if (access != GLAMOR_ACCESS_WO) { + if (pixmap_priv->pbo == 0) + glGenBuffersARB(1, &pixmap_priv->pbo); + glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); + glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT, + stride * pixmap->drawable.height, + NULL, GL_STREAM_READ_ARB); + glReadPixels (0, 0, row_length, pixmap->drawable.height, + format, type, 0); + read = glMapBufferARB(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_ONLY_ARB); + + for (y = 0; y < pixmap->drawable.height; y++) + memcpy(data + y * stride, + read + (pixmap->drawable.height - y - 1) * stride, stride); + glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_EXT); + glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0); + pixmap_priv->pbo_valid = FALSE; + glDeleteBuffersARB(1, &pixmap_priv->pbo); + pixmap_priv->pbo = 0; + } + } + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + pixmap->devPrivate.ptr = data; + return TRUE; +} + + + +static void +_glamor_destroy_upload_pixmap(PixmapPtr pixmap) +{ + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + + assert(pixmap_priv->gl_fbo == 0); + if (pixmap_priv->fb) + glDeleteFramebuffersEXT(1, &pixmap_priv->fb); + if (pixmap_priv->tex) + glDeleteTextures(1, &pixmap_priv->tex); + if (pixmap_priv->pbo) + glDeleteBuffersARB(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_polyfillrect.c b/glamor/glamor_polyfillrect.c index 660dc4a5b..218c308dd 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -50,9 +50,9 @@ glamor_poly_fill_rect(DrawablePtr drawable, int off_x, off_y; RegionPtr pClip = fbGetCompositeClip(gc); PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - - if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) + if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) { goto fail; + } xorg = drawable->x; yorg = drawable->y; @@ -101,9 +101,8 @@ glamor_poly_fill_rect(DrawablePtr drawable, return; fail: - glamor_fallback("glamor_poly_fill_rect() to %p (%c)\n", + glamor_fallback(" to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); - if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_gc(gc)) { fbPolyFillRect(drawable, gc, nrect, prect ); diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c index 75bc9bf9a..914961161 100644 --- a/glamor/glamor_polylines.c +++ b/glamor/glamor_polylines.c @@ -49,18 +49,17 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, xRectangle *rects; int x1, x2, y1, y2; int i; - /* Don't try to do wide lines or non-solid fill style. */ if (gc->lineWidth != 0) { /* This ends up in miSetSpans, which is accelerated as well as we * can hope X wide lines will be. */ - /*glamor_fallback("glamor_poly_lines(): wide lines\n");*/ goto fail; } if (gc->lineStyle != LineSolid || gc->fillStyle != FillSolid) { - glamor_fallback("glamor_poly_lines(): non-solid fill\n"); + glamor_fallback("non-solid fill line style %d, fill style %d\n", + gc->lineStyle, gc->fillStyle); goto fail; } @@ -77,11 +76,9 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, y2 = points[i + 1].y; } if (x1 != x2 && y1 != y2) { - PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); free(rects); glamor_fallback("stub diagonal poly_line\n"); goto fail; - return; } if (x1 < x2) { rects[i].x = x1; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 1dc2c42c5..cf293b5dc 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -39,6 +39,7 @@ #include "glyphstr.h" #endif + #ifndef MAX_WIDTH #define MAX_WIDTH 4096 #endif @@ -47,175 +48,450 @@ #define MAX_HEIGHT 4096 #endif -typedef enum glamor_access { - GLAMOR_ACCESS_RO, - GLAMOR_ACCESS_RW, -} glamor_access_t; +#include "glamor_debug.h" + +#define glamor_check_fbo_width_height(_w_, _h_) (_w_ > 0 && _h_ > 0 \ + && _w_ < MAX_WIDTH \ + && _h_ < MAX_HEIGHT) + +#define glamor_check_fbo_depth(_depth_) ( \ + _depth_ == 8 \ + || _depth_ == 15 \ + || _depth_ == 16 \ + || _depth_ == 24 \ + || _depth_ == 30 \ + || _depth_ == 32) + + +#define GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) (pixmap_priv->is_picture == 1) +#define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv->gl_fbo == 1) typedef struct glamor_transform_uniforms { - GLint x_bias; - GLint x_scale; - GLint y_bias; - GLint y_scale; + GLint x_bias; + GLint x_scale; + GLint y_bias; + GLint y_scale; } glamor_transform_uniforms; typedef struct glamor_composite_shader { - GLuint prog; - GLint dest_to_dest_uniform_location; - GLint dest_to_source_uniform_location; - GLint dest_to_mask_uniform_location; - GLint source_uniform_location; - GLint mask_uniform_location; + GLuint prog; + GLint dest_to_dest_uniform_location; + GLint dest_to_source_uniform_location; + GLint dest_to_mask_uniform_location; + GLint source_uniform_location; + GLint mask_uniform_location; } glamor_composite_shader; typedef struct { - INT16 x_src; - INT16 y_src; - INT16 x_mask; - INT16 y_mask; - INT16 x_dst; - INT16 y_dst; - INT16 width; - INT16 height; + INT16 x_src; + INT16 y_src; + INT16 x_mask; + INT16 y_mask; + INT16 x_dst; + INT16 y_dst; + INT16 width; + INT16 height; } glamor_composite_rect_t; typedef struct { - unsigned char sha1[20]; + unsigned char sha1[20]; } glamor_cached_glyph_t; typedef struct { - /* The identity of the cache, statically configured at initialization */ - unsigned int format; - int glyph_width; - int glyph_height; + /* The identity of the cache, statically configured at initialization */ + unsigned int format; + int glyph_width; + int glyph_height; - /* Size of cache; eventually this should be dynamically determined */ - int size; + /* Size of cache; eventually this should be dynamically determined */ + int size; - /* Hash table mapping from glyph sha1 to position in the glyph; we use - * open addressing with a hash table size determined based on size and large - * enough so that we always have a good amount of free space, so we can - * use linear probing. (Linear probing is preferrable to double hashing - * here because it allows us to easily remove entries.) - */ - int *hash_entries; - int hash_size; + /* Hash table mapping from glyph sha1 to position in the glyph; we use + * open addressing with a hash table size determined based on size and large + * enough so that we always have a good amount of free space, so we can + * use linear probing. (Linear probing is preferrable to double hashing + * here because it allows us to easily remove entries.) + */ + int *hash_entries; + int hash_size; - glamor_cached_glyph_t *glyphs; - int glyph_count; /* Current number of glyphs */ + glamor_cached_glyph_t *glyphs; + int glyph_count; /* Current number of glyphs */ - PicturePtr picture; /* Where the glyphs of the cache are stored */ - int y_offset; /* y location within the picture where the cache starts */ - int columns; /* Number of columns the glyphs are layed out in */ - int eviction_position; /* Next random position to evict a glyph */ + PicturePtr picture; /* Where the glyphs of the cache are stored */ + int y_offset; /* y location within the picture where the cache starts */ + int columns; /* Number of columns the glyphs are layed out in */ + int eviction_position; /* Next random position to evict a glyph */ } glamor_glyph_cache_t; #define GLAMOR_NUM_GLYPH_CACHES 4 enum shader_source { - SHADER_SOURCE_SOLID, - SHADER_SOURCE_TEXTURE, - SHADER_SOURCE_TEXTURE_ALPHA, - SHADER_SOURCE_COUNT, + SHADER_SOURCE_SOLID, + SHADER_SOURCE_TEXTURE, + SHADER_SOURCE_TEXTURE_ALPHA, + SHADER_SOURCE_COUNT, }; enum shader_mask { - SHADER_MASK_NONE, - SHADER_MASK_SOLID, - SHADER_MASK_TEXTURE, - SHADER_MASK_TEXTURE_ALPHA, - SHADER_MASK_COUNT, + SHADER_MASK_NONE, + SHADER_MASK_SOLID, + SHADER_MASK_TEXTURE, + SHADER_MASK_TEXTURE_ALPHA, + SHADER_MASK_COUNT, }; enum shader_in { - SHADER_IN_SOURCE_ONLY, - SHADER_IN_NORMAL, - SHADER_IN_CA_SOURCE, - SHADER_IN_CA_ALPHA, - SHADER_IN_COUNT, + SHADER_IN_SOURCE_ONLY, + SHADER_IN_NORMAL, + SHADER_IN_CA_SOURCE, + SHADER_IN_CA_ALPHA, + SHADER_IN_COUNT, }; typedef struct glamor_screen_private { - CloseScreenProcPtr saved_close_screen; - CreateGCProcPtr saved_create_gc; - CreatePixmapProcPtr saved_create_pixmap; - DestroyPixmapProcPtr saved_destroy_pixmap; - GetSpansProcPtr saved_get_spans; - GetImageProcPtr saved_get_image; - CompositeProcPtr saved_composite; - TrapezoidsProcPtr saved_trapezoids; - GlyphsProcPtr saved_glyphs; - ChangeWindowAttributesProcPtr saved_change_window_attributes; - CopyWindowProcPtr saved_copy_window; - BitmapToRegionProcPtr saved_bitmap_to_region; - TrianglesProcPtr saved_triangles; + CloseScreenProcPtr saved_close_screen; + CreateGCProcPtr saved_create_gc; + CreatePixmapProcPtr saved_create_pixmap; + DestroyPixmapProcPtr saved_destroy_pixmap; + GetSpansProcPtr saved_get_spans; + GetImageProcPtr saved_get_image; + CompositeProcPtr saved_composite; + TrapezoidsProcPtr saved_trapezoids; + GlyphsProcPtr saved_glyphs; + ChangeWindowAttributesProcPtr saved_change_window_attributes; + CopyWindowProcPtr saved_copy_window; + BitmapToRegionProcPtr saved_bitmap_to_region; + TrianglesProcPtr saved_triangles; + CreatePictureProcPtr saved_create_picture; + DestroyPictureProcPtr saved_destroy_picture; - char *delayed_fallback_string; - int yInverted; - GLuint vbo; - int vbo_offset; - int vbo_size; - char *vb; - int vb_stride; + int yInverted; + int screen_fbo; + GLuint vbo; + int vbo_offset; + int vbo_size; + char *vb; + int vb_stride; - /* glamor_finishaccess */ - GLint finish_access_prog; - GLint aswizzle_prog; + /* glamor_finishaccess */ + GLint finish_access_prog[2]; - /* glamor_solid */ - GLint solid_prog; - GLint solid_color_uniform_location; + /* glamor_solid */ + GLint solid_prog; + GLint solid_color_uniform_location; - /* glamor_tile */ - GLint tile_prog; + /* glamor_tile */ + GLint tile_prog; - /* glamor_putimage */ - GLint put_image_xybitmap_prog; - glamor_transform_uniforms put_image_xybitmap_transform; - GLint put_image_xybitmap_fg_uniform_location; - GLint put_image_xybitmap_bg_uniform_location; + /* glamor_putimage */ + GLint put_image_xybitmap_prog; + glamor_transform_uniforms put_image_xybitmap_transform; + GLint put_image_xybitmap_fg_uniform_location; + GLint put_image_xybitmap_bg_uniform_location; - /* glamor_composite */ - glamor_composite_shader composite_shader[SHADER_SOURCE_COUNT] - [SHADER_MASK_COUNT] - [SHADER_IN_COUNT]; - Bool has_source_coords, has_mask_coords; - int render_nr_verts; + /* glamor_composite */ + glamor_composite_shader composite_shader[SHADER_SOURCE_COUNT] + [SHADER_MASK_COUNT] + [SHADER_IN_COUNT]; + Bool has_source_coords, has_mask_coords; + int render_nr_verts; - glamor_glyph_cache_t glyph_caches[GLAMOR_NUM_GLYPH_CACHES]; + glamor_glyph_cache_t glyph_caches[GLAMOR_NUM_GLYPH_CACHES]; + char delayed_fallback_string[GLAMOR_DELAYED_STRING_MAX + 1]; + int delayed_fallback_pending; } glamor_screen_private; -enum glamor_pixmap_type { - GLAMOR_GL, - GLAMOR_FB -}; +typedef enum glamor_access { + GLAMOR_ACCESS_RO, + GLAMOR_ACCESS_RW, + GLAMOR_ACCESS_WO, +} glamor_access_t; + +/* + * glamor_pixmap_private - glamor pixmap's private structure. + * @gl_fbo: The pixmap is attached to a fbo originally. + * @gl_tex: The pixmap is in a gl texture originally. + * @pbo_valid: The pbo has a valid copy of the pixmap's data. + * @is_picture: The drawable is attached to a picture. + * @tex: attached texture. + * @fb: attached fbo. + * @pbo: attached pbo. + * @access_mode: access mode during the prepare/finish pair. + * @pict_format: the corresponding picture's format. + * @container: The corresponding pixmap's pointer. + **/ typedef struct glamor_pixmap_private { - GLuint tex; - GLuint fb; - GLuint pbo; - enum glamor_pixmap_type type; - glamor_access_t access_mode; + unsigned char gl_fbo:1; + unsigned char gl_tex:1; + unsigned char pbo_valid:1; + unsigned char is_picture:1; + GLuint tex; + GLuint fb; + GLuint pbo; + glamor_access_t access_mode; + PictFormatShort pict_format; + PixmapPtr container; } glamor_pixmap_private; +/* + * Pixmap dynamic status, used by dynamic upload feature. + * + * GLAMOR_NONE: initial status, don't need to do anything. + * GLAMOR_UPLOAD_PENDING: marked as need to be uploaded to gl texture. + * GLAMOR_UPLOAD_DONE: the pixmap has been uploaded successfully. + * GLAMOR_UPLOAD_FAILED: fail to upload the pixmap. + * + * */ +typedef enum glamor_pixmap_status { + GLAMOR_NONE, + GLAMOR_UPLOAD_PENDING, + GLAMOR_UPLOAD_DONE, + GLAMOR_UPLOAD_FAILED +} glamor_pixmap_status_t; + + extern DevPrivateKey glamor_screen_private_key; extern DevPrivateKey glamor_pixmap_private_key; static inline glamor_screen_private * glamor_get_screen_private(ScreenPtr screen) { - return (glamor_screen_private *)dixLookupPrivate(&screen->devPrivates, - glamor_screen_private_key); + return (glamor_screen_private *)dixLookupPrivate(&screen->devPrivates, + glamor_screen_private_key); } static inline glamor_pixmap_private * glamor_get_pixmap_private(PixmapPtr pixmap) { - return dixLookupPrivate(&pixmap->devPrivates, glamor_pixmap_private_key); + return dixLookupPrivate(&pixmap->devPrivates, glamor_pixmap_private_key); } #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) #define MIN(a,b) ((a) < (b) ? (a) : (b)) +/** + * Borrow from uxa. + */ +static inline CARD32 +format_for_depth(int depth) +{ + switch (depth) { + case 1: return PICT_a1; + case 4: return PICT_a4; + case 8: return PICT_a8; + case 15: return PICT_x1r5g5b5; + case 16: return PICT_r5g6b5; + default: + case 24: return PICT_x8r8g8b8; +#if XORG_VERSION_CURRENT >= 10699900 + case 30: return PICT_x2r10g10b10; +#endif + case 32: return PICT_a8r8g8b8; + } +} + +static inline CARD32 +format_for_pixmap(PixmapPtr pixmap) +{ + glamor_pixmap_private *pixmap_priv; + PictFormatShort pict_format; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) + pict_format = pixmap_priv->pict_format; + else + pict_format = format_for_depth(pixmap->drawable.depth); + + return pict_format; +} + +/* + * Map picture's format to the correct gl texture format and type. + * xa is used to indicate whehter we need to wire alpha to 1. + * + * Return 0 if find a matched texture type. Otherwise return -1. + **/ +static inline int +glamor_get_tex_format_type_from_pictformat(PictFormatShort format, + GLenum *tex_format, + GLenum *tex_type, + int *xa) +{ + *xa = 0; + switch (format) { + case PICT_a1: + *tex_format = GL_COLOR_INDEX; + *tex_type = GL_BITMAP; + break; + case PICT_b8g8r8x8: + *xa = 1; + case PICT_b8g8r8a8: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_INT_8_8_8_8; + break; + + case PICT_x8r8g8b8: + *xa = 1; + case PICT_a8r8g8b8: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + case PICT_x8b8g8r8: + *xa = 1; + case PICT_a8b8g8r8: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + case PICT_x2r10g10b10: + *xa = 1; + case PICT_a2r10g10b10: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; + break; + case PICT_x2b10g10r10: + *xa = 1; + case PICT_a2b10g10r10: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; + break; + + case PICT_r5g6b5: + *tex_format = GL_RGB; + *tex_type = GL_UNSIGNED_SHORT_5_6_5; + break; + case PICT_b5g6r5: + *tex_format = GL_RGB; + *tex_type = GL_UNSIGNED_SHORT_5_6_5_REV; + break; + case PICT_x1b5g5r5: + *xa = 1; + case PICT_a1b5g5r5: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + break; + + case PICT_x1r5g5b5: + *xa = 1; + case PICT_a1r5g5b5: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + break; + case PICT_a8: + *tex_format = GL_ALPHA; + *tex_type = GL_UNSIGNED_BYTE; + break; + case PICT_x4r4g4b4: + *xa = 1; + case PICT_a4r4g4b4: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; + break; + + case PICT_x4b4g4r4: + *xa = 1; + case PICT_a4b4g4r4: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; + break; + + default: + LogMessageVerb(X_INFO, 0, "fail to get matched format for %x \n", format); + return -1; + } + return 0; +} + + +static inline int +glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap, + GLenum *format, + GLenum *type, + int *ax) +{ + glamor_pixmap_private *pixmap_priv; + PictFormatShort pict_format; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) + pict_format = pixmap_priv->pict_format; + else + pict_format = format_for_depth(pixmap->drawable.depth); + + return glamor_get_tex_format_type_from_pictformat(pict_format, + format, type, ax); +} + + +/* borrowed from uxa */ +static inline Bool +glamor_get_rgba_from_pixel(CARD32 pixel, + float * red, + float * green, + float * blue, + float * alpha, + CARD32 format) +{ + int rbits, bbits, gbits, abits; + int rshift, bshift, gshift, ashift; + + rbits = PICT_FORMAT_R(format); + gbits = PICT_FORMAT_G(format); + bbits = PICT_FORMAT_B(format); + abits = PICT_FORMAT_A(format); + + if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) { + rshift = gshift = bshift = ashift = 0; + } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { + bshift = 0; + gshift = bbits; + rshift = gshift + gbits; + ashift = rshift + rbits; + } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) { + rshift = 0; + gshift = rbits; + bshift = gshift + gbits; + ashift = bshift + bbits; +#if XORG_VERSION_CURRENT >= 10699900 + } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { + ashift = 0; + rshift = abits; + if (abits == 0) + rshift = PICT_FORMAT_BPP(format) - (rbits+gbits+bbits); + gshift = rshift + rbits; + bshift = gshift + gbits; +#endif + } else { + return FALSE; + } +#define COLOR_INT_TO_FLOAT(_fc_, _p_, _s_, _bits_) \ + *_fc_ = (((_p_) >> (_s_)) & (( 1 << (_bits_)) - 1)) \ + / (float)((1<<(_bits_)) - 1) + + if (rbits) + COLOR_INT_TO_FLOAT(red, pixel, rshift, rbits); + else + *red = 0; + + if (gbits) + COLOR_INT_TO_FLOAT(green, pixel, gshift, gbits); + else + *green = 0; + + if (bbits) + COLOR_INT_TO_FLOAT(blue, pixel, bshift, bbits); + else + *blue = 0; + + if (abits) + COLOR_INT_TO_FLOAT(alpha, pixel, ashift, abits); + else + *alpha = 1; + + return TRUE; +} + + /** * Returns TRUE if the given planemask covers all the significant bits in the * pixel values for pDrawable. @@ -223,91 +499,47 @@ glamor_get_pixmap_private(PixmapPtr pixmap) static inline Bool glamor_pm_is_solid(DrawablePtr drawable, unsigned long planemask) { - return (planemask & FbFullMask(drawable->depth)) == - FbFullMask(drawable->depth); + return (planemask & FbFullMask(drawable->depth)) == + FbFullMask(drawable->depth); } -static inline void -glamor_fallback(char *format, ...) -{ - va_list ap; - - va_start(ap, format); - //LogMessageVerb(X_INFO, 3, "fallback: "); - //LogMessageVerb(X_NONE, 3, format, ap); - va_end(ap); -} - -static inline void -glamor_delayed_fallback(ScreenPtr screen, char *format, ...) -{ - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - va_list ap; - - if (glamor_priv->delayed_fallback_string != NULL) - return; - - va_start(ap, format); - XNFvasprintf(&glamor_priv->delayed_fallback_string, format, ap); - va_end(ap); -} - -static inline void -glamor_clear_delayed_fallbacks(ScreenPtr screen) -{ - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - - free(glamor_priv->delayed_fallback_string); - glamor_priv->delayed_fallback_string = NULL; -} - -static inline void -glamor_report_delayed_fallbacks(ScreenPtr screen) -{ - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - - if (glamor_priv->delayed_fallback_string) { - //LogMessageVerb(X_INFO, 3, "fallback: %s", - // glamor_priv->delayed_fallback_string); - glamor_clear_delayed_fallbacks(screen); - } -} +extern int glamor_debug_level; static inline float v_from_x_coord_x(PixmapPtr pixmap, int x) { - return (float)x / pixmap->drawable.width * 2.0 - 1.0; + return (float)x / pixmap->drawable.width * 2.0 - 1.0; } static inline float v_from_x_coord_y(PixmapPtr pixmap, int y) { - return (float)y / pixmap->drawable.height * -2.0 + 1.0; + return (float)y / pixmap->drawable.height * -2.0 + 1.0; } static inline float v_from_x_coord_y_inverted(PixmapPtr pixmap, int y) { - return (float)y / pixmap->drawable.height * 2.0 - 1.0; + return (float)y / pixmap->drawable.height * 2.0 - 1.0; } static inline float t_from_x_coord_x(PixmapPtr pixmap, int x) { - return (float)x / pixmap->drawable.width; + return (float)x / pixmap->drawable.width; } static inline float t_from_x_coord_y(PixmapPtr pixmap, int y) { - return 1.0 - (float)y / pixmap->drawable.height; + return 1.0 - (float)y / pixmap->drawable.height; } static inline float t_from_x_coord_y_inverted(PixmapPtr pixmap, int y) { - return (float)y / pixmap->drawable.height; + return (float)y / pixmap->drawable.height; } @@ -359,7 +591,15 @@ GLint glamor_compile_glsl_prog(GLenum type, const char *source); void glamor_link_glsl_prog(GLint prog); void glamor_get_color_4f_from_pixel(PixmapPtr pixmap, unsigned long fg_pixel, GLfloat *color); -Bool glamor_set_destination_pixmap(PixmapPtr pixmap); + +int glamor_set_destination_pixmap(PixmapPtr pixmap); +int glamor_set_destination_pixmap_priv(glamor_pixmap_private *pixmap_priv); + +/* nc means no check. caller must ensure this pixmap has valid fbo. + * usually use the GLAMOR_PIXMAP_PRIV_HAS_FBO firstly. + * */ +void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv); + void glamor_set_alu(unsigned char alu); Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask); void glamor_get_transform_uniform_locations(GLint prog, @@ -462,15 +702,93 @@ Bool glamor_tile(PixmapPtr pixmap, PixmapPtr tile, int tile_x, int tile_y); void glamor_init_tile_shader(ScreenPtr screen); -/* glamor_triangles */ +/* glamor_triangles.c */ void glamor_triangles (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int ntris, - xTriangle *tris); + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntris, + xTriangle *tris); + +/* glamor_pixmap.c */ + +/** + * Download a pixmap's texture to cpu memory. If success, + * One copy of current pixmap's texture will be put into + * the pixmap->devPrivate.ptr. Will use pbo to map to + * the pointer if possible. + * The pixmap must be a gl texture pixmap. gl_fbo and + * gl_tex must be 1. Used by glamor_prepare_access. + * + */ +Bool +glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access); + +/** + * Restore a pixmap's data which is downloaded by + * glamor_download_pixmap_to_cpu to its original + * gl texture. Used by glamor_finish_access. + * + * The pixmap must be + * in texture originally. In other word, the gl_fbo + * must be 1. + **/ +void +glamor_restore_pixmap_to_texture(PixmapPtr pixmap); + +/** + * Upload a pixmap to gl texture. Used by dynamic pixmap + * uploading feature. The pixmap must be a software pixmap. + * This function will change current FBO and current shaders. + */ +enum glamor_pixmap_status +glamor_upload_pixmap_to_texture(PixmapPtr pixmap); + +/** + * Upload a picture to gl texture. Similar to the + * glamor_upload_pixmap_to_texture. Used in rendering. + **/ +enum glamor_pixmap_status +glamor_upload_picture_to_texture(PicturePtr picture); + +/** + * Destroy all the resources allocated on the uploading + * phase, includs the tex and fbo. + **/ +void +glamor_destroy_upload_pixmap(PixmapPtr pixmap); + + + +int +glamor_create_picture(PicturePtr picture); + +Bool +glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access); + +void +glamor_finish_access_picture(PicturePtr picture); + +void +glamor_destroy_picture(PicturePtr picture); + +enum glamor_pixmap_status +glamor_upload_picture_to_texture(PicturePtr picture); + +void +glamor_picture_format_fixup(PicturePtr picture, glamor_pixmap_private *pixmap_priv); + +/* Dynamic pixmap upload to texture if needed. + * Sometimes, the target is a gl texture pixmap/picture, + * but the source or mask is in cpu memory. In that case, + * upload the source/mask to gl texture and then avoid + * fallback the whole process to cpu. Most of the time, + * this will increase performance obviously. */ + + +#define GLAMOR_PIXMAP_DYNAMIC_UPLOAD #endif /* GLAMOR_PRIV_H */ diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index f1081b055..d056576a0 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -132,6 +132,7 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, 0.0, 1.0, }; + dest_coords[0][0] = v_from_x_coord_x(pixmap, x); dest_coords[0][1] = v_from_x_coord_y(pixmap, y); dest_coords[1][0] = v_from_x_coord_x(pixmap, x + w); @@ -226,13 +227,11 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); return; - -fail: glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); - - glamor_fallback("glamor_put_image(): to %p (%c)\n", + glamor_fallback(": to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); +fail: if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { fbPutImage(drawable, gc, 1, x, y, w, h, left_pad, XYBitmap, bits); glamor_finish_access(drawable); @@ -251,12 +250,11 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, RegionPtr clip; BoxPtr pbox; int nbox; - int bpp = drawable->bitsPerPixel; int src_stride = PixmapBytePad(w, drawable->depth); int x_off, y_off; float vertices[4][2], texcoords[4][2]; GLuint tex; - int alfa_mode = 0; + int ax = 0; if (image_format == XYBitmap) { assert(depth == 1); glamor_put_image_xybitmap(drawable, gc, x, y, w, h, @@ -264,56 +262,32 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, return; } - if (pixmap_priv == NULL) { - glamor_fallback("glamor_put_image: system memory pixmap\n"); - goto fail; + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { + glamor_fallback("has no fbo.\n"); + goto fail; } - if (pixmap_priv->fb == 0) { - ScreenPtr screen = pixmap->drawable.pScreen; - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); - - if (pixmap != screen_pixmap) { - glamor_fallback("glamor_put_image: no fbo\n"); - goto fail; - } - } - - if (bpp == 1 && image_format == XYPixmap) - image_format = ZPixmap; - if (image_format != ZPixmap) { - glamor_fallback("glamor_put_image: non-ZPixmap\n"); + glamor_fallback("non-ZPixmap\n"); goto fail; } - switch (drawable->depth) { - case 1: - format = GL_COLOR_INDEX; - type = GL_BITMAP; - break; - case 8: - format = GL_ALPHA; - type = GL_UNSIGNED_BYTE; - break; - case 24: - assert(drawable->bitsPerPixel == 32); - /* FALLTHROUGH */ - alfa_mode = 1; - case 32: - format = GL_BGRA; - type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - default: - glamor_fallback("glamor_putimage: bad depth %d\n", drawable->depth); + if (!glamor_set_planemask(pixmap, gc->planemask)) { goto fail; } - - if (!glamor_set_planemask(pixmap, gc->planemask)) - goto fail; - glamor_set_alu(gc->alu); + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &format, + &type, + &ax + )) { + glamor_fallback("unknown depth. %d \n", + drawable->depth); + goto fail; + } + + /* XXX consider to reuse a function to do the following work. */ glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); @@ -321,15 +295,13 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, texcoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); - glViewport(0, 0, pixmap->drawable.width, pixmap->drawable.height); + glamor_set_destination_pixmap_priv_nc(pixmap_priv); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, src_stride * 8 / pixmap->drawable.bitsPerPixel); - if (bpp == 1) - glPixelStorei(GL_UNPACK_SKIP_PIXELS, left_pad); + glGenTextures(1, &tex); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex); @@ -341,10 +313,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glEnable(GL_TEXTURE_2D); assert(GLEW_ARB_fragment_shader); - if (alfa_mode == 0) - glUseProgramObjectARB(glamor_priv->finish_access_prog); - else - glUseProgramObjectARB(glamor_priv->aswizzle_prog); + glUseProgramObjectARB(glamor_priv->finish_access_prog[ax]); x += drawable->x; y += drawable->y; @@ -425,7 +394,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, fail: glamor_set_planemask(pixmap, ~0); - glamor_fallback("glamor_put_image(): to %p (%c)\n", + glamor_fallback("to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { fbPutImage(drawable, gc, depth, x, y, w, h, left_pad, image_format, diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index e69d370d9..ca27b4d59 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -39,251 +39,251 @@ #include "glu3/glu3.h" struct shader_key { - enum shader_source source; - enum shader_mask mask; - enum shader_in in; + enum shader_source source; + enum shader_mask mask; + enum shader_in in; }; struct blendinfo { - Bool dest_alpha; - Bool source_alpha; - GLenum source_blend; - GLenum dest_blend; + Bool dest_alpha; + Bool source_alpha; + GLenum source_blend; + GLenum dest_blend; }; static struct blendinfo composite_op_info[] = { - [PictOpClear] = {0, 0, GL_ZERO, GL_ZERO}, - [PictOpSrc] = {0, 0, GL_ONE, GL_ZERO}, - [PictOpDst] = {0, 0, GL_ZERO, GL_ONE}, - [PictOpOver] = {0, 1, GL_ONE, GL_ONE_MINUS_SRC_ALPHA}, - [PictOpOverReverse] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ONE}, - [PictOpIn] = {1, 0, GL_DST_ALPHA, GL_ZERO}, - [PictOpInReverse] = {0, 1, GL_ZERO, GL_SRC_ALPHA}, - [PictOpOut] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ZERO}, - [PictOpOutReverse] = {0, 1, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA}, - [PictOpAtop] = {1, 1, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, - [PictOpAtopReverse] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA}, - [PictOpXor] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, - [PictOpAdd] = {0, 0, GL_ONE, GL_ONE}, + [PictOpClear] = {0, 0, GL_ZERO, GL_ZERO}, + [PictOpSrc] = {0, 0, GL_ONE, GL_ZERO}, + [PictOpDst] = {0, 0, GL_ZERO, GL_ONE}, + [PictOpOver] = {0, 1, GL_ONE, GL_ONE_MINUS_SRC_ALPHA}, + [PictOpOverReverse] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ONE}, + [PictOpIn] = {1, 0, GL_DST_ALPHA, GL_ZERO}, + [PictOpInReverse] = {0, 1, GL_ZERO, GL_SRC_ALPHA}, + [PictOpOut] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ZERO}, + [PictOpOutReverse] = {0, 1, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA}, + [PictOpAtop] = {1, 1, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, + [PictOpAtopReverse] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA}, + [PictOpXor] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, + [PictOpAdd] = {0, 0, GL_ONE, GL_ONE}, }; static GLuint glamor_create_composite_fs(struct shader_key *key) { - const char *source_solid_fetch = - "uniform vec4 source;\n" - "vec4 get_source()\n" - "{\n" - " return source;\n" - "}\n"; - const char *source_alpha_pixmap_fetch = - "uniform sampler2D source_sampler;\n" - "vec4 get_source()\n" - "{\n" - " return texture2D(source_sampler, gl_TexCoord[0].xy);\n" - "}\n"; - const char *source_pixmap_fetch = - "uniform sampler2D source_sampler;\n" - "vec4 get_source()\n" - "{\n" - " return texture2D(source_sampler, gl_TexCoord[0].xy);\n" - "}\n"; - const char *mask_solid_fetch = - "uniform vec4 mask;\n" - "vec4 get_mask()\n" - "{\n" - " return mask;\n" - "}\n"; - const char *mask_alpha_pixmap_fetch = - "uniform sampler2D mask_sampler;\n" - "vec4 get_mask()\n" - "{\n" - " return texture2D(mask_sampler, gl_TexCoord[1].xy);\n" - "}\n"; - const char *mask_pixmap_fetch = - "uniform sampler2D mask_sampler;\n" - "vec4 get_mask()\n" - "{\n" - " return texture2D(mask_sampler, gl_TexCoord[1].xy);\n" - "}\n"; - const char *in_source_only = - "void main()\n" - "{\n" - " gl_FragColor = get_source();\n" - "}\n"; - const char *in_normal = - "void main()\n" - "{\n" - " gl_FragColor = get_source() * get_mask().a;\n" - "}\n"; - const char *in_ca_source = - "void main()\n" - "{\n" - " gl_FragColor = get_source() * get_mask();\n" - "}\n"; - const char *in_ca_alpha = - "void main()\n" - "{\n" - " gl_FragColor = get_source().a * get_mask();\n" - "}\n"; - char *source; - const char *source_fetch; - const char *mask_fetch = ""; - const char *in; - GLuint prog; + const char *source_solid_fetch = + "uniform vec4 source;\n" + "vec4 get_source()\n" + "{\n" + " return source;\n" + "}\n"; + const char *source_alpha_pixmap_fetch = + "uniform sampler2D source_sampler;\n" + "vec4 get_source()\n" + "{\n" + " return texture2D(source_sampler, gl_TexCoord[0].xy);\n" + "}\n"; + const char *source_pixmap_fetch = + "uniform sampler2D source_sampler;\n" + "vec4 get_source()\n" + "{\n" + " return vec4(texture2D(source_sampler, gl_TexCoord[0].xy).rgb, 1);\n" + "}\n"; + const char *mask_solid_fetch = + "uniform vec4 mask;\n" + "vec4 get_mask()\n" + "{\n" + " return mask;\n" + "}\n"; + const char *mask_alpha_pixmap_fetch = + "uniform sampler2D mask_sampler;\n" + "vec4 get_mask()\n" + "{\n" + " return texture2D(mask_sampler, gl_TexCoord[1].xy);\n" + "}\n"; + const char *mask_pixmap_fetch = + "uniform sampler2D mask_sampler;\n" + "vec4 get_mask()\n" + "{\n" + " return vec4(texture2D(mask_sampler, gl_TexCoord[1].xy).rgb, 1);\n" + "}\n"; + const char *in_source_only = + "void main()\n" + "{\n" + " gl_FragColor = get_source();\n" + "}\n"; + const char *in_normal = + "void main()\n" + "{\n" + " gl_FragColor = get_source() * get_mask().a;\n" + "}\n"; + const char *in_ca_source = + "void main()\n" + "{\n" + " gl_FragColor = get_source() * get_mask();\n" + "}\n"; + const char *in_ca_alpha = + "void main()\n" + "{\n" + " gl_FragColor = get_source().a * get_mask();\n" + "}\n"; + char *source; + const char *source_fetch; + const char *mask_fetch = ""; + const char *in; + GLuint prog; - switch (key->source) { - case SHADER_SOURCE_SOLID: - source_fetch = source_solid_fetch; - break; - case SHADER_SOURCE_TEXTURE_ALPHA: - source_fetch = source_alpha_pixmap_fetch; - break; - case SHADER_SOURCE_TEXTURE: - source_fetch = source_pixmap_fetch; - break; - default: - FatalError("Bad composite shader source"); - } + switch (key->source) { + case SHADER_SOURCE_SOLID: + source_fetch = source_solid_fetch; + break; + case SHADER_SOURCE_TEXTURE_ALPHA: + source_fetch = source_alpha_pixmap_fetch; + break; + case SHADER_SOURCE_TEXTURE: + source_fetch = source_pixmap_fetch; + break; + default: + FatalError("Bad composite shader source"); + } - switch (key->mask) { - case SHADER_MASK_NONE: - break; - case SHADER_MASK_SOLID: - mask_fetch = mask_solid_fetch; - break; - case SHADER_MASK_TEXTURE_ALPHA: - mask_fetch = mask_alpha_pixmap_fetch; - break; - case SHADER_MASK_TEXTURE: - mask_fetch = mask_pixmap_fetch; - break; - default: - FatalError("Bad composite shader mask"); - } + switch (key->mask) { + case SHADER_MASK_NONE: + break; + case SHADER_MASK_SOLID: + mask_fetch = mask_solid_fetch; + break; + case SHADER_MASK_TEXTURE_ALPHA: + mask_fetch = mask_alpha_pixmap_fetch; + break; + case SHADER_MASK_TEXTURE: + mask_fetch = mask_pixmap_fetch; + break; + default: + FatalError("Bad composite shader mask"); + } - switch (key->in) { - case SHADER_IN_SOURCE_ONLY: - in = in_source_only; - break; - case SHADER_IN_NORMAL: - in = in_normal; - break; - case SHADER_IN_CA_SOURCE: - in = in_ca_source; - break; - case SHADER_IN_CA_ALPHA: - in = in_ca_alpha; - break; - default: - FatalError("Bad composite IN type"); - } + switch (key->in) { + case SHADER_IN_SOURCE_ONLY: + in = in_source_only; + break; + case SHADER_IN_NORMAL: + in = in_normal; + break; + case SHADER_IN_CA_SOURCE: + in = in_ca_source; + break; + case SHADER_IN_CA_ALPHA: + in = in_ca_alpha; + break; + default: + FatalError("Bad composite IN type"); + } - XNFasprintf(&source, - "%s%s%s", - source_fetch, - mask_fetch, - in); + XNFasprintf(&source, + "%s%s%s", + source_fetch, + mask_fetch, + in); - prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, source); - free(source); + prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, source); + free(source); - return prog; + return prog; } static GLuint glamor_create_composite_vs(struct shader_key *key) { - const char *main_opening = - "void main()\n" - "{\n" - " gl_Position = gl_Vertex;\n"; - const char *source_coords = - " gl_TexCoord[0] = gl_MultiTexCoord0;\n"; - const char *mask_coords = - " gl_TexCoord[1] = gl_MultiTexCoord1;\n"; - const char *main_closing = - "}\n"; - const char *source_coords_setup = ""; - const char *mask_coords_setup = ""; - char *source; - GLuint prog; + const char *main_opening = + "void main()\n" + "{\n" + " gl_Position = gl_Vertex;\n"; + const char *source_coords = + " gl_TexCoord[0] = gl_MultiTexCoord0;\n"; + const char *mask_coords = + " gl_TexCoord[1] = gl_MultiTexCoord1;\n"; + const char *main_closing = + "}\n"; + const char *source_coords_setup = ""; + const char *mask_coords_setup = ""; + char *source; + GLuint prog; - if (key->source != SHADER_SOURCE_SOLID) - source_coords_setup = source_coords; + if (key->source != SHADER_SOURCE_SOLID) + source_coords_setup = source_coords; - if (key->mask != SHADER_MASK_NONE && key->mask != SHADER_MASK_SOLID) - mask_coords_setup = mask_coords; + if (key->mask != SHADER_MASK_NONE && key->mask != SHADER_MASK_SOLID) + mask_coords_setup = mask_coords; - XNFasprintf(&source, - "%s%s%s%s", - main_opening, - source_coords_setup, - mask_coords_setup, - main_closing); + XNFasprintf(&source, + "%s%s%s%s", + main_opening, + source_coords_setup, + mask_coords_setup, + main_closing); - prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, source); - free(source); + prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, source); + free(source); - return prog; + return prog; } static void glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key, glamor_composite_shader *shader) { - GLuint vs, fs, prog; - GLint source_sampler_uniform_location, mask_sampler_uniform_location; + GLuint vs, fs, prog; + GLint source_sampler_uniform_location, mask_sampler_uniform_location; - vs = glamor_create_composite_vs(key); - if (vs == 0) - return; - fs = glamor_create_composite_fs(key); - if (fs == 0) - return; + vs = glamor_create_composite_vs(key); + if (vs == 0) + return; + fs = glamor_create_composite_fs(key); + if (fs == 0) + return; - prog = glCreateProgramObjectARB(); - glAttachObjectARB(prog, vs); - glAttachObjectARB(prog, fs); - glamor_link_glsl_prog(prog); + prog = glCreateProgramObjectARB(); + glAttachObjectARB(prog, vs); + glAttachObjectARB(prog, fs); + glamor_link_glsl_prog(prog); - shader->prog = prog; + shader->prog = prog; - glUseProgramObjectARB(prog); + glUseProgramObjectARB(prog); - if (key->source == SHADER_SOURCE_SOLID) { - shader->source_uniform_location = glGetUniformLocationARB(prog, - "source"); + if (key->source == SHADER_SOURCE_SOLID) { + shader->source_uniform_location = glGetUniformLocationARB(prog, + "source"); + } else { + source_sampler_uniform_location = glGetUniformLocationARB(prog, + "source_sampler"); + glUniform1i(source_sampler_uniform_location, 0); + } + + if (key->mask != SHADER_MASK_NONE) { + if (key->mask == SHADER_MASK_SOLID) { + shader->mask_uniform_location = glGetUniformLocationARB(prog, + "mask"); } else { - source_sampler_uniform_location = glGetUniformLocationARB(prog, - "source_sampler"); - glUniform1i(source_sampler_uniform_location, 0); - } - - if (key->mask != SHADER_MASK_NONE) { - if (key->mask == SHADER_MASK_SOLID) { - shader->mask_uniform_location = glGetUniformLocationARB(prog, - "mask"); - } else { - mask_sampler_uniform_location = glGetUniformLocationARB(prog, - "mask_sampler"); - glUniform1i(mask_sampler_uniform_location, 1); - } + mask_sampler_uniform_location = glGetUniformLocationARB(prog, + "mask_sampler"); + glUniform1i(mask_sampler_uniform_location, 1); } + } } static glamor_composite_shader * glamor_lookup_composite_shader(ScreenPtr screen, struct shader_key *key) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_composite_shader *shader; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_composite_shader *shader; - shader = &glamor_priv->composite_shader[key->source][key->mask][key->in]; - if (shader->prog == 0) - glamor_create_composite_shader(screen, key, shader); + shader = &glamor_priv->composite_shader[key->source][key->mask][key->in]; + if (shader->prog == 0) + glamor_create_composite_shader(screen, key, shader); - return shader; + return shader; } void @@ -295,149 +295,149 @@ static Bool glamor_set_composite_op(ScreenPtr screen, CARD8 op, PicturePtr dest, PicturePtr mask) { - GLenum source_blend, dest_blend; - struct blendinfo *op_info; + GLenum source_blend, dest_blend; + struct blendinfo *op_info; - if (op >= ARRAY_SIZE(composite_op_info)) { - ErrorF("unsupported render op\n"); - return GL_FALSE; + if (op >= ARRAY_SIZE(composite_op_info)) { + glamor_fallback("unsupported render op %d \n", op); + return GL_FALSE; + } + op_info = &composite_op_info[op]; + + source_blend = op_info->source_blend; + dest_blend = op_info->dest_blend; + + /* If there's no dst alpha channel, adjust the blend op so that we'll treat + * it as always 1. + */ + if (PICT_FORMAT_A(dest->format) == 0 && op_info->dest_alpha) { + if (source_blend == GL_DST_ALPHA) + source_blend = GL_ONE; + else if (source_blend == GL_ONE_MINUS_DST_ALPHA) + source_blend = GL_ZERO; + } + + /* Set up the source alpha value for blending in component alpha mode. */ + if (mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format) != 0 && + op_info->source_alpha) { + if (source_blend != GL_ZERO) { + glamor_fallback("Dual-source composite blending not supported\n"); + return GL_FALSE; } - op_info = &composite_op_info[op]; + if (dest_blend == GL_SRC_ALPHA) + dest_blend = GL_SRC_COLOR; + else if (dest_blend == GL_ONE_MINUS_SRC_ALPHA) + dest_blend = GL_ONE_MINUS_SRC_COLOR; + } - source_blend = op_info->source_blend; - dest_blend = op_info->dest_blend; - - /* If there's no dst alpha channel, adjust the blend op so that we'll treat - * it as always 1. - */ - if (PICT_FORMAT_A(dest->format) == 0 && op_info->dest_alpha) { - if (source_blend == GL_DST_ALPHA) - source_blend = GL_ONE; - else if (source_blend == GL_ONE_MINUS_DST_ALPHA) - source_blend = GL_ZERO; - } - - /* Set up the source alpha value for blending in component alpha mode. */ - if (mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format) != 0 && - op_info->source_alpha) { - if (source_blend != GL_ZERO) { - ErrorF("Dual-source composite blending not supported\n"); - return GL_FALSE; - } - if (dest_blend == GL_SRC_ALPHA) - dest_blend = GL_SRC_COLOR; - else if (dest_blend == GL_ONE_MINUS_SRC_ALPHA) - dest_blend = GL_ONE_MINUS_SRC_COLOR; - } - - if (source_blend == GL_ONE && dest_blend == GL_ZERO) { - glDisable(GL_BLEND); - } else { - glEnable(GL_BLEND); - glBlendFunc(source_blend, dest_blend); - } - return TRUE; + if (source_blend == GL_ONE && dest_blend == GL_ZERO) { + glDisable(GL_BLEND); + } else { + glEnable(GL_BLEND); + glBlendFunc(source_blend, dest_blend); + } + return TRUE; } static void glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, glamor_pixmap_private *pixmap_priv) { - glActiveTexture(GL_TEXTURE0 + unit); - glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); - switch (picture->repeatType) { - case RepeatNone: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - break; - case RepeatNormal: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - break; - case RepeatPad: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - break; - case RepeatReflect: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); - break; - } + glActiveTexture(GL_TEXTURE0 + unit); + glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); + switch (picture->repeatType) { + case RepeatNone: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + break; + case RepeatNormal: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + break; + case RepeatPad: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + break; + case RepeatReflect: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); + break; + } - switch (picture->filter) { - case PictFilterNearest: - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - break; - case PictFilterBilinear: - default: - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - break; - } + switch (picture->filter) { + case PictFilterNearest: + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + break; + case PictFilterBilinear: + default: + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + break; + } - glEnable(GL_TEXTURE_2D); + glEnable(GL_TEXTURE_2D); } static void glamor_set_composite_solid(PicturePtr picture, GLint uniform_location) { - CARD32 c = picture->pSourcePict->solidFill.color; /* a8r8g8b8 */ - float color[4]; /* rgba */ + CARD32 c = picture->pSourcePict->solidFill.color; /* a8r8g8b8 */ + float color[4]; /* rgba */ - color[0] = ((c >> 16) & 0xff) / 255.0; - color[1] = ((c >> 8) & 0xff) / 255.0; - color[2] = ((c >> 0) & 0xff) / 255.0; - color[3] = ((c >> 24) & 0xff) / 255.0; + color[0] = ((c >> 16) & 0xff) / 255.0; + color[1] = ((c >> 8) & 0xff) / 255.0; + color[2] = ((c >> 0) & 0xff) / 255.0; + color[3] = ((c >> 24) & 0xff) / 255.0; - glUniform4fvARB(uniform_location, 1, color); + glUniform4fvARB(uniform_location, 1, color); } static int compatible_formats (CARD8 op, PicturePtr dst, PicturePtr src) { - if (op == PictOpSrc) { - if (src->format == dst->format) - return 1; + if (op == PictOpSrc) { + if (src->format == dst->format) + return 1; - if (src->format == PICT_a8r8g8b8 && dst->format == PICT_x8r8g8b8) - return 1; + if (src->format == PICT_a8r8g8b8 && dst->format == PICT_x8r8g8b8) + return 1; - if (src->format == PICT_a8b8g8r8 && dst->format == PICT_x8b8g8r8) - return 1; - } else if (op == PictOpOver) { - if (src->alphaMap || dst->alphaMap) - return 0; + if (src->format == PICT_a8b8g8r8 && dst->format == PICT_x8b8g8r8) + return 1; + } else if (op == PictOpOver) { + if (src->alphaMap || dst->alphaMap) + return 0; - if (src->format != dst->format) - return 0; + if (src->format != dst->format) + return 0; - if (src->format == PICT_x8r8g8b8 || src->format == PICT_x8b8g8r8) - return 1; - } + if (src->format == PICT_x8r8g8b8 || src->format == PICT_x8b8g8r8) + return 1; + } - return 0; + return 0; } static char glamor_get_picture_location(PicturePtr picture) { - if (picture == NULL) - return ' '; + if (picture == NULL) + return ' '; - if (picture->pDrawable == NULL) { - switch (picture->pSourcePict->type) { - case SourcePictTypeSolidFill: - return 'c'; - case SourcePictTypeLinear: - return 'l'; - case SourcePictTypeRadial: - return 'r'; - default: - return '?'; - } + if (picture->pDrawable == NULL) { + switch (picture->pSourcePict->type) { + case SourcePictTypeSolidFill: + return 'c'; + case SourcePictTypeLinear: + return 'l'; + case SourcePictTypeRadial: + return 'r'; + default: + return '?'; } - return glamor_get_drawable_location(picture->pDrawable); + } + return glamor_get_drawable_location(picture->pDrawable); } static Bool @@ -451,151 +451,154 @@ glamor_composite_with_copy(CARD8 op, CARD16 width, CARD16 height) { - RegionRec region; + RegionRec region; - if (!source->pDrawable) - return FALSE; + if (!source->pDrawable) + return FALSE; - if (!compatible_formats(op, dest, source)) - return FALSE; + if (!compatible_formats(op, dest, source)) + return FALSE; - if (source->repeat || source->transform) - return FALSE; + if (source->repeat || source->transform) + return FALSE; - x_dest += dest->pDrawable->x; - y_dest += dest->pDrawable->y; - x_source += source->pDrawable->x; - y_source += source->pDrawable->y; + x_dest += dest->pDrawable->x; + y_dest += dest->pDrawable->y; + x_source += source->pDrawable->x; + y_source += source->pDrawable->y; - if (!miComputeCompositeRegion(®ion, - source, NULL, dest, - x_source, y_source, - 0, 0, - x_dest, y_dest, - width, height)) - return TRUE; - - glamor_copy_n_to_n(source->pDrawable, - dest->pDrawable, NULL, - REGION_RECTS(®ion), - REGION_NUM_RECTS(®ion), - x_source - x_dest, y_source - y_dest, - FALSE, FALSE, 0, NULL); - REGION_UNINIT(dest->pDrawable->pScreen, - ®ion); + if (!miComputeCompositeRegion(®ion, + source, NULL, dest, + x_source, y_source, + 0, 0, + x_dest, y_dest, + width, height)) return TRUE; + + glamor_copy_n_to_n(source->pDrawable, + dest->pDrawable, NULL, + REGION_RECTS(®ion), + REGION_NUM_RECTS(®ion), + x_source - x_dest, y_source - y_dest, + FALSE, FALSE, 0, NULL); + REGION_UNINIT(dest->pDrawable->pScreen, + ®ion); + return TRUE; } static Bool good_source_format(PicturePtr picture) { - switch (picture->format) { - case PICT_a1: - case PICT_a8: - case PICT_a8r8g8b8: - case PICT_x8r8g8b8: - return TRUE; - default: - glamor_fallback("Bad source format 0x%08x\n", picture->format); - return FALSE; - } + switch (picture->format) { + case PICT_a1: + case PICT_a8: + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + return TRUE; + default: + return TRUE; + glamor_fallback("Bad source format 0x%08x\n", picture->format); + return FALSE; + } } static Bool good_mask_format(PicturePtr picture) { - switch (picture->format) { - case PICT_a1: - case PICT_a8: - case PICT_a8r8g8b8: - case PICT_x8r8g8b8: - return TRUE; - default: - glamor_fallback("Bad mask format 0x%08x\n", picture->format); - return FALSE; - } + switch (picture->format) { + case PICT_a1: + case PICT_a8: + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + return TRUE; + default: + return TRUE; + glamor_fallback("Bad mask format 0x%08x\n", picture->format); + return FALSE; + } } static Bool good_dest_format(PicturePtr picture) { - switch (picture->format) { - case PICT_a8: - case PICT_a8r8g8b8: - case PICT_x8r8g8b8: - return TRUE; - default: - glamor_fallback("Bad dest format 0x%08x\n", picture->format); - return FALSE; - } + switch (picture->format) { + case PICT_a8: + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + return TRUE; + default: + return TRUE; + glamor_fallback("Bad dest format 0x%08x\n", picture->format); + return FALSE; + } } static inline float xFixedToFloat(pixman_fixed_t val) { - return ((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0)); + return ((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0)); } static void glamor_set_transformed_point(PicturePtr picture, PixmapPtr pixmap, float *texcoord, int x, int y) { - float result[3]; - int i; - float tx, ty; - ScreenPtr screen = picture->pDrawable->pScreen; - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + float result[3]; + int i; + float tx, ty; + ScreenPtr screen = picture->pDrawable->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - if (picture->transform) { - for (i = 0; i < 3; i++) { - result[i] = (xFixedToFloat(picture->transform->matrix[i][0]) * x + - xFixedToFloat(picture->transform->matrix[i][1]) * y + - xFixedToFloat(picture->transform->matrix[i][2])); - } - tx = result[0] / result[2]; - ty = result[1] / result[2]; - } else { - tx = x; - ty = y; + if (picture->transform) { + for (i = 0; i < 3; i++) { + result[i] = (xFixedToFloat(picture->transform->matrix[i][0]) * x + + xFixedToFloat(picture->transform->matrix[i][1]) * y + + xFixedToFloat(picture->transform->matrix[i][2])); } - texcoord[0] = t_from_x_coord_x(pixmap, tx); - if (glamor_priv->yInverted) - texcoord[1] = t_from_x_coord_y_inverted(pixmap, ty); - else - texcoord[1] = t_from_x_coord_y(pixmap, ty); + tx = result[0] / result[2]; + ty = result[1] / result[2]; + } else { + tx = x; + ty = y; + } + texcoord[0] = t_from_x_coord_x(pixmap, tx); + if (glamor_priv->yInverted) + texcoord[1] = t_from_x_coord_y_inverted(pixmap, ty); + else + texcoord[1] = t_from_x_coord_y(pixmap, ty); } static void glamor_setup_composite_vbo(ScreenPtr screen) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_priv->vb_stride = 2 * sizeof(float); - if (glamor_priv->has_source_coords) - glamor_priv->vb_stride += 2 * sizeof(float); - if (glamor_priv->has_mask_coords) - glamor_priv->vb_stride += 2 * sizeof(float); + glamor_priv->vb_stride = 2 * sizeof(float); + if (glamor_priv->has_source_coords) + glamor_priv->vb_stride += 2 * sizeof(float); + if (glamor_priv->has_mask_coords) + glamor_priv->vb_stride += 2 * sizeof(float); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, glamor_priv->vbo); - glVertexPointer(2, GL_FLOAT, glamor_priv->vb_stride, - (void *)((long)glamor_priv->vbo_offset)); - glEnableClientState(GL_VERTEX_ARRAY); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, glamor_priv->vbo); + glVertexPointer(2, GL_FLOAT, glamor_priv->vb_stride, + (void *)((long)glamor_priv->vbo_offset)); + glEnableClientState(GL_VERTEX_ARRAY); - if (glamor_priv->has_source_coords) { - glClientActiveTexture(GL_TEXTURE0); - glTexCoordPointer(2, GL_FLOAT, glamor_priv->vb_stride, - (void *)(glamor_priv->vbo_offset + 2 * sizeof(float))); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - } + if (glamor_priv->has_source_coords) { + glClientActiveTexture(GL_TEXTURE0); + glTexCoordPointer(2, GL_FLOAT, glamor_priv->vb_stride, + (void *)(glamor_priv->vbo_offset + 2 * sizeof(float))); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } - if (glamor_priv->has_mask_coords) { - glClientActiveTexture(GL_TEXTURE1); - glTexCoordPointer(2, GL_FLOAT, glamor_priv->vb_stride, - (void *)(glamor_priv->vbo_offset + - (glamor_priv->has_source_coords ? 4 : 2) * - sizeof(float))); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - } + if (glamor_priv->has_mask_coords) { + glClientActiveTexture(GL_TEXTURE1); + glTexCoordPointer(2, GL_FLOAT, glamor_priv->vb_stride, + (void *)(glamor_priv->vbo_offset + + (glamor_priv->has_source_coords ? 4 : 2) * + sizeof(float))); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } } static void @@ -605,39 +608,39 @@ glamor_emit_composite_vert(ScreenPtr screen, const float *dst_coords, int i) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - float *vb = (float *)(glamor_priv->vb + glamor_priv->vbo_offset); - int j = 0; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + float *vb = (float *)(glamor_priv->vb + glamor_priv->vbo_offset); + int j = 0; - vb[j++] = dst_coords[i * 2 + 0]; - vb[j++] = dst_coords[i * 2 + 1]; - if (glamor_priv->has_source_coords) { - vb[j++] = src_coords[i * 2 + 0]; - vb[j++] = src_coords[i * 2 + 1]; - } - if (glamor_priv->has_mask_coords) { - vb[j++] = mask_coords[i * 2 + 0]; - vb[j++] = mask_coords[i * 2 + 1]; - } + vb[j++] = dst_coords[i * 2 + 0]; + vb[j++] = dst_coords[i * 2 + 1]; + if (glamor_priv->has_source_coords) { + vb[j++] = src_coords[i * 2 + 0]; + vb[j++] = src_coords[i * 2 + 1]; + } + if (glamor_priv->has_mask_coords) { + vb[j++] = mask_coords[i * 2 + 0]; + vb[j++] = mask_coords[i * 2 + 1]; + } - glamor_priv->render_nr_verts++; - glamor_priv->vbo_offset += glamor_priv->vb_stride; + glamor_priv->render_nr_verts++; + glamor_priv->vbo_offset += glamor_priv->vb_stride; } static void glamor_flush_composite_rects(ScreenPtr screen) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - if (!glamor_priv->render_nr_verts) - return; + if (!glamor_priv->render_nr_verts) + return; - glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); - glamor_priv->vb = NULL; + glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); + glamor_priv->vb = NULL; - glDrawArrays(GL_QUADS, 0, glamor_priv->render_nr_verts); - glamor_priv->render_nr_verts = 0; - glamor_priv->vbo_size = 0; + glDrawArrays(GL_QUADS, 0, glamor_priv->render_nr_verts); + glamor_priv->render_nr_verts = 0; + glamor_priv->vbo_size = 0; } static void @@ -646,31 +649,96 @@ glamor_emit_composite_rect(ScreenPtr screen, const float *mask_coords, const float *dst_coords) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - if (glamor_priv->vbo_offset + 4 * glamor_priv->vb_stride > - glamor_priv->vbo_size) + if (glamor_priv->vbo_offset + 4 * glamor_priv->vb_stride > + glamor_priv->vbo_size) { - glamor_flush_composite_rects(screen); + glamor_flush_composite_rects(screen); } - if (glamor_priv->vbo_size == 0) { - if (glamor_priv->vbo == 0) - glGenBuffersARB(1, &glamor_priv->vbo); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, glamor_priv->vbo); + if (glamor_priv->vbo_size == 0) { + if (glamor_priv->vbo == 0) + glGenBuffersARB(1, &glamor_priv->vbo); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, glamor_priv->vbo); - glamor_priv->vbo_size = 4096; - glBufferDataARB(GL_ARRAY_BUFFER_ARB, glamor_priv->vbo_size, NULL, - GL_STREAM_DRAW_ARB); - glamor_priv->vbo_offset = 0; - glamor_priv->vb = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); - glamor_setup_composite_vbo(screen); - } + glamor_priv->vbo_size = 4096; + glBufferDataARB(GL_ARRAY_BUFFER_ARB, glamor_priv->vbo_size, NULL, + GL_STREAM_DRAW_ARB); + glamor_priv->vbo_offset = 0; + glamor_priv->vb = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + glamor_setup_composite_vbo(screen); + } - glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 0); - glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 1); - glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 2); - glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 3); + glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 0); + glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 1); + glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 2); + glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 3); +} + + +int pict_format_combine_tab[][3] = + { + {PICT_TYPE_ARGB, PICT_TYPE_A, PICT_TYPE_ARGB}, + {PICT_TYPE_ABGR, PICT_TYPE_A, PICT_TYPE_ABGR}, + }; + +static Bool +combine_pict_format(PictFormatShort *des, const PictFormatShort src, + const PictFormatShort mask, enum shader_in in_ca) +{ + PictFormatShort new_vis; + int src_type, mask_type, src_bpp, mask_bpp; + int i; + if (src == mask) { + *des = src; + return TRUE; + } + src_bpp = PICT_FORMAT_BPP(src); + mask_bpp = PICT_FORMAT_BPP(mask); + + assert(src_bpp == mask_bpp); + + new_vis = PICT_FORMAT_VIS(src) | PICT_FORMAT_VIS(mask); + + switch(in_ca) { + case SHADER_IN_SOURCE_ONLY: + return TRUE; + case SHADER_IN_NORMAL: + src_type = PICT_FORMAT_TYPE(src); + mask_type = PICT_TYPE_A; + break; + case SHADER_IN_CA_SOURCE: + src_type = PICT_FORMAT_TYPE(src); + mask_type = PICT_FORMAT_TYPE(mask); + break; + case SHADER_IN_CA_ALPHA: + src_type = PICT_TYPE_A; + mask_type = PICT_FORMAT_TYPE(mask); + break; + default: + return FALSE; + } + + + if (src_type == mask_type) { + *des = PICT_VISFORMAT(src_bpp, src_type, new_vis); + return TRUE; + } + + for(i = 0; + i < sizeof(pict_format_combine_tab)/sizeof(pict_format_combine_tab[0]); + i++) + { + if ((src_type == pict_format_combine_tab[i][0] + && mask_type == pict_format_combine_tab[i][1]) + ||(src_type == pict_format_combine_tab[i][1] + && mask_type == pict_format_combine_tab[i][0])) { + *des = PICT_VISFORMAT(src_bpp, pict_format_combine_tab[i][2], new_vis); + return TRUE; + } + } + return FALSE; } static Bool @@ -681,302 +749,374 @@ glamor_composite_with_shader(CARD8 op, int nrect, glamor_composite_rect_t *rects) { - ScreenPtr screen = dest->pDrawable->pScreen; - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); - PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; - glamor_pixmap_private *source_pixmap_priv = NULL; - glamor_pixmap_private *mask_pixmap_priv = NULL; - struct shader_key key; - glamor_composite_shader *shader; - RegionRec region; - float vertices[8], source_texcoords[8], mask_texcoords[8]; - int i; - BoxPtr box; - int dest_x_off, dest_y_off; - int source_x_off, source_y_off; - int mask_x_off, mask_y_off; + ScreenPtr screen = dest->pDrawable->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); + PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; + glamor_pixmap_private *source_pixmap_priv = NULL; + glamor_pixmap_private *mask_pixmap_priv = NULL; + glamor_pixmap_private *dest_pixmap_priv = NULL; + struct shader_key key; + glamor_composite_shader *shader; + RegionRec region; + float vertices[8], source_texcoords[8], mask_texcoords[8]; + int i; + BoxPtr box; + int dest_x_off, dest_y_off; + int source_x_off, source_y_off; + int mask_x_off, mask_y_off; + enum glamor_pixmap_status source_status = GLAMOR_NONE; + enum glamor_pixmap_status mask_status = GLAMOR_NONE; + PictFormatShort saved_source_format = 0; + dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); - memset(&key, 0, sizeof(key)); - if (!source->pDrawable) { - if (source->pSourcePict->type == SourcePictTypeSolidFill) { - key.source = SHADER_SOURCE_SOLID; - } else { - glamor_fallback("gradient source\n"); - goto fail; - } + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { + glamor_fallback("dest has no fbo.\n"); + goto fail; + } + memset(&key, 0, sizeof(key)); + if (!source->pDrawable) { + if (source->pSourcePict->type == SourcePictTypeSolidFill) { + key.source = SHADER_SOURCE_SOLID; } else { - if (PICT_FORMAT_A(source->format) != 0) { - key.source = SHADER_SOURCE_TEXTURE_ALPHA; - } else { - key.source = SHADER_SOURCE_TEXTURE; - } + glamor_fallback("gradient source\n"); + goto fail; } - if (mask) { - if (!mask->pDrawable) { - if (mask->pSourcePict->type == SourcePictTypeSolidFill) { - key.mask = SHADER_MASK_SOLID; - } else { - glamor_fallback("gradient mask\n"); - goto fail; - } - } else { - if (PICT_FORMAT_A(mask->format) != 0) { - key.mask = SHADER_MASK_TEXTURE_ALPHA; - } else { - key.mask = SHADER_MASK_TEXTURE; - } - } - - if (!mask->componentAlpha) { - key.in = SHADER_IN_NORMAL; - } else { - /* We only handle two CA modes. */ - if (op == PictOpAdd) - key.in = SHADER_IN_CA_SOURCE; - else if (op == PictOpOutReverse) { - key.in = SHADER_IN_CA_ALPHA; - } else { - glamor_fallback("Unsupported component alpha op: %d\n", op); - goto fail; - } - } + } else { + key.source = SHADER_SOURCE_TEXTURE_ALPHA; + } + if (mask) { + if (!mask->pDrawable) { + if (mask->pSourcePict->type == SourcePictTypeSolidFill) { + key.mask = SHADER_MASK_SOLID; + } else { + glamor_fallback("gradient mask\n"); + goto fail; + } } else { - key.mask = SHADER_MASK_NONE; - key.in = SHADER_IN_SOURCE_ONLY; + key.mask = SHADER_MASK_TEXTURE_ALPHA; } - if (source->alphaMap) { - glamor_fallback("source alphaMap\n"); - goto fail; - } - if (mask && mask->alphaMap) { - glamor_fallback("mask alphaMap\n"); - goto fail; - } - - if (key.source == SHADER_SOURCE_TEXTURE || - key.source == SHADER_SOURCE_TEXTURE_ALPHA) { - source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); - source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); - if (source_pixmap == dest_pixmap) { - glamor_fallback("glamor_composite(): source == dest\n"); - goto fail; - } - if (!source_pixmap_priv || source_pixmap_priv->tex == 0) { - glamor_fallback("glamor_composite(): no texture in source\n"); - goto fail; - } - if (!good_source_format(source)) - goto fail; - } - if (key.mask == SHADER_MASK_TEXTURE || - key.mask == SHADER_MASK_TEXTURE_ALPHA) { - mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); - mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); - if (mask_pixmap == dest_pixmap) { - glamor_fallback("glamor_composite(): mask == dest\n"); - goto fail; - } - if (!mask_pixmap_priv || mask_pixmap_priv->tex == 0) { - glamor_fallback("glamor_composite(): no texture in mask\n"); - goto fail; - } - if (!good_mask_format(mask)) - goto fail; - } - if (!good_dest_format(dest)) - goto fail; - - shader = glamor_lookup_composite_shader(screen, &key); - if (shader->prog == 0) { - glamor_fallback("glamor_composite(): " - "no shader program for this render acccel mode\n"); - goto fail; - } - - glUseProgramObjectARB(shader->prog); - - if (!glamor_set_destination_pixmap(dest_pixmap)) - goto fail; - - if (!glamor_set_composite_op(screen, op, dest, mask)) { - goto fail; - } - - if (key.source == SHADER_SOURCE_SOLID) { - glamor_set_composite_solid(source, shader->source_uniform_location); + if (!mask->componentAlpha) { + key.in = SHADER_IN_NORMAL; } else { - glamor_set_composite_texture(screen, 0, source, source_pixmap_priv); + /* We only handle two CA modes. */ + if (op == PictOpAdd) + key.in = SHADER_IN_CA_SOURCE; + else if (op == PictOpOutReverse) { + key.in = SHADER_IN_CA_ALPHA; + } else { + glamor_fallback("Unsupported component alpha op: %d\n", op); + goto fail; + } } - if (key.mask != SHADER_MASK_NONE) { - if (key.mask == SHADER_MASK_SOLID) { - glamor_set_composite_solid(mask, shader->mask_uniform_location); - } else { - glamor_set_composite_texture(screen, 1, mask, mask_pixmap_priv); - } + } else { + key.mask = SHADER_MASK_NONE; + key.in = SHADER_IN_SOURCE_ONLY; + } + + if (source->alphaMap) { + glamor_fallback("source alphaMap\n"); + goto fail; + } + if (mask && mask->alphaMap) { + glamor_fallback("mask alphaMap\n"); + goto fail; + } + if (key.source == SHADER_SOURCE_TEXTURE || + key.source == SHADER_SOURCE_TEXTURE_ALPHA) { + source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); + source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); + if (source_pixmap == dest_pixmap) { + glamor_fallback("source == dest\n"); + goto fail; + } + if (!source_pixmap_priv || source_pixmap_priv->gl_tex == 0) { +#ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD + source_status = GLAMOR_UPLOAD_PENDING; +#else + glamor_fallback("no texture in source\n"); + goto fail; +#endif + } + if ((source_status != GLAMOR_UPLOAD_PENDING) + && !good_source_format(source)) { + goto fail; + } + } + if (key.mask == SHADER_MASK_TEXTURE || + key.mask == SHADER_MASK_TEXTURE_ALPHA) { + mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); + mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); + if (mask_pixmap == dest_pixmap) { + glamor_fallback("mask == dest\n"); + goto fail; + } + if (!mask_pixmap_priv || mask_pixmap_priv->gl_tex == 0) { +#ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD + mask_status = GLAMOR_UPLOAD_PENDING; +#else + glamor_fallback("no texture in mask\n"); + goto fail; +#endif + } + if ((mask_status != GLAMOR_UPLOAD_PENDING) + && !good_mask_format(mask)) { + goto fail; + } + } + if (!good_dest_format(dest)) { + goto fail; + } + if (!glamor_set_composite_op(screen, op, dest, mask)) { + goto fail; + } + +#ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD + if (source_status == GLAMOR_UPLOAD_PENDING + && mask_status == GLAMOR_UPLOAD_PENDING + && source_pixmap == mask_pixmap) { + + if (source->format != mask->format) { + saved_source_format = source->format; + /* XXX + * when need to flip the texture and mask and source share the same pixmap, + * there is a bug, need to be fixed. * + */ + if (!glamor_priv->yInverted) + goto fail; + if (!combine_pict_format(&source->format, source->format, mask->format, key.in)) { + glamor_fallback("combine source %x mask %x failed.\n", + source->format, mask->format); + goto fail; + } + if (source->format != saved_source_format) { + glamor_picture_format_fixup(source, source_pixmap_priv); + } + /* XXX + * By default, glamor_upload_picture_to_texture will wire alpha to 1 + * if one picture doesn't have alpha. So we don't do that again in + * rendering function. But here is a special case, as source and + * mask share the same texture but may have different formats. For + * example, source doesn't have alpha, but mask has alpha. Then the + * texture will have the alpha value for the mask. And will not wire + * to 1 for the source. In this case, we have to use different shader + * to wire the source's alpha to 1. + * + * But this may cause a potential problem if the source's repeat mode + * is REPEAT_NONE, and if the source is smaller than the dest, then + * for the region not covered by the source may be painted incorrectly. + * because we wire the alpha to 1. + * + **/ + if (!PICT_FORMAT_A(saved_source_format) && PICT_FORMAT_A(mask->format)) + key.source = SHADER_SOURCE_TEXTURE; + + if (!PICT_FORMAT_A(mask->format) && PICT_FORMAT_A(saved_source_format)) + key.mask = SHADER_MASK_TEXTURE; + + mask_status = GLAMOR_NONE; + } + 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); + if (source_status != GLAMOR_UPLOAD_DONE) { + glamor_fallback("Failed to upload source texture.\n"); + goto fail; + } } - glamor_priv->has_source_coords = key.source != SHADER_SOURCE_SOLID; - glamor_priv->has_mask_coords = (key.mask != SHADER_MASK_NONE && - key.mask != SHADER_MASK_SOLID); - - glamor_get_drawable_deltas(dest->pDrawable, dest_pixmap, - &dest_x_off, &dest_y_off); - if (source_pixmap) { - glamor_get_drawable_deltas(source->pDrawable, source_pixmap, - &source_x_off, &source_y_off); + if (mask_status == GLAMOR_UPLOAD_PENDING) { + mask_status = glamor_upload_picture_to_texture(mask); + if (mask_status != GLAMOR_UPLOAD_DONE) { + glamor_fallback("Failed to upload mask texture.\n"); + goto fail; + } } - if (mask_pixmap) { - glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap, - &mask_x_off, &mask_y_off); - } - - while (nrect--) { - INT16 x_source; - INT16 y_source; - INT16 x_mask; - INT16 y_mask; - INT16 x_dest; - INT16 y_dest; - CARD16 width; - CARD16 height; - - x_dest = rects->x_dst; - y_dest = rects->y_dst; - x_source = rects->x_src; - y_source = rects->y_src; - x_mask = rects->x_mask; - y_mask = rects->y_mask; - width = rects->width; - height = rects->height; - - x_dest += dest->pDrawable->x; - y_dest += dest->pDrawable->y; - if (source->pDrawable) { - x_source += source->pDrawable->x; - y_source += source->pDrawable->y; - } - if (mask && mask->pDrawable) { - x_mask += mask->pDrawable->x; - y_mask += mask->pDrawable->y; - } - - if (!miComputeCompositeRegion(®ion, - source, mask, dest, - x_source, y_source, - x_mask, y_mask, - x_dest, y_dest, - width, height)) - continue; - - x_source += source_x_off; - y_source += source_y_off; - x_mask += mask_x_off; - y_mask += mask_y_off; - - box = REGION_RECTS(®ion); - for (i = 0; i < REGION_NUM_RECTS(®ion); i++) { - vertices[0] = v_from_x_coord_x(dest_pixmap, - box[i].x1 + dest_x_off); - vertices[2] = v_from_x_coord_x(dest_pixmap, - box[i].x2 + dest_x_off); - vertices[4] = v_from_x_coord_x(dest_pixmap, - box[i].x2 + dest_x_off); - vertices[6] = v_from_x_coord_x(dest_pixmap, - box[i].x1 + dest_x_off); - - if (glamor_priv->yInverted) { - vertices[1] = v_from_x_coord_y_inverted(dest_pixmap, - box[i].y1 + dest_y_off); - vertices[3] = v_from_x_coord_y_inverted(dest_pixmap, - box[i].y1 + dest_y_off); - vertices[5] = v_from_x_coord_y_inverted(dest_pixmap, - box[i].y2 + dest_y_off); - vertices[7] = v_from_x_coord_y_inverted(dest_pixmap, - box[i].y2 + dest_y_off); - - } else { - vertices[1] = v_from_x_coord_y(dest_pixmap, - box[i].y1 + dest_y_off); - vertices[3] = v_from_x_coord_y(dest_pixmap, - box[i].y1 + dest_y_off); - vertices[5] = v_from_x_coord_y(dest_pixmap, - box[i].y2 + dest_y_off); - vertices[7] = v_from_x_coord_y(dest_pixmap, - box[i].y2 + dest_y_off); - } - if (key.source != SHADER_SOURCE_SOLID) { - int tx1 = box[i].x1 + x_source - x_dest; - int ty1 = box[i].y1 + y_source - y_dest; - int tx2 = box[i].x2 + x_source - x_dest; - int ty2 = box[i].y2 + y_source - y_dest; - - glamor_set_transformed_point(source, source_pixmap, - source_texcoords + 0, tx1, ty1); - glamor_set_transformed_point(source, source_pixmap, - source_texcoords + 2, tx2, ty1); - glamor_set_transformed_point(source, source_pixmap, - source_texcoords + 4, tx2, ty2); - glamor_set_transformed_point(source, source_pixmap, - source_texcoords + 6, tx1, ty2); - } - - if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID) { - float tx1 = box[i].x1 + x_mask - x_dest; - float ty1 = box[i].y1 + y_mask - y_dest; - float tx2 = box[i].x2 + x_mask - x_dest; - float ty2 = box[i].y2 + y_mask - y_dest; - - glamor_set_transformed_point(mask, mask_pixmap, - mask_texcoords + 0, tx1, ty1); - glamor_set_transformed_point(mask, mask_pixmap, - mask_texcoords + 2, tx2, ty1); - glamor_set_transformed_point(mask, mask_pixmap, - mask_texcoords + 4, tx2, ty2); - glamor_set_transformed_point(mask, mask_pixmap, - mask_texcoords + 6, tx1, ty2); - } -#if 0 - else memset(mask_texcoords, 0, sizeof(mask_texcoords)); - for (i = 0; i < 4; i++) { - ErrorF("%d: (%04.4f, %04.4f) (%04.4f, %04.4f) " - "(%04.4f, %04.4f)\n", - i, - source_texcoords[i][0], source_texcoords[i][1], - mask_texcoords[i][0], mask_texcoords[i][1], - vertices[i][0], vertices[i][1]); - } + } #endif - glamor_emit_composite_rect(screen, source_texcoords, - mask_texcoords, vertices); - } - rects++; + glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); + + shader = glamor_lookup_composite_shader(screen, &key); + if (shader->prog == 0) { + glamor_fallback("no shader program for this render acccel mode\n"); + goto fail; + } + + glUseProgramObjectARB(shader->prog); + if (key.source == SHADER_SOURCE_SOLID) { + glamor_set_composite_solid(source, shader->source_uniform_location); + } else { + glamor_set_composite_texture(screen, 0, source, source_pixmap_priv); + } + if (key.mask != SHADER_MASK_NONE) { + if (key.mask == SHADER_MASK_SOLID) { + glamor_set_composite_solid(mask, shader->mask_uniform_location); + } else { + glamor_set_composite_texture(screen, 1, mask, mask_pixmap_priv); + } + } + + glamor_priv->has_source_coords = key.source != SHADER_SOURCE_SOLID; + glamor_priv->has_mask_coords = (key.mask != SHADER_MASK_NONE && + key.mask != SHADER_MASK_SOLID); + + glamor_get_drawable_deltas(dest->pDrawable, dest_pixmap, + &dest_x_off, &dest_y_off); + if (source_pixmap) { + glamor_get_drawable_deltas(source->pDrawable, source_pixmap, + &source_x_off, &source_y_off); + } + if (mask_pixmap) { + glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap, + &mask_x_off, &mask_y_off); + } + while (nrect--) { + INT16 x_source; + INT16 y_source; + INT16 x_mask; + INT16 y_mask; + INT16 x_dest; + INT16 y_dest; + CARD16 width; + CARD16 height; + + x_dest = rects->x_dst; + y_dest = rects->y_dst; + x_source = rects->x_src; + y_source = rects->y_src; + x_mask = rects->x_mask; + y_mask = rects->y_mask; + width = rects->width; + height = rects->height; + + x_dest += dest->pDrawable->x; + y_dest += dest->pDrawable->y; + if (source->pDrawable) { + x_source += source->pDrawable->x; + y_source += source->pDrawable->y; + } + if (mask && mask->pDrawable) { + x_mask += mask->pDrawable->x; + y_mask += mask->pDrawable->y; } - glamor_flush_composite_rects(screen); + if (!miComputeCompositeRegion(®ion, + source, mask, dest, + x_source, y_source, + x_mask, y_mask, + x_dest, y_dest, + width, height)) + continue; - glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - glClientActiveTexture(GL_TEXTURE0); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glClientActiveTexture(GL_TEXTURE1); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); + x_source += source_x_off; + y_source += source_y_off; + x_mask += mask_x_off; + y_mask += mask_y_off; - REGION_UNINIT(dst->pDrawable->pScreen, ®ion); - glDisable(GL_BLEND); - glActiveTexture(GL_TEXTURE0); - glDisable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE1); - glDisable(GL_TEXTURE_2D); - glUseProgramObjectARB(0); - return TRUE; + box = REGION_RECTS(®ion); + for (i = 0; i < REGION_NUM_RECTS(®ion); i++) { + vertices[0] = v_from_x_coord_x(dest_pixmap, + box[i].x1 + dest_x_off); + vertices[2] = v_from_x_coord_x(dest_pixmap, + box[i].x2 + dest_x_off); + vertices[4] = v_from_x_coord_x(dest_pixmap, + box[i].x2 + dest_x_off); + vertices[6] = v_from_x_coord_x(dest_pixmap, + box[i].x1 + dest_x_off); -fail: - glDisable(GL_BLEND); - glUseProgramObjectARB(0); - return FALSE; + if (glamor_priv->yInverted) { + vertices[1] = v_from_x_coord_y_inverted(dest_pixmap, + box[i].y1 + dest_y_off); + vertices[3] = v_from_x_coord_y_inverted(dest_pixmap, + box[i].y1 + dest_y_off); + vertices[5] = v_from_x_coord_y_inverted(dest_pixmap, + box[i].y2 + dest_y_off); + vertices[7] = v_from_x_coord_y_inverted(dest_pixmap, + box[i].y2 + dest_y_off); + + } else { + vertices[1] = v_from_x_coord_y(dest_pixmap, + box[i].y1 + dest_y_off); + vertices[3] = v_from_x_coord_y(dest_pixmap, + box[i].y1 + dest_y_off); + vertices[5] = v_from_x_coord_y(dest_pixmap, + box[i].y2 + dest_y_off); + vertices[7] = v_from_x_coord_y(dest_pixmap, + box[i].y2 + dest_y_off); + } + if (key.source != SHADER_SOURCE_SOLID) { + int tx1 = box[i].x1 + x_source - x_dest; + int ty1 = box[i].y1 + y_source - y_dest; + int tx2 = box[i].x2 + x_source - x_dest; + int ty2 = box[i].y2 + y_source - y_dest; + + glamor_set_transformed_point(source, source_pixmap, + source_texcoords + 0, tx1, ty1); + glamor_set_transformed_point(source, source_pixmap, + source_texcoords + 2, tx2, ty1); + glamor_set_transformed_point(source, source_pixmap, + source_texcoords + 4, tx2, ty2); + glamor_set_transformed_point(source, source_pixmap, + source_texcoords + 6, tx1, ty2); + } + + if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID) { + float tx1 = box[i].x1 + x_mask - x_dest; + float ty1 = box[i].y1 + y_mask - y_dest; + float tx2 = box[i].x2 + x_mask - x_dest; + float ty2 = box[i].y2 + y_mask - y_dest; + + glamor_set_transformed_point(mask, mask_pixmap, + mask_texcoords + 0, tx1, ty1); + glamor_set_transformed_point(mask, mask_pixmap, + mask_texcoords + 2, tx2, ty1); + glamor_set_transformed_point(mask, mask_pixmap, + mask_texcoords + 4, tx2, ty2); + glamor_set_transformed_point(mask, mask_pixmap, + mask_texcoords + 6, tx1, ty2); + } + glamor_emit_composite_rect(screen, source_texcoords, + mask_texcoords, vertices); + } + rects++; + } + glamor_flush_composite_rects(screen); + + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + glClientActiveTexture(GL_TEXTURE0); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glClientActiveTexture(GL_TEXTURE1); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + REGION_UNINIT(dst->pDrawable->pScreen, ®ion); + glDisable(GL_BLEND); + glActiveTexture(GL_TEXTURE0); + glDisable(GL_TEXTURE_2D); + glActiveTexture(GL_TEXTURE1); + glDisable(GL_TEXTURE_2D); + glUseProgramObjectARB(0); + if (saved_source_format) + source->format = saved_source_format; + return TRUE; + + fail: + if (saved_source_format) + source->format = saved_source_format; + + glDisable(GL_BLEND); + glUseProgramObjectARB(0); + return FALSE; } void @@ -993,83 +1133,81 @@ glamor_composite(CARD8 op, CARD16 width, CARD16 height) { - glamor_composite_rect_t rect; + glamor_composite_rect_t rect; - /* Do two-pass PictOpOver componentAlpha, until we enable - * dual source color blending. - */ - if (mask && mask->componentAlpha) { - if (op == PictOpOver) { - glamor_composite(PictOpOutReverse, - source, mask, dest, - x_source, y_source, - x_mask, y_mask, - x_dest, y_dest, - width, height); - glamor_composite(PictOpAdd, - source, mask, dest, - x_source, y_source, - x_mask, y_mask, - x_dest, y_dest, - width, height); - return; - } else if (op != PictOpAdd && op != PictOpOutReverse) { - glamor_fallback("glamor_composite(): component alpha\n"); - goto fail; - } + /* Do two-pass PictOpOver componentAlpha, until we enable + * dual source color blending. + */ + if (mask && mask->componentAlpha) { + if (op == PictOpOver) { + glamor_composite(PictOpOutReverse, + source, mask, dest, + x_source, y_source, + x_mask, y_mask, + x_dest, y_dest, + width, height); + glamor_composite(PictOpAdd, + source, mask, dest, + x_source, y_source, + x_mask, y_mask, + x_dest, y_dest, + width, height); + return; + } else if (op != PictOpAdd && op != PictOpOutReverse) { + glamor_fallback("glamor_composite(): component alpha\n"); + goto fail; } + } - if (!mask) { - if (glamor_composite_with_copy(op, source, dest, - x_source, y_source, - x_dest, y_dest, - width, height)) - return; - } + if (!mask) { + if (glamor_composite_with_copy(op, source, dest, + x_source, y_source, + x_dest, y_dest, + width, height)) + return; + } - rect.x_src = x_source; - rect.y_src = y_source; - rect.x_mask = x_mask; - rect.y_mask = y_mask; - rect.x_dst = x_dest; - rect.y_dst = y_dest; - rect.width = width; - rect.height = height; - if (glamor_composite_with_shader(op, source, mask, dest, 1, &rect)) - return; + rect.x_src = x_source; + rect.y_src = y_source; + rect.x_mask = x_mask; + rect.y_mask = y_mask; + rect.x_dst = x_dest; + rect.y_dst = y_dest; + rect.width = width; + rect.height = height; + if (glamor_composite_with_shader(op, source, mask, dest, 1, &rect)) + return; -fail: - glamor_fallback("glamor_composite(): " - "from picts %p/%p(%c,%c) to pict %p (%c)\n", - source, mask, - glamor_get_picture_location(source), - glamor_get_picture_location(mask), - dest, - glamor_get_picture_location(dest)); + fail: + glamor_fallback("glamor_composite(): " + "from picts %p/%p(%c,%c) to pict %p (%c)\n", + source, mask, + glamor_get_picture_location(source), + glamor_get_picture_location(mask), + dest, + glamor_get_picture_location(dest)); - glUseProgramObjectARB(0); - glDisable(GL_BLEND); - if (glamor_prepare_access(dest->pDrawable, GLAMOR_ACCESS_RW)) { - if (source->pDrawable == NULL || - glamor_prepare_access(source->pDrawable, GLAMOR_ACCESS_RO)) - { - if (!mask || mask->pDrawable == NULL || - glamor_prepare_access(mask->pDrawable, GLAMOR_ACCESS_RO)) - { - fbComposite(op, - source, mask, dest, - x_source, y_source, - x_mask, y_mask, - x_dest, y_dest, - width, height); - if (mask && mask->pDrawable != NULL) - glamor_finish_access(mask->pDrawable); - } - if (source->pDrawable != NULL) - glamor_finish_access(source->pDrawable); - } - glamor_finish_access(dest->pDrawable); - } + glUseProgramObjectARB(0); + glDisable(GL_BLEND); + if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) { + if (glamor_prepare_access_picture(source, GLAMOR_ACCESS_RO)) + { + if (!mask || + glamor_prepare_access_picture(mask, GLAMOR_ACCESS_RO)) + { + fbComposite(op, + source, mask, dest, + x_source, y_source, + x_mask, y_mask, + x_dest, y_dest, + width, height); + if (mask) + glamor_finish_access_picture(mask); + } + glamor_finish_access_picture(source); + } + glamor_finish_access_picture(dest); + } } @@ -1084,28 +1222,28 @@ glamor_create_mask_picture(ScreenPtr screen, CARD16 width, CARD16 height) { - PixmapPtr pixmap; - PicturePtr picture; - int error; + PixmapPtr pixmap; + PicturePtr picture; + int error; - if (!pict_format) { - if (dst->polyEdge == PolyEdgeSharp) - pict_format = PictureMatchFormat(screen, 1, PICT_a1); - else - pict_format = PictureMatchFormat(screen, 8, PICT_a8); - if (!pict_format) - return 0; - } + if (!pict_format) { + if (dst->polyEdge == PolyEdgeSharp) + pict_format = PictureMatchFormat(screen, 1, PICT_a1); + else + pict_format = PictureMatchFormat(screen, 8, PICT_a8); + if (!pict_format) + return 0; + } - pixmap = screen->CreatePixmap(screen, width, height, - pict_format->depth, - 0); - if (!pixmap) - return 0; - picture = CreatePicture(0, &pixmap->drawable, pict_format, - 0, 0, serverClient, &error); - screen->DestroyPixmap(pixmap); - return picture; + pixmap = screen->CreatePixmap(screen, width, height, + pict_format->depth, + 0); + if (!pixmap) + return 0; + picture = CreatePicture(0, &pixmap->drawable, pict_format, + 0, 0, serverClient, &error); + screen->DestroyPixmap(pixmap); + return picture; } /** @@ -1118,94 +1256,94 @@ glamor_trapezoids(CARD8 op, PictFormatPtr mask_format, INT16 x_src, INT16 y_src, int ntrap, xTrapezoid *traps) { - ScreenPtr screen = dst->pDrawable->pScreen; - BoxRec bounds; - PicturePtr picture; - INT16 x_dst, y_dst; - INT16 x_rel, y_rel; - int width, height, stride; - PixmapPtr pixmap; - GCPtr gc; - pixman_image_t *image; - - /* If a mask format wasn't provided, we get to choose, but behavior should - * be as if there was no temporary mask the traps were accumulated into. - */ - if (!mask_format) { - if (dst->polyEdge == PolyEdgeSharp) - mask_format = PictureMatchFormat(screen, 1, PICT_a1); - else - mask_format = PictureMatchFormat(screen, 8, PICT_a8); - for (; ntrap; ntrap--, traps++) - glamor_trapezoids(op, src, dst, mask_format, x_src, y_src, - 1, traps); - return; - } - - miTrapezoidBounds(ntrap, traps, &bounds); - - if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) - return; - - x_dst = traps[0].left.p1.x >> 16; - y_dst = traps[0].left.p1.y >> 16; - - width = bounds.x2 - bounds.x1; - height = bounds.y2 - bounds.y1; - stride = (width * BitsPerPixel(mask_format->depth) + 7) / 8; - - picture = glamor_create_mask_picture(screen, dst, mask_format, - width, height); - if (!picture) - return; - - image = pixman_image_create_bits(picture->format, - width, height, - NULL, stride); - if (!image) { - FreePicture(picture, 0); - return; - } + ScreenPtr screen = dst->pDrawable->pScreen; + BoxRec bounds; + PicturePtr picture; + INT16 x_dst, y_dst; + INT16 x_rel, y_rel; + int width, height, stride; + PixmapPtr pixmap; + GCPtr gc; + pixman_image_t *image; + /* If a mask format wasn't provided, we get to choose, but behavior should + * be as if there was no temporary mask the traps were accumulated into. + */ + if (!mask_format) { + if (dst->polyEdge == PolyEdgeSharp) + mask_format = PictureMatchFormat(screen, 1, PICT_a1); + else + mask_format = PictureMatchFormat(screen, 8, PICT_a8); for (; ntrap; ntrap--, traps++) - pixman_rasterize_trapezoid(image, (pixman_trapezoid_t *) traps, - -bounds.x1, -bounds.y1); + glamor_trapezoids(op, src, dst, mask_format, x_src, y_src, + 1, traps); + return; + } - pixmap = GetScratchPixmapHeader(screen, width, height, - mask_format->depth, - BitsPerPixel(mask_format->depth), - PixmapBytePad(width, mask_format->depth), - pixman_image_get_data(image)); - if (!pixmap) { - FreePicture(picture, 0); - pixman_image_unref(image); - return; - } + miTrapezoidBounds(ntrap, traps, &bounds); - gc = GetScratchGC(picture->pDrawable->depth, screen); - if (!gc) { - FreeScratchPixmapHeader(pixmap); - pixman_image_unref (image); - FreePicture(picture, 0); - return; - } - ValidateGC(picture->pDrawable, gc); + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return; - gc->ops->CopyArea(&pixmap->drawable, picture->pDrawable, - gc, 0, 0, width, height, 0, 0); + x_dst = traps[0].left.p1.x >> 16; + y_dst = traps[0].left.p1.y >> 16; - FreeScratchGC(gc); - FreeScratchPixmapHeader(pixmap); - pixman_image_unref(image); + width = bounds.x2 - bounds.x1; + height = bounds.y2 - bounds.y1; + stride = (width * BitsPerPixel(mask_format->depth) + 7) / 8; - x_rel = bounds.x1 + x_src - x_dst; - y_rel = bounds.y1 + y_src - y_dst; - CompositePicture(op, src, picture, dst, - x_rel, y_rel, - 0, 0, - bounds.x1, bounds.y1, - bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); + picture = glamor_create_mask_picture(screen, dst, mask_format, + width, height); + if (!picture) + return; + + image = pixman_image_create_bits(picture->format, + width, height, + NULL, stride); + if (!image) { FreePicture(picture, 0); + return; + } + + for (; ntrap; ntrap--, traps++) + pixman_rasterize_trapezoid(image, (pixman_trapezoid_t *) traps, + -bounds.x1, -bounds.y1); + + pixmap = GetScratchPixmapHeader(screen, width, height, + mask_format->depth, + BitsPerPixel(mask_format->depth), + PixmapBytePad(width, mask_format->depth), + pixman_image_get_data(image)); + if (!pixmap) { + FreePicture(picture, 0); + pixman_image_unref(image); + return; + } + + gc = GetScratchGC(picture->pDrawable->depth, screen); + if (!gc) { + FreeScratchPixmapHeader(pixmap); + pixman_image_unref (image); + FreePicture(picture, 0); + return; + } + ValidateGC(picture->pDrawable, gc); + + gc->ops->CopyArea(&pixmap->drawable, picture->pDrawable, + gc, 0, 0, width, height, 0, 0); + + FreeScratchGC(gc); + FreeScratchPixmapHeader(pixmap); + pixman_image_unref(image); + + x_rel = bounds.x1 + x_src - x_dst; + y_rel = bounds.y1 + y_src - y_dst; + CompositePicture(op, src, picture, dst, + x_rel, y_rel, + 0, 0, + bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); + FreePicture(picture, 0); } void @@ -1213,29 +1351,29 @@ glamor_composite_rects(CARD8 op, PicturePtr src, PicturePtr dst, int nrect, glamor_composite_rect_t *rects) { - int n; - glamor_composite_rect_t *r; + int n; + glamor_composite_rect_t *r; - ValidatePicture(src); - ValidatePicture(dst); + ValidatePicture(src); + ValidatePicture(dst); - if (glamor_composite_with_shader(op, src, NULL, dst, nrect, rects)) - return; + if (glamor_composite_with_shader(op, src, NULL, dst, nrect, rects)) + return; - n = nrect; - r = rects; + n = nrect; + r = rects; - while (n--) { - CompositePicture(op, - src, - NULL, - dst, - r->x_src, r->y_src, - 0, 0, - r->x_dst, r->y_dst, - r->width, r->height); - r++; - } + while (n--) { + CompositePicture(op, + src, + NULL, + dst, + r->x_src, r->y_src, + 0, 0, + r->x_dst, r->y_dst, + r->width, r->height); + r++; + } } #endif /* RENDER */ diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 6c1c2ff3f..253f20345 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -37,46 +37,23 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, { PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); GLenum format, type; - uint8_t *temp_src = NULL, *drawpixels_src = (uint8_t *)src; - int i, j; - int wmax = 0; + int ax, i; + uint8_t *drawpixels_src = (uint8_t *)src; RegionPtr clip = fbGetCompositeClip(gc); BoxRec *pbox; int x_off, y_off; - goto fail; - - for (i = 0 ; i < n; i++) { - if (wmax < widths[i]) - wmax = widths[i]; + if (glamor_get_tex_format_type_from_pixmap(dest_pixmap, + &format, + &type, + &ax + )) { + glamor_fallback("unknown depth. %d \n", + drawable->depth); + goto fail; } - switch (drawable->depth) { - case 1: - temp_src = malloc(wmax); - format = GL_ALPHA; - type = GL_UNSIGNED_BYTE; - drawpixels_src = temp_src; - break; - case 8: - format = GL_ALPHA; - type = GL_UNSIGNED_BYTE; - break; - case 24: - format = GL_RGB; - type = GL_UNSIGNED_BYTE; - break; - case 32: - format = GL_BGRA; - type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - default: - glamor_fallback("glamor_set_spans()Unknown depth %d\n", - drawable->depth); - goto fail; - } - - if (!glamor_set_destination_pixmap(dest_pixmap)) + if (glamor_set_destination_pixmap(dest_pixmap)) goto fail; if (!glamor_set_planemask(dest_pixmap, gc->planemask)) goto fail; @@ -87,14 +64,6 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, glamor_get_drawable_deltas(drawable, dest_pixmap, &x_off, &y_off); for (i = 0; i < n; i++) { - if (temp_src) { - for (j = 0; j < widths[i]; j++) { - if (src[j / 8] & (1 << (j % 8))) - temp_src[j] = 0xff; - else - temp_src[j] = 0; - } - } n = REGION_NUM_RECTS(clip); pbox = REGION_RECTS(clip); @@ -113,19 +82,14 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, format, type, drawpixels_src); } - if (temp_src) { - src += PixmapBytePad(widths[i], drawable->depth); - } else { drawpixels_src += PixmapBytePad(widths[i], drawable->depth); - } } fail: glDisable(GL_SCISSOR_TEST); glamor_set_planemask(dest_pixmap, ~0); glamor_set_alu(GXcopy); - free(temp_src); - glamor_fallback("glamor_set_spans(): to %p (%c)\n", + glamor_fallback("to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { fbSetSpans(drawable, gc, src, points, widths, n, sorted); diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 5b1e73d5a..2991eddd5 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -91,24 +91,26 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glamor_pixmap_private *tile_priv = glamor_get_pixmap_private(tile); float vertices[4][2]; float source_texcoords[4][2]; - if (glamor_priv->tile_prog == 0) { glamor_fallback("Tiling unsupported\n"); goto fail; } - if (!glamor_set_destination_pixmap(pixmap)) + if (glamor_set_destination_pixmap(pixmap)) { + glamor_fallback("dest has no fbo."); goto fail; + } - if (tile_priv->tex == 0) { + if (tile_priv->gl_tex == 0) { glamor_fallback("Non-texture tile pixmap\n"); goto fail; } - if (!glamor_set_planemask(pixmap, planemask)) + if (!glamor_set_planemask(pixmap, planemask)) { + glamor_fallback("unsupported planemask %lx\n", planemask); goto fail; + } glamor_set_alu(alu); - glUseProgramObjectARB(glamor_priv->tile_prog); glActiveTexture(GL_TEXTURE0); diff --git a/hw/kdrive/ephyr/ephyr_glamor.c b/hw/kdrive/ephyr/ephyr_glamor.c index 027cfc52f..53bfbb995 100644 --- a/hw/kdrive/ephyr/ephyr_glamor.c +++ b/hw/kdrive/ephyr/ephyr_glamor.c @@ -45,7 +45,7 @@ ephyr_glamor_init(ScreenPtr screen) ephyr_glamor_host_create_context(kd_screen); - glamor_init(screen, 0); + glamor_init(screen, GLAMOR_HOSTX); return TRUE; } diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index 665cd0aea..d0432b31e 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -113,8 +113,7 @@ glamor_resize(ScrnInfoPtr scrn, int width, int height) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); - glamor_set_pixmap_texture(screen->GetScreenPixmap(screen), - width, height, texture); + glamor_set_screen_pixmap_texture(screen, width, height, texture); glamor->root = image; scrn->virtualX = width; scrn->virtualY = height;